From 7dd1233346d70bc1c48b67af0e9e462306d7f10d Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Tue, 27 Feb 2018 22:19:19 +0000 Subject: [PATCH] No longer treat EditSubsetMode as a singleton but instead instantiate it at the application/session level --- CHANGES.md | 3 +++ glue/app/qt/application.py | 4 ++-- glue/app/qt/edit_subset_mode_toolbar.py | 14 +++++++------- glue/app/qt/layer_tree_widget.py | 8 +++++--- glue/app/qt/tests/test_layer_tree_widget.py | 15 ++++++--------- glue/conftest.py | 6 ------ glue/core/application_base.py | 1 - glue/core/command.py | 2 +- glue/core/edit_subset_mode.py | 1 - glue/core/session.py | 6 +++--- glue/viewers/custom/qt/custom_viewer.py | 6 ++++-- .../histogram/qt/tests/test_data_viewer.py | 2 +- glue/viewers/image/qt/mouse_mode.py | 4 ++-- glue/viewers/image/qt/tests/test_data_viewer.py | 2 +- glue/viewers/scatter/qt/tests/test_data_viewer.py | 4 ++-- glue/viewers/table/qt/data_viewer.py | 2 +- glue/viewers/table/qt/tests/test_data_viewer.py | 2 +- 17 files changed, 39 insertions(+), 43 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3ba09e07c..0349c39d4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -60,6 +60,9 @@ v0.13.0 (unreleased) * Remember last session filename and filter used. [#1537] +* EditSubsetMode is now no longer a singleton class and is + instead instantiated at the Application/Session level. [#1538] + v0.12.4 (unreleased) -------------------- diff --git a/glue/app/qt/application.py b/glue/app/qt/application.py index a68b04696..e029fb5bb 100644 --- a/glue/app/qt/application.py +++ b/glue/app/qt/application.py @@ -275,7 +275,7 @@ def _setup_ui(self): self.setCentralWidget(self._ui) self._ui.tabWidget.setTabBar(GlueTabBar()) - lw = LayerTreeWidget() + lw = LayerTreeWidget(session=self._session) lw.set_checkable(False) self._vb = QtWidgets.QVBoxLayout() self._vb.setContentsMargins(0, 0, 0, 0) @@ -358,7 +358,7 @@ def _setup_ui(self): # Selection mode toolbar - tbar = EditSubsetModeToolBar() + tbar = EditSubsetModeToolBar(parent=self) self._mode_toolbar = tbar self.addToolBar(self._mode_toolbar) diff --git a/glue/app/qt/edit_subset_mode_toolbar.py b/glue/app/qt/edit_subset_mode_toolbar.py index eb345c4ad..96cfc95f8 100644 --- a/glue/app/qt/edit_subset_mode_toolbar.py +++ b/glue/app/qt/edit_subset_mode_toolbar.py @@ -8,11 +8,6 @@ from glue.utils import nonpartial -def set_mode(mode): - edit_mode = EditSubsetMode() - edit_mode.mode = mode - - class EditSubsetModeToolBar(QtWidgets.QToolBar): def __init__(self, title="Subset Update Mode", parent=None): @@ -30,7 +25,8 @@ def __init__(self, title="Subset Update Mode", parent=None): self._group = QtWidgets.QActionGroup(self) self._modes = {} self._add_actions() - self._modes[EditSubsetMode().mode].trigger() + self._edit_subset_mode = self.parent()._session.edit_subset_mode + self._modes[self._edit_subset_mode.mode].trigger() self._backup_mode = None spacer = QtWidgets.QWidget() @@ -41,6 +37,10 @@ def __init__(self, title="Subset Update Mode", parent=None): self.addWidget(spacer) def _make_mode(self, name, tip, icon, mode): + + def set_mode(mode): + self._edit_subset_mode.mode = mode + a = action(name, self, tip, icon) a.setCheckable(True) a.triggered.connect(nonpartial(set_mode, mode)) @@ -74,7 +74,7 @@ def set_mode(self, mode): except KeyError: raise KeyError("Unrecognized mode: %s" % mode) - self._backup_mode = self._backup_mode or EditSubsetMode().mode + self._backup_mode = self._backup_mode or self._edit_subset_mode.mode self._modes[mode].trigger() # mode class to action def unset_mode(self): diff --git a/glue/app/qt/layer_tree_widget.py b/glue/app/qt/layer_tree_widget.py index f0b30e153..89881c1c7 100644 --- a/glue/app/qt/layer_tree_widget.py +++ b/glue/app/qt/layer_tree_widget.py @@ -10,7 +10,7 @@ from qtpy import QtCore, QtWidgets, QtGui from qtpy.QtCore import Qt -from glue.core.edit_subset_mode import AndMode, OrMode, XorMode, AndNotMode, EditSubsetMode +from glue.core.edit_subset_mode import AndMode, OrMode, XorMode, AndNotMode from glue.config import layer_action from glue import core from glue.dialogs.link_editor.qt import LinkEditor @@ -448,10 +448,12 @@ class LayerTreeWidget(QtWidgets.QMainWindow, HubListener): it isn't attached to a hub, interactions may not propagate properly. """ - def __init__(self, parent=None): + def __init__(self, session=None, parent=None): super(LayerTreeWidget, self).__init__(parent) + self.session = session + self.ui = load_ui('layer_tree_widget.ui', None, directory=os.path.dirname(__file__)) self.setCentralWidget(self.ui) @@ -521,7 +523,7 @@ def _update_edit_subset(self): """ Update edit subsets to match current selection """ - mode = EditSubsetMode() + mode = self.session.edit_subset_mode mode.edit_subset = [s for s in self.selected_layers() if isinstance(s, core.SubsetGroup)] def _create_component(self): diff --git a/glue/app/qt/tests/test_layer_tree_widget.py b/glue/app/qt/tests/test_layer_tree_widget.py index 65d1a9955..87a15a645 100644 --- a/glue/app/qt/tests/test_layer_tree_widget.py +++ b/glue/app/qt/tests/test_layer_tree_widget.py @@ -4,16 +4,12 @@ from mock import MagicMock, patch -from qtpy.QtCore import Qt -from qtpy.QtTest import QTest from qtpy import QtWidgets from glue import core -from glue.utils.qt import get_qapp from glue.tests import example_data -from glue.core.edit_subset_mode import EditSubsetMode +from glue.core.session import Session -from ..layer_tree_widget import (LayerTreeWidget, Clipboard, - PlotAction, DeleteAction) +from ..layer_tree_widget import LayerTreeWidget, Clipboard, PlotAction class TestLayerTree(object): @@ -24,7 +20,8 @@ def setup_method(self, method): self.data = example_data.test_data() self.collect = core.data_collection.DataCollection(list(self.data)) self.hub = self.collect.hub - self.widget = LayerTreeWidget() + self.session = Session(data_collection=self.collect, hub=self.hub) + self.widget = LayerTreeWidget(session=self.session) self.win = QtWidgets.QMainWindow() self.win.setCentralWidget(self.widget) self.widget.setup(self.collect) @@ -197,23 +194,23 @@ def test_clear_subset_group(self): assert sub.subset_state is not dummy_state def test_single_selection_updates_editable(self): - mode = EditSubsetMode() self.widget.bind_selection_to_edit_subset() self.add_layer() grp1 = self.collect.new_subset_group() grp2 = self.collect.new_subset_group() + mode = self.session.edit_subset_mode assert mode.edit_subset[0] is not grp1 self.select_layers(grp1) assert mode.edit_subset[0] is grp1 def test_multi_selection_updates_editable(self): """Selection disables edit_subset for all other data""" - mode = EditSubsetMode() self.widget.bind_selection_to_edit_subset() self.add_layer() self.add_layer() grps = [self.collect.new_subset_group() for _ in range(3)] self.select_layers(*grps[:2]) + mode = self.session.edit_subset_mode assert grps[0] in mode.edit_subset assert grps[1] in mode.edit_subset assert grps[2] not in mode.edit_subset diff --git a/glue/conftest.py b/glue/conftest.py index df1b2167f..0938f4116 100644 --- a/glue/conftest.py +++ b/glue/conftest.py @@ -14,12 +14,6 @@ def pytest_addoption(parser): help="don't skip any tests with optional dependencies") -def pytest_runtest_setup(item): - mode = EditSubsetMode() - mode.mode = ReplaceMode - mode.edit_subset = [] - - def pytest_runtest_teardown(item, nextitem): sys.stderr = STDERR_ORIGINAL diff --git a/glue/core/application_base.py b/glue/core/application_base.py index 8b1f0a222..e82203cfb 100644 --- a/glue/core/application_base.py +++ b/glue/core/application_base.py @@ -55,7 +55,6 @@ def __init__(self, data_collection=None, session=None): self._session = Session(data_collection=self._data, application=self) - EditSubsetMode().data_collection = self._data self._hub = self._session.hub self._cmds = self._session.command_stack self._cmds.add_callback(lambda x: self._update_undo_redo_enabled()) diff --git a/glue/core/command.py b/glue/core/command.py index 364e9b4d3..95f544921 100644 --- a/glue/core/command.py +++ b/glue/core/command.py @@ -297,7 +297,7 @@ def do(self, session): for subset in data.subsets: self.old_states[subset] = subset.subset_state - mode = EditSubsetMode() + mode = session.edit_subset_mode mode.update(self.data_collection, self.subset_state) def undo(self, session): diff --git a/glue/core/edit_subset_mode.py b/glue/core/edit_subset_mode.py index 6338ee9ec..3126bde99 100644 --- a/glue/core/edit_subset_mode.py +++ b/glue/core/edit_subset_mode.py @@ -19,7 +19,6 @@ from glue.utils import as_list -@singleton class EditSubsetMode(object): """ Implements how new SubsetStates modify the edit_subset state diff --git a/glue/core/session.py b/glue/core/session.py index d58610ae8..bb6572e7f 100644 --- a/glue/core/session.py +++ b/glue/core/session.py @@ -2,6 +2,7 @@ from glue.core.command import CommandStack from glue.core.data_collection import DataCollection +from glue.core.edit_subset_mode import EditSubsetMode class Session(object): @@ -17,6 +18,5 @@ def __init__(self, application=None, data_collection=None, self.command_stack = command_stack or CommandStack() self.command_stack.session = self - # set the global data_collection for subset updates - from glue.core.edit_subset_mode import EditSubsetMode - EditSubsetMode().data_collection = self.data_collection + self.edit_subset_mode = EditSubsetMode() + self.edit_subset_mode.data_collection = self.data_collection diff --git a/glue/viewers/custom/qt/custom_viewer.py b/glue/viewers/custom/qt/custom_viewer.py index 9aae73bef..440a08362 100644 --- a/glue/viewers/custom/qt/custom_viewer.py +++ b/glue/viewers/custom/qt/custom_viewer.py @@ -838,6 +838,7 @@ class CustomClient(GenericMplClient): def __init__(self, *args, **kwargs): self._coordinator = kwargs.pop('coordinator') kwargs.setdefault('axes_factory', self._coordinator.create_axes) + self.session = kwargs.pop('session', None) super(CustomClient, self).__init__(*args, **kwargs) self._coordinator.axes = self.axes @@ -856,7 +857,7 @@ def apply_roi(self, roi): s = self._coordinator._build_subset_state(roi=roi) if s: - EditSubsetMode().update(self.collect, s, focus_data=focus) + self.session.edit_subset_mode.update(self.collect, s, focus_data=focus) def _update_layer(self, layer): for artist in self.artists[layer]: @@ -885,7 +886,8 @@ def __init__(self, session, parent=None): self.client = CustomClient(self._data, self.central_widget.canvas.fig, layer_artist_container=self._layer_artist_container, - coordinator=self._coordinator) + coordinator=self._coordinator, + session=session) self.statusBar().setSizeGripEnabled(False) self._update_artists = [] diff --git a/glue/viewers/histogram/qt/tests/test_data_viewer.py b/glue/viewers/histogram/qt/tests/test_data_viewer.py index 4f352b759..b7b9a9740 100644 --- a/glue/viewers/histogram/qt/tests/test_data_viewer.py +++ b/glue/viewers/histogram/qt/tests/test_data_viewer.py @@ -511,7 +511,7 @@ def test_apply_roi_single(self): # messages regarding subset updates (this occurred when multiple) # datasets were present. - layer_tree = LayerTreeWidget() + layer_tree = LayerTreeWidget(session=self.session) layer_tree.set_checkable(False) layer_tree.setup(self.data_collection) layer_tree.bind_selection_to_edit_subset() diff --git a/glue/viewers/image/qt/mouse_mode.py b/glue/viewers/image/qt/mouse_mode.py index 8d7c605ec..b4851fc7b 100644 --- a/glue/viewers/image/qt/mouse_mode.py +++ b/glue/viewers/image/qt/mouse_mode.py @@ -26,8 +26,8 @@ def __init__(self, viewer, **kwargs): super(RoiClickAndDragMode, self).__init__(viewer, **kwargs) self._viewer = viewer - self._dc = self._viewer.state.data_collection - self._edit_subset_mode = EditSubsetMode() + self._dc = viewer.state.data_collection + self._edit_subset_mode = viewer.session.edit_subset_mode self._roi = None self._subset = None diff --git a/glue/viewers/image/qt/tests/test_data_viewer.py b/glue/viewers/image/qt/tests/test_data_viewer.py index a9076d4cc..0431bead1 100644 --- a/glue/viewers/image/qt/tests/test_data_viewer.py +++ b/glue/viewers/image/qt/tests/test_data_viewer.py @@ -298,7 +298,7 @@ def test_apply_roi_single(self): # messages regarding subset updates (this occurred when multiple) # datasets were present. - layer_tree = LayerTreeWidget() + layer_tree = LayerTreeWidget(session=self.session) layer_tree.set_checkable(False) layer_tree.setup(self.data_collection) layer_tree.bind_selection_to_edit_subset() diff --git a/glue/viewers/scatter/qt/tests/test_data_viewer.py b/glue/viewers/scatter/qt/tests/test_data_viewer.py index 705d9806e..706d36d1a 100644 --- a/glue/viewers/scatter/qt/tests/test_data_viewer.py +++ b/glue/viewers/scatter/qt/tests/test_data_viewer.py @@ -366,7 +366,7 @@ def test_apply_roi_single(self): # messages regarding subset updates (this occurred when multiple) # datasets were present. - layer_tree = LayerTreeWidget() + layer_tree = LayerTreeWidget(session=self.session) layer_tree.set_checkable(False) layer_tree.setup(self.data_collection) layer_tree.bind_selection_to_edit_subset() @@ -529,7 +529,7 @@ def test_datetime64_support(self, tmpdir): assert self.viewer.axes.get_ylim() == (719348.0, 719678.0) # Apply an ROI selection in plotting coordinates - edit = EditSubsetMode() + edit = self.session.edit_subset_mode edit.edit_subset = [] roi = CircularROI(xc=719463, yc=719563, radius=200) self.viewer.apply_roi(roi) diff --git a/glue/viewers/table/qt/data_viewer.py b/glue/viewers/table/qt/data_viewer.py index 3e2bc9f71..400f6d98e 100644 --- a/glue/viewers/table/qt/data_viewer.py +++ b/glue/viewers/table/qt/data_viewer.py @@ -217,7 +217,7 @@ def finalize_selection(self, clear=True): model = self.ui.table.selectionModel() selected_rows = [self.model.order[x.row()] for x in model.selectedRows()] subset_state = ElementSubsetState(indices=selected_rows, data=self.data) - mode = EditSubsetMode() + mode = self.session.edit_subset_mode mode.update(self._data, subset_state, focus_data=self.data) if clear: # We block the signals here to make sure that we don't update diff --git a/glue/viewers/table/qt/tests/test_data_viewer.py b/glue/viewers/table/qt/tests/test_data_viewer.py index f00031f2e..6189c5e61 100644 --- a/glue/viewers/table/qt/tests/test_data_viewer.py +++ b/glue/viewers/table/qt/tests/test_data_viewer.py @@ -99,7 +99,7 @@ def test_table_widget(tmpdir): widget = gapp.new_data_viewer(TableViewer) widget.add_data(d) - subset_mode = EditSubsetMode() + subset_mode = gapp._session._edit_subset_mode # Create two subsets