-
Notifications
You must be signed in to change notification settings - Fork 153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve loading of plugins #590
Conversation
At the moment, we have a bit of a mix of ways to load plugins:
Neither are ideal in my opinion. The first is not ideal because the main glue code should not have to know about plugins, so it's up to the PV slicer and Spectrum to declare themselves The second is not ideal either because at the moment there is no way to tell glue to NOT load those plugins. One solution I've been thinking about is to instead have a registry of plugins, which would be identified by a string giving the module name, like sphinx does with extensions. The user could then add/remove these in their own However, this is still not perfect, because the question is, at what stage should the plugins be loaded? That is, the coordinate_helper plugin is needed for stuff in
Ok, so one option is:
An alternative option I just thought of is:
This avoids the creation of a new registry, and allows loading as needed. @ChrisBeaumont - sorry for the brain dump, but do you have any thoughts on this? |
I'm going to try and whip up a PR based on my alternative suggestion since I think it would be easy, just to see. |
I've attached pseudo code here to demonstrate what I think is my preferred option for now. |
Agreed that this should be standardized somehow. If at all possible we should prevent the user or plugin developer from having to worry about import logic. The registry definitely feels like the right place for all hooks to live, and ideally the registry API is a single hook (ie the decorator/ I wonder if each registry group should define when it should be loaded? |
@ChrisBeaumont - see attached code, where the plugins are added on a per-registry basis, and each registry loads its own plugins only when |
This works nicely by the way - the ginga widget is only loaded at the point of dragging a dataset into the main window! The exporters are loaded sooner because that registry must be accessed sooner. |
However, the plugins are registered before the user's |
One final thing - from the plugin developer's point of view, they just need to define a |
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') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So is the idea that someone who has their own plugin would manually call the appropriate registry.add_plugin
from their config.py
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this approach, yes, or they could directly load it (see below)
Adding an item to a registry using Registering a plugin Loading a plugin means actually adding the proper entries to a registry (note that when the registries load plugins, they remove the plugin entry, so they are loaded only once) Registries can contain two kinds of things - normal members entries (in To summarize what happens inside glue: as soon as glue is started up, we register all built-in plugins internally using In fact, what I've ended up doing is very close to what sphinx does:
https://github.com/glue-viz/glue/blob/master/doc/conf.py#L32 (equivalent to what I call registering the plugin)
The difference is that in Sphinx, all plugins are loaded at the start. If we don't want that to happen, then we need to make them be loaded as needed, which is why plugins need to be registered on a per-registry basis. However, the terminology is confusing (registering plugins with registries...) so an alternative API is to simply have registries have a
What do you think? The alternative would be to have a single list of plugins like sphinx, so e.g.:
but then it would be hard to determine when plugins should be loaded and we might end up importing qt straight up. However, we could allow both - that is, have a general purpose plugins registry for when users don't care if it's loaded straight away, and then allow plugins to also be added on a per-registry basis. Then we get the best of both world. [as a side note I think we could also in addition rename What do you think? |
This sounds like the essential distinction between a normal registry item and a plugin -- the plugin mechanism exists solely to add things to a registry in the future. I think the names I like using Once we decide on an API, this feature should be added to the sphinx docs as well. |
@ChrisBeaumont - I agree with all your points. It's possible to write plug-in functionality and load it immediately not using lazy loading, so I agree the terminology was wrong. I have renamed Note that currently I still need to make the spectrum tool and PV slicing tool use this. As a side note, should the registry of models to fit live in the spectrum tool plugin? |
@@ -35,6 +34,7 @@ class Registry(object): | |||
|
|||
def __init__(self): | |||
self._members = [] | |||
self._plugins = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might as well call this something like lazy_members
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, should this then just be a public attribute and we get rid of lazy_add
, so that users can append but also remove from lazy_members
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh sorry -- I meant to type _lazy_members
. I don't have any opinions on whether it should be public or private though.
Much clearer to me know! looks good |
Thanks for the review! I've now moved the PV slicer and Spectrum tool to use this too, so if it passes, I'll go ahead and merge :) |
In #578 and #585, I tried to improve the loading of plugins so that the loading itself is done from the plugin directories, and the only thing outside is that
GlueApplication
callsload_all_plugins
. I'm still not quite happy with it, so this issue is meant to be a reminder that we need to improve this a little.In particular, for example the link helpers in #578 can get registered just by importing the plugins directory, whereas the ginga plugin has to be explicitly loaded, which doesn't seem very consistent.