Skip to content

Commit ccf74f3

Browse files
authored
fix: fix remove_lut_view on unowned LUTViews (#247)
* fix: fix remove_lut_view on unowned LUTViews * more robust test
1 parent e745716 commit ccf74f3

4 files changed

Lines changed: 25 additions & 0 deletions

File tree

src/ndv/views/_jupyter/_array_view.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,8 @@ def add_lut_view(self, channel: ChannelKey) -> JupyterLUTView:
562562

563563
def remove_lut_view(self, view: LUTView) -> None:
564564
"""Remove a LUT view from the viewer."""
565+
if view not in self._luts.values():
566+
return
565567
view = cast("JupyterLUTView", view)
566568
layout = self._luts_box
567569
layout.children = tuple(

src/ndv/views/_qt/_array_view.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,8 @@ def add_lut_view(self, channel: ChannelKey) -> QLUTView:
844844
return view
845845

846846
def remove_lut_view(self, view: LUTView) -> None:
847+
if view not in self._luts.values():
848+
return
847849
self._qwidget.luts.removeWidget(cast("QLUTView", view).frontend_widget())
848850

849851
def _on_channel_mode_changed(self, text: str) -> None:

src/ndv/views/_wx/_array_view.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,9 @@ def add_histogram(self, channel: ChannelKey, widget: HistogramCanvas) -> None:
782782
self._wxwidget.Layout()
783783

784784
def remove_lut_view(self, lut: LUTView) -> None:
785+
if lut not in self._luts.values():
786+
return
787+
785788
# Find the channel key for this LUT view
786789
channel_to_remove = next(
787790
(channel for channel, view in self._luts.items() if view == lut), None

tests/test_controller.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,24 @@ def test_data_replacement_with_stale_index() -> None:
648648
ctrl._join()
649649

650650

651+
@no_type_check
652+
@_patch_views
653+
def test_remove_lut_view_with_non_gui_view() -> None:
654+
"""remove_lut_view should handle non-GUI LUTViews (e.g. ImageHandle).
655+
656+
See https://github.com/pyapp-kit/ndv/issues/138
657+
"""
658+
ctrl = ArrayViewer()
659+
ctrl._async = False
660+
ctrl.data = np.random.randint(0, 255, size=(10, 10), dtype="uint8")
661+
662+
lut_ctrl = next(iter(ctrl._lut_controllers.values()))
663+
# lut_views contains both the GUI LUTView and the ImageHandle
664+
for view in lut_ctrl.lut_views:
665+
# This should not raise, even for non-GUI views like ImageHandle
666+
ctrl._view.remove_lut_view(view)
667+
668+
651669
@no_type_check
652670
@_patch_views
653671
def test_user_current_index_preserved_on_init() -> None:

0 commit comments

Comments
 (0)