From 20a5df58fd16040a2ab997f1732548bbcce24a27 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Tue, 17 Mar 2015 23:09:59 +0100 Subject: [PATCH 1/7] Allow plugins to be registered with registries then loaded when needed --- glue/__init__.py | 5 ++++- glue/config.py | 14 ++++++++++++++ glue/plugins/__init__.py | 14 +++++++++----- glue/qt/glue_application.py | 4 ---- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/glue/__init__.py b/glue/__init__.py index 28d6d8fd2..6581de8b0 100644 --- a/glue/__init__.py +++ b/glue/__init__.py @@ -118,13 +118,16 @@ def make_selector_func(roi): from .qt.custom_viewer import CustomViewer return CustomViewer.create_new_subclass(name, **kwargs) +# Register default plugins (but don't load them) +from .plugins import register_plugins +register_plugins() + # Load user's configuration file from .config import load_configuration env = load_configuration() from .qglue import qglue - from .version import __version__ def test(no_optional_skip=False): diff --git a/glue/config.py b/glue/config.py index eb7769f76..7b56a5174 100644 --- a/glue/config.py +++ b/glue/config.py @@ -35,6 +35,7 @@ class Registry(object): def __init__(self): self._members = [] + self._plugins = [] self._loaded = False @property @@ -42,6 +43,7 @@ def members(self): """ A list of the members in the registry. The return value is a list. The contents of the list are specified in each subclass""" + self._load_plugins() if not self._loaded: self._members = self.default_members() + self._members self._loaded = True @@ -57,6 +59,18 @@ def add(self, value): """ Add a new item to the registry """ self._members.append(value) + def add_plugin(self, value): + """ + Add a plugin that will populate this registry + """ + self._plugins.append(value) + + def _load_plugins(self): + from .plugins import load_plugin + while self._plugins: + plugin = self._plugins.pop() + load_plugin(plugin) + def __iter__(self): return iter(self.members) diff --git a/glue/plugins/__init__.py b/glue/plugins/__init__.py index 3ef21f8b5..b36cebbd9 100644 --- a/glue/plugins/__init__.py +++ b/glue/plugins/__init__.py @@ -3,10 +3,14 @@ from . import ginga_viewer -def load_all_plugins(): +def register_plugins(): + from ..config import qt_client + qt_client.register_plugin('glue.plugins.ginga_viewer') + + +def load_plugin(plugin): """ - Load built-in plugins + Load plugin referred to by name 'plugin' """ - - from .ginga_viewer import load_ginga_viewer_plugin - load_ginga_viewer_plugin() + # TODO: load plugin here + print("LOADING", plugin) \ No newline at end of file diff --git a/glue/qt/glue_application.py b/glue/qt/glue_application.py index 8caa70be4..5cc57761a 100644 --- a/glue/qt/glue_application.py +++ b/glue/qt/glue_application.py @@ -179,10 +179,6 @@ def __init__(self, data_collection=None, session=None): Application.__init__(self, data_collection=data_collection, session=session) - # Load all plugins - from ..plugins import load_all_plugins - load_all_plugins() - self.app = get_qapp() self.setWindowIcon(self.app.windowIcon()) From 1e8f02365384a9ec0b00b67e8fc282a8a5aaa749 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Tue, 17 Mar 2015 23:17:20 +0100 Subject: [PATCH 2/7] More tidying up --- glue/plugins/__init__.py | 11 +++++++---- glue/plugins/export_d3po.py | 7 +++++-- glue/plugins/export_plotly.py | 11 +++++++---- glue/plugins/ginga_viewer/__init__.py | 2 +- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/glue/plugins/__init__.py b/glue/plugins/__init__.py index b36cebbd9..4f4ae6e70 100644 --- a/glue/plugins/__init__.py +++ b/glue/plugins/__init__.py @@ -4,13 +4,16 @@ def register_plugins(): - from ..config import qt_client - qt_client.register_plugin('glue.plugins.ginga_viewer') + from ..config import qt_client, exporters + qt_client.add_plugin('glue.plugins.ginga_viewer') + exporters.add_plugin('glue.plugins.export_d3po') + exporters.add_plugin('glue.plugins.export_plotly') def load_plugin(plugin): """ Load plugin referred to by name 'plugin' """ - # TODO: load plugin here - print("LOADING", plugin) \ No newline at end of file + import importlib + module = importlib.import_module(plugin) + module.load_plugin() diff --git a/glue/plugins/export_d3po.py b/glue/plugins/export_d3po.py index 9ffc4cd1a..82f74deca 100644 --- a/glue/plugins/export_d3po.py +++ b/glue/plugins/export_d3po.py @@ -3,7 +3,6 @@ import json import os -from ..config import exporters from ..qt.widgets import ScatterWidget, HistogramWidget from ..core import Subset @@ -247,7 +246,11 @@ def launch(path): webbrowser.open('http://0.0.0.0:%i' % PORT) -exporters.add('D3PO', save_d3po, can_save_d3po, outmode='directory') +def load_plugin(): + from ..logger import logger + from ..config import exporters + exporters.add('D3PO', save_d3po, can_save_d3po, outmode='directory') + logger.info("Loaded d3po exporter plugin") HTML = """ diff --git a/glue/plugins/export_plotly.py b/glue/plugins/export_plotly.py index 78f3d129d..a15592c5b 100644 --- a/glue/plugins/export_plotly.py +++ b/glue/plugins/export_plotly.py @@ -6,7 +6,6 @@ except ImportError: plotly = None -from ..config import exporters, settings from ..qt.widgets import ScatterWidget, HistogramWidget from ..core.data import CategoricalComponent from ..core.layout import Rectangle, snap_to_grid @@ -305,6 +304,10 @@ def save_plotly(application, label): plotly.sign_in(user, apikey) plotly.plot(*args, **kwargs) -exporters.add('Plotly', save_plotly, can_save_plotly, outmode='label') -settings.add('PLOTLY_USER', 'Glue') -settings.add('PLOTLY_APIKEY', 't24aweai14') +def load_plugin(): + from ..logger import logger + from ..config import exporters, settings + exporters.add('Plotly', save_plotly, can_save_plotly, outmode='label') + settings.add('PLOTLY_USER', 'Glue') + settings.add('PLOTLY_APIKEY', 't24aweai14') + logger.info("Loaded plotly exporter plugin") diff --git a/glue/plugins/ginga_viewer/__init__.py b/glue/plugins/ginga_viewer/__init__.py index cf197fa21..a84a67fe0 100644 --- a/glue/plugins/ginga_viewer/__init__.py +++ b/glue/plugins/ginga_viewer/__init__.py @@ -1,4 +1,4 @@ -def load_ginga_viewer_plugin(): +def load_plugin(): from ...logger import logger try: from .qt_widget import GingaWidget From 1254236c6aeb570a47c8ce713efc832f6e640f34 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 18 Mar 2015 21:36:21 +0100 Subject: [PATCH 3/7] Rename add_plugin to lazy_add, and load_plugin to setup --- glue/config.py | 8 +++++--- glue/plugins/__init__.py | 11 +++++++---- glue/plugins/export_d3po.py | 2 +- glue/plugins/export_plotly.py | 2 +- glue/plugins/ginga_viewer/__init__.py | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/glue/config.py b/glue/config.py index 7b56a5174..e5a56f16d 100644 --- a/glue/config.py +++ b/glue/config.py @@ -56,12 +56,14 @@ def default_members(self): return [] def add(self, value): - """ Add a new item to the registry """ + """ + Add a new item to the registry. + """ self._members.append(value) - def add_plugin(self, value): + def lazy_add(self, value): """ - Add a plugin that will populate this registry + Add a reference to a plugin which will be loaded when needed. """ self._plugins.append(value) diff --git a/glue/plugins/__init__.py b/glue/plugins/__init__.py index 4f4ae6e70..a24c01d80 100644 --- a/glue/plugins/__init__.py +++ b/glue/plugins/__init__.py @@ -5,9 +5,9 @@ def register_plugins(): from ..config import qt_client, exporters - qt_client.add_plugin('glue.plugins.ginga_viewer') - exporters.add_plugin('glue.plugins.export_d3po') - exporters.add_plugin('glue.plugins.export_plotly') + qt_client.lazy_add('glue.plugins.ginga_viewer') + exporters.lazy_add('glue.plugins.export_d3po') + exporters.lazy_add('glue.plugins.export_plotly') def load_plugin(plugin): @@ -16,4 +16,7 @@ def load_plugin(plugin): """ import importlib module = importlib.import_module(plugin) - module.load_plugin() + if hasattr(module, 'setup'): + module.setup() + else: + raise AttributeError("Plugin {0} should define 'setup' function".format(plugin)) diff --git a/glue/plugins/export_d3po.py b/glue/plugins/export_d3po.py index 82f74deca..8157848bf 100644 --- a/glue/plugins/export_d3po.py +++ b/glue/plugins/export_d3po.py @@ -246,7 +246,7 @@ def launch(path): webbrowser.open('http://0.0.0.0:%i' % PORT) -def load_plugin(): +def setup(): from ..logger import logger from ..config import exporters exporters.add('D3PO', save_d3po, can_save_d3po, outmode='directory') diff --git a/glue/plugins/export_plotly.py b/glue/plugins/export_plotly.py index a15592c5b..2ed2a150b 100644 --- a/glue/plugins/export_plotly.py +++ b/glue/plugins/export_plotly.py @@ -304,7 +304,7 @@ def save_plotly(application, label): plotly.sign_in(user, apikey) plotly.plot(*args, **kwargs) -def load_plugin(): +def setup(): from ..logger import logger from ..config import exporters, settings exporters.add('Plotly', save_plotly, can_save_plotly, outmode='label') diff --git a/glue/plugins/ginga_viewer/__init__.py b/glue/plugins/ginga_viewer/__init__.py index a84a67fe0..a602abe5b 100644 --- a/glue/plugins/ginga_viewer/__init__.py +++ b/glue/plugins/ginga_viewer/__init__.py @@ -1,4 +1,4 @@ -def load_plugin(): +def setup(): from ...logger import logger try: from .qt_widget import GingaWidget From 5dd86f7dd4695145ba0af889be364126168cb71a Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 18 Mar 2015 23:10:29 +0100 Subject: [PATCH 4/7] Added documentation about plugins --- doc/gui_guide/configuration.rst | 1 - doc/python_guide/customization.rst | 150 +++++++++++++++++++++++------ glue/config.py | 7 +- 3 files changed, 126 insertions(+), 32 deletions(-) diff --git a/doc/gui_guide/configuration.rst b/doc/gui_guide/configuration.rst index c03befb43..028716be6 100644 --- a/doc/gui_guide/configuration.rst +++ b/doc/gui_guide/configuration.rst @@ -24,7 +24,6 @@ To obtain a fresh ``config.py`` file to edit, run the command line program:: Which will create a new file at ``~/.glue/config.py`` - Example Usage: Custom Link Functions ------------------------------------ diff --git a/doc/python_guide/customization.rst b/doc/python_guide/customization.rst index 34467792a..7b8fc75df 100644 --- a/doc/python_guide/customization.rst +++ b/doc/python_guide/customization.rst @@ -2,26 +2,48 @@ Customizing Glue ================ -There are a few ways to customize the Glue UI -with configuration files and plugins. +There are a few ways to customize the Glue UI with configuration files and +plugins. Configuration Files ------------------- -Each time Glue starts, it looks for and executes a configuration file. This is a normal python script into which users can define or import new functions to link data, plug in their own visualization modules, set up logging, etc. +Each time Glue starts, it looks for and executes a configuration file. This +is a normal python script into which users can define or import new functions +to link data, plug in their own visualization modules, set up logging, etc. -The glue configuration file is called ``config.py``. Glue looks for this file in the following locations, in order: +The glue configuration file is called ``config.py``. Glue looks for this file +in the following locations, in order: * The current working directory * The path specified in the ``GLUERC`` environment variable, if present * The path ``.glue/config.py`` within the user's home directory +Registries +---------- + +Glue is written so as to allow users to easily register new plug-in data +viewers, tools, exporters, and more. Registering such plug-ins can be done +via *registries* located in the ``glue.config`` sub-package. Registries +include for example ``link_function``, ``data_factory``, ``colormaps``, and +so on. As demonstrated below, some registries can be used as decorators (see +e.g. `Adding Custom Link Functions`_) and for others you can add items using +the ``add`` method (see e.g. `Custom Colormaps`_). + +In the following sections, we show a few examples of registering new +functionality, and a full list of available registries is given in `Complete +list of registries`_. + Adding Custom Link Functions ---------------------------- .. _custom_links: -From the :ref:`Link Data Dialog `, you inform Glue how to convert between quantities among different data sets. You do this by selecting a translation function, and specifying which data attributes should be treated as inputs and outputs. You can use the configuration file to specify custom translation functions. Here's how: +From the :ref:`Link Data Dialog `, you inform Glue how +to convert between quantities among different data sets. You do this by +selecting a translation function, and specifying which data attributes should +be treated as inputs and outputs. You can use the configuration file to +specify custom translation functions. Here's how: .. literalinclude:: scripts/config_link_example.py @@ -30,14 +52,15 @@ Some remarks about this code: #. We provide a short summary of the function in the ``info`` keyword, and a list of ``output_labels``. Usually, only one quantity is returned, so ``output_labels`` has one element. #. Glue will always pass numpy arrays as inputs to a link function, and expects a numpy array (or a tuple of numpy arrays) as output -With this code in your configuration file, the ``deg_to_rad`` function is available in the ``Link Data`` dialog: +With this code in your configuration file, the ``deg_to_rad`` function is +available in the ``Link Data`` dialog: .. figure:: images/custom_link.png :align: center :width: 200px -This would allow you to link between two datasets with different conventions for specifying angles. - +This would allow you to link between two datasets with different conventions +for specifying angles. Custom Data Loaders ------------------- @@ -46,10 +69,10 @@ Custom Data Loaders Glue lets you create custom data loader functions, to use from within the GUI. -Here's a quick example: the default image loader in Glue -reads each color in an RGB image into 3 two-dimensional components. -Perhaps you want to be able to load these images into a single 3-dimensional -component called ``cube``. Here's how you could do this:: +Here's a quick example: the default image loader in Glue reads each color in +an RGB image into 3 two-dimensional components. Perhaps you want to be able +to load these images into a single 3-dimensional component called ``cube``. +Here's how you could do this:: from glue.config import data_factory from glue.core import Data @@ -68,12 +91,14 @@ Let's look at this line-by-line: * The `is_jpeg` function takes a filename and keywords as input, and returns True if a data factory can handle this file -* The ``@data_factory`` decorator is how Glue "finds" this function. - Its two arguments are a label, and the `is_jpeg` identifier function +* The ``@data_factory`` decorator is how Glue "finds" this function. Its two + arguments are a label, and the `is_jpeg` identifier function -* The first line in ``read_jpeg`` uses scikit-image to load an image file into a NumPy array. +* The first line in ``read_jpeg`` uses scikit-image to load an image file + into a NumPy array. -* The second line :ref:`constructs a Data object ` from this array, and returns the result. +* The second line :ref:`constructs a Data object ` from this + array, and returns the result. If you put this in your ``config.py`` file, you will see a new file type when loading data: @@ -82,15 +107,17 @@ file type when loading data: :align: center :width: 50% -If you open a file using this file type selection, Glue will pass -the path of this file to your function, and use the resulting Data -object. +If you open a file using this file type selection, Glue will pass the path of +this file to your function, and use the resulting Data object. -For more examples of custom data loaders, see the `example repository `_. +For more examples of custom data loaders, see the `example repository +`_. Custom Colormaps ---------------- -You can add additional matplotlib colormaps to Glue's image viewer by adding the following code into ``config.py``:: + +You can add additional matplotlib colormaps to Glue's image viewer by adding +the following code into ``config.py``:: from glue.config import colormaps from matplotlib.cm import Paired @@ -98,8 +125,9 @@ You can add additional matplotlib colormaps to Glue's image viewer by adding the Custom Subset Actions --------------------- -You can add menu items to run custom functions on subsets. -Use the following pattern in ``config..py``:: + +You can add menu items to run custom functions on subsets. Use the following +pattern in ``config..py``:: from glue.config import single_subset_action @@ -108,7 +136,75 @@ Use the following pattern in ``config..py``:: single_subset_action('Menu title', callback) -This menu item is available by right clicking on a subset -when a single subset is selected in the Data Collection window. Note -that you must select the subset specific to a particular Data set, -and not the parent Subset Group. \ No newline at end of file +This menu item is available by right clicking on a subset when a single +subset is selected in the Data Collection window. Note that you must select +the subset specific to a particular Data set, and not the parent Subset Group. + +Complete list of registries +--------------------------- + +A few registries have been demonstrated above, and a complete list of main +registries are listed below. All can be imported from ``glue.config`` - each +registry is an instance of a class, given in the second column, and which +provides more information about what the registry is and how it can be used. + +========================== ======================================================= +Registry name Registry class +========================== ======================================================= +``qt_client`` :class:`glue.config.QtClientRegistry` +``tool_registry`` :class:`glue.config.QtToolRegistry` +``data_factory`` :class:`glue.config.DataFactoryRegistry` +``link_function`` :class:`glue.config.LinkFunctionRegistry` +``link_helper`` :class:`glue.config.LinkHelperRegistry` +``colormaps`` :class:`glue.config.ColormapRegistry` +``exporters`` :class:`glue.config.ExporterRegistry` +``settings`` :class:`glue.config.SettingRegistry` +``fit_plugin`` :class:`glue.config.ProfileFitterRegistry` +``single_subset_action`` :class:`glue.config.SingleSubsetLayerActionRegistry` +========================== ======================================================= + +Deferring loading of plug-in functionality (advanced) +----------------------------------------------------- + +In some cases, you may want to defer the loading of your plugin until it is +actually needed. To do this: + +* Place the code for your plugin in a file or package that could be imported + from the ``config.py`` (but don't import it directly - it just has to be + importable) + +* Include a function called ``setup`` alongside the plugin, and this function + should contain code to actually add your custom tools to the appropriate + registries. + +* In ``config.py``, you can then add the plugin file or package to a registry + by using the ``lazy_add`` method and pass a string giving the name of the + package or sub-package containing the plugin. + +Imagine that you have created a data viewer ``MyQtViewer``. You could +directly register it using:: + + from glue.config import qt_client + qt_client.add(MyQtViewer) + +but if you want to defer the loading of the ``MyQtViewer`` class, you can +place the definition of ``MyQtViewer`` in a file called e.g. +``my_qt_viewer.py`` that is located in the same directory as your +``config.py`` file. This file should look something like:: + + class MyQtViewer(...): + ... + + def setup(): + from glue.config import qt_client + qt_client.add(MyQtViewer) + +then in ``config.py``, you can do:: + + from glue.config import qt_client + qt_client.lazy_add('my_qt_viewer') + +With this in place, the ``setup`` in your plugin will only get called if the +Qt data viewers are needed, but you will avoid unecessarily importing Qt if +you only want to access ``glue.core``. + diff --git a/glue/config.py b/glue/config.py index e5a56f16d..aee9e9521 100644 --- a/glue/config.py +++ b/glue/config.py @@ -11,11 +11,10 @@ __all__ = ['Registry', 'SettingRegistry', 'ExporterRegistry', 'ColormapRegistry', 'DataFactoryRegistry', 'QtClientRegistry', - 'LinkFunctionRegistry', 'LinkHelperRegistry', - 'ProfileFitterRegistry', + 'LinkFunctionRegistry', 'LinkHelperRegistry', 'QtToolRegistry', + 'SingleSubsetLayerActionRegistry', 'ProfileFitterRegistry', 'qt_client', 'data_factory', 'link_function', 'link_helper', - 'colormaps', - 'exporters', 'settings', 'fit_plugin', 'auto_refresh'] + 'colormaps', 'exporters', 'settings', 'fit_plugin', 'auto_refresh'] class Registry(object): From ac2b213cc38b970036f53e10a4f171632b3c7aaf Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 18 Mar 2015 23:37:13 +0100 Subject: [PATCH 5/7] =?UTF-8?q?Can=E2=80=99t=20use=20importlib=20as=20long?= =?UTF-8?q?=20as=20we=20support=20Python=202.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- glue/plugins/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/glue/plugins/__init__.py b/glue/plugins/__init__.py index a24c01d80..e16f3da34 100644 --- a/glue/plugins/__init__.py +++ b/glue/plugins/__init__.py @@ -1,6 +1,4 @@ -from . import export_d3po -from . import export_plotly -from . import ginga_viewer +import sys def register_plugins(): @@ -8,14 +6,17 @@ def register_plugins(): qt_client.lazy_add('glue.plugins.ginga_viewer') exporters.lazy_add('glue.plugins.export_d3po') exporters.lazy_add('glue.plugins.export_plotly') - + def load_plugin(plugin): """ Load plugin referred to by name 'plugin' """ - import importlib - module = importlib.import_module(plugin) + # When Python 2.6 is no longer supported, we can use: + # import importlib + # module = importlib.import_module(plugin) + __import__(plugin) + return sys.modules[plugin] if hasattr(module, 'setup'): module.setup() else: From 7b53f4b13f4dbd9bb32ab64efade1f68cffbebea Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Thu, 19 Mar 2015 00:22:24 +0100 Subject: [PATCH 6/7] Renamed _plugins to _lazy_members --- glue/config.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/glue/config.py b/glue/config.py index aee9e9521..3f5fd7fa1 100644 --- a/glue/config.py +++ b/glue/config.py @@ -34,7 +34,7 @@ class Registry(object): def __init__(self): self._members = [] - self._plugins = [] + self._lazy_members = [] self._loaded = False @property @@ -42,7 +42,7 @@ def members(self): """ A list of the members in the registry. The return value is a list. The contents of the list are specified in each subclass""" - self._load_plugins() + self._load_lazy_members() if not self._loaded: self._members = self.default_members() + self._members self._loaded = True @@ -64,12 +64,12 @@ def lazy_add(self, value): """ Add a reference to a plugin which will be loaded when needed. """ - self._plugins.append(value) + self._lazy_members.append(value) - def _load_plugins(self): + def _load_lazy_members(self): from .plugins import load_plugin - while self._plugins: - plugin = self._plugins.pop() + while self._lazy_members: + plugin = self._lazy_members.pop() load_plugin(plugin) def __iter__(self): From 238241d718eece62b96657f5ad9d5aba821938aa Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Thu, 19 Mar 2015 00:34:08 +0100 Subject: [PATCH 7/7] Make PV slicer and spectrum tool use new plugin lazy loading --- glue/config.py | 2 ++ glue/plugins/__init__.py | 4 +++- glue/plugins/tools/pv_slicer.py | 8 ++++++++ glue/plugins/tools/spectrum_tool.py | 8 ++++++++ glue/qt/widgets/image_widget.py | 4 +--- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/glue/config.py b/glue/config.py index 3f5fd7fa1..cc4462771 100644 --- a/glue/config.py +++ b/glue/config.py @@ -249,10 +249,12 @@ class QtToolRegistry(Registry): def __init__(self): self._members = {} + self._lazy_members = [] self._loaded = False @property def members(self): + self._load_lazy_members() if not self._loaded: defaults = self.default_members() for key in defaults: diff --git a/glue/plugins/__init__.py b/glue/plugins/__init__.py index e16f3da34..d18b8ca65 100644 --- a/glue/plugins/__init__.py +++ b/glue/plugins/__init__.py @@ -6,6 +6,8 @@ def register_plugins(): qt_client.lazy_add('glue.plugins.ginga_viewer') exporters.lazy_add('glue.plugins.export_d3po') exporters.lazy_add('glue.plugins.export_plotly') + exporters.lazy_add('glue.plugins.tools.pv_slicer') + exporters.lazy_add('glue.plugins.tools.spectrum_tool') def load_plugin(plugin): @@ -16,7 +18,7 @@ def load_plugin(plugin): # import importlib # module = importlib.import_module(plugin) __import__(plugin) - return sys.modules[plugin] + module = sys.modules[plugin] if hasattr(module, 'setup'): module.setup() else: diff --git a/glue/plugins/tools/pv_slicer.py b/glue/plugins/tools/pv_slicer.py index bb67d0559..9e5542f81 100644 --- a/glue/plugins/tools/pv_slicer.py +++ b/glue/plugins/tools/pv_slicer.py @@ -4,6 +4,14 @@ from ...qt.widgets.mpl_widget import defer_draw +def setup(): + from ...logger import logger + from ...config import tool_registry + from ...qt.widgets import ImageWidget + tool_registry.add(PVSlicerTool, widget_cls=ImageWidget) + logger.info("Loaded pv slicer plugin") + + class PVSlicerTool(object): def __init__(self, widget=None): diff --git a/glue/plugins/tools/spectrum_tool.py b/glue/plugins/tools/spectrum_tool.py index 19aa92f0e..d511cb9a9 100644 --- a/glue/plugins/tools/spectrum_tool.py +++ b/glue/plugins/tools/spectrum_tool.py @@ -33,6 +33,14 @@ from ...utils import drop_axis +def setup(): + from ...logger import logger + from ...config import tool_registry + from ...qt.widgets import ImageWidget + tool_registry.add(SpectrumTool, widget_cls=ImageWidget) + logger.info("Loaded spectrum tool plugin") + + class Extractor(object): # Warning: # Coordinate conversion is not well-defined if pix2world is not diff --git a/glue/qt/widgets/image_widget.py b/glue/qt/widgets/image_widget.py index 00ac0f53c..0e8bf8825 100644 --- a/glue/qt/widgets/image_widget.py +++ b/glue/qt/widgets/image_widget.py @@ -88,9 +88,7 @@ def make_toolbar(self): @staticmethod def _get_default_tools(): - from ...plugins.tools.pv_slicer import PVSlicerTool - from ...plugins.tools.spectrum_tool import SpectrumTool - return [PVSlicerTool, SpectrumTool] + return [] def _setup_tools(self): """