Allow sorting of Startup and ShutdownPlugins

This commit is contained in:
Gina Häußge 2015-09-04 15:01:35 +02:00
parent 44c76fa70b
commit 2a52b6d1a2
4 changed files with 38 additions and 13 deletions

View file

@ -152,7 +152,7 @@ def plugin_settings(plugin_key, defaults=None, get_preprocessors=None, set_prepr
return PluginSettings(settings(), plugin_key, defaults=defaults, get_preprocessors=get_preprocessors, set_preprocessors=set_preprocessors)
def call_plugin(types, method, args=None, kwargs=None, callback=None, error_callback=None):
def call_plugin(types, method, args=None, kwargs=None, callback=None, error_callback=None, sorting_context=None):
"""
Helper method to invoke the indicated ``method`` on all registered plugin implementations implementing the
indicated ``types``. Allows providing method arguments and registering callbacks to call in case of success
@ -198,7 +198,7 @@ def call_plugin(types, method, args=None, kwargs=None, callback=None, error_call
if kwargs is None:
kwargs = dict()
plugins = plugin_manager().get_implementations(*types)
plugins = plugin_manager().get_implementations(*types, sorting_context=sorting_context)
for plugin in plugins:
if hasattr(plugin, method):
try:

View file

@ -1046,7 +1046,7 @@ class PluginManager(object):
result[h[0]] = h[1]
return result
def get_implementations(self, *types):
def get_implementations(self, *types, **kwargs):
"""
Get all mixin implementations that implement *all* of the provided ``types``.
@ -1057,6 +1057,8 @@ class PluginManager(object):
list: A list of all found implementations
"""
sorting_context = kwargs.get("sorting_context", None)
result = None
for t in types:
@ -1067,10 +1069,26 @@ class PluginManager(object):
result = result.intersection(implementations)
if result is None:
return dict()
return [impl[1] for impl in result]
return []
def get_filtered_implementations(self, f, *types):
found_implementations = [impl[1] for impl in result]
if sorting_context is not None:
def sort_func(impl):
sorting_value = None
if isinstance(impl, SorteablePlugin):
try:
sorting_value = impl.get_sorting_key(sorting_context)
except:
self.logger.exception("Error while trying to retrieve sorting order for plugin {}".format(impl._identifier))
return sorting_value is None, sorting_value
found_implementations = sorted(found_implementations, key=sort_func)
return found_implementations
def get_filtered_implementations(self, f, sorting_context=None, *types):
"""
Get all mixin implementation that implementat *all* of the provided ``types`` and match the provided filter `f`.
@ -1083,7 +1101,7 @@ class PluginManager(object):
"""
assert callable(f)
implementations = self.get_implementations(*types)
implementations = self.get_implementations(*types, sorting_context=sorting_context)
return filter(f, implementations)
def get_helpers(self, name, *helpers):
@ -1242,6 +1260,10 @@ class Plugin(object):
class RestartNeedingPlugin(Plugin):
pass
class SorteablePlugin(Plugin):
def get_sorting_key(self, context=None):
return None
class PluginNeedsRestart(Exception):
def __init__(self, name):
Exception.__init__(self)

View file

@ -18,7 +18,7 @@ __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agp
__copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms of the AGPLv3 License"
from .core import (Plugin, RestartNeedingPlugin)
from .core import (Plugin, RestartNeedingPlugin, SorteablePlugin)
class OctoPrintPlugin(Plugin):
@ -99,7 +99,7 @@ class OctoPrintPlugin(Plugin):
class ReloadNeedingPlugin(Plugin):
pass
class StartupPlugin(OctoPrintPlugin):
class StartupPlugin(OctoPrintPlugin, SorteablePlugin):
"""
The ``StartupPlugin`` allows hooking into the startup of OctoPrint. It can be used to start up additional services
on or just after the startup of the server.
@ -127,7 +127,7 @@ class StartupPlugin(OctoPrintPlugin):
pass
class ShutdownPlugin(OctoPrintPlugin):
class ShutdownPlugin(OctoPrintPlugin, SorteablePlugin):
"""
The ``ShutdownPlugin`` allows hooking into the shutdown of OctoPrint. It's usually used in conjunction with the
:class:`StartupPlugin` mixin, to cleanly shut down additional services again that where started by the :class:`StartupPlugin`

View file

@ -417,7 +417,8 @@ class Server(object):
# run our startup plugins
octoprint.plugin.call_plugin(octoprint.plugin.StartupPlugin,
"on_startup",
args=(self._host, self._port))
args=(self._host, self._port),
sorting_context="StartupPlugin.on_startup")
def call_on_startup(name, plugin):
implementation = plugin.get_implementation(octoprint.plugin.StartupPlugin)
@ -437,7 +438,8 @@ class Server(object):
# control to the ioloop
def work():
octoprint.plugin.call_plugin(octoprint.plugin.StartupPlugin,
"on_after_startup")
"on_after_startup",
sorting_context="StartupPlugin.on_after_startup")
def call_on_after_startup(name, plugin):
implementation = plugin.get_implementation(octoprint.plugin.StartupPlugin)
@ -458,7 +460,8 @@ class Server(object):
observer.stop()
observer.join()
octoprint.plugin.call_plugin(octoprint.plugin.ShutdownPlugin,
"on_shutdown")
"on_shutdown",
sorting_context="ShutdownPlugin.on_shutdown")
self._logger.info("Goodbye!")
atexit.register(on_shutdown)