Made hooks and templates sortable
This commit is contained in:
parent
aa6998ec5e
commit
44c76fa70b
2 changed files with 61 additions and 17 deletions
|
|
@ -23,7 +23,7 @@ __copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms
|
|||
|
||||
import os
|
||||
import imp
|
||||
from collections import defaultdict, namedtuple
|
||||
from collections import defaultdict, namedtuple, OrderedDict
|
||||
import logging
|
||||
|
||||
import pkg_resources
|
||||
|
|
@ -449,10 +449,11 @@ class PluginManager(object):
|
|||
|
||||
self.enabled_plugins = dict()
|
||||
self.disabled_plugins = dict()
|
||||
self.plugin_hooks = defaultdict(list)
|
||||
self.plugin_implementations = dict()
|
||||
self.plugin_implementations_by_type = defaultdict(list)
|
||||
|
||||
self._plugin_hooks = defaultdict(list)
|
||||
|
||||
self.implementation_injects = dict()
|
||||
self.implementation_inject_factories = []
|
||||
self.implementation_pre_inits = []
|
||||
|
|
@ -476,6 +477,10 @@ class PluginManager(object):
|
|||
plugins.update(self.disabled_plugins)
|
||||
return plugins
|
||||
|
||||
@property
|
||||
def plugin_hooks(self):
|
||||
return {key: map(lambda v: (v[1], v[2]), value) for key, value in self._plugin_hooks.items()}
|
||||
|
||||
def find_plugins(self, existing=None, ignore_uninstalled=True):
|
||||
if existing is None:
|
||||
existing = dict(self.plugins)
|
||||
|
|
@ -780,7 +785,15 @@ class PluginManager(object):
|
|||
|
||||
# evaluate registered hooks
|
||||
for hook, callback in plugin.hooks.items():
|
||||
self.plugin_hooks[hook].append((name, callback))
|
||||
if isinstance(callback, tuple):
|
||||
if len(callback) != 2:
|
||||
continue
|
||||
callback, order = callback
|
||||
else:
|
||||
order = None
|
||||
|
||||
self._plugin_hooks[hook].append((order, name, callback))
|
||||
self._sort_hooks(hook)
|
||||
|
||||
# evaluate registered implementation
|
||||
if plugin.implementation:
|
||||
|
|
@ -792,8 +805,16 @@ class PluginManager(object):
|
|||
|
||||
def _deactivate_plugin(self, name, plugin):
|
||||
for hook, callback in plugin.hooks.items():
|
||||
if isinstance(callback, tuple):
|
||||
if len(callback) != 2:
|
||||
continue
|
||||
callback, order = callback
|
||||
else:
|
||||
order = None
|
||||
|
||||
try:
|
||||
self.plugin_hooks[hook].remove((name, callback))
|
||||
self._plugin_hooks[hook].remove((order, name, callback))
|
||||
self._sort_hooks(hook)
|
||||
except ValueError:
|
||||
# that's ok, the plugin was just not registered for the hook
|
||||
pass
|
||||
|
|
@ -1019,7 +1040,11 @@ class PluginManager(object):
|
|||
|
||||
if not hook in self.plugin_hooks:
|
||||
return dict()
|
||||
return {hook[0]: hook[1] for hook in self.plugin_hooks[hook]}
|
||||
|
||||
result = OrderedDict()
|
||||
for h in self.plugin_hooks[hook]:
|
||||
result[h[0]] = h[1]
|
||||
return result
|
||||
|
||||
def get_implementations(self, *types):
|
||||
"""
|
||||
|
|
@ -1118,6 +1143,10 @@ class PluginManager(object):
|
|||
try: client(plugin, data)
|
||||
except: self.logger.exception("Exception while sending plugin data to client")
|
||||
|
||||
def _sort_hooks(self, hook):
|
||||
self._plugin_hooks[hook] = sorted(self._plugin_hooks[hook],
|
||||
key=lambda x: (x[0] is None, x[0], x[1], x[2]))
|
||||
|
||||
|
||||
class InstalledEntryPoint(pkginfo.Installed):
|
||||
|
||||
|
|
|
|||
|
|
@ -270,18 +270,20 @@ def index():
|
|||
if len(missing_in_order) == 0:
|
||||
continue
|
||||
|
||||
# finally add anything that's not included in our order yet
|
||||
sorted_missing = list(missing_in_order)
|
||||
if template_sorting[t]["key"] is not None:
|
||||
# default extractor: works with entries that are dicts and entries that are 2-tuples with the
|
||||
# entry data at index 1
|
||||
def extractor(item, key):
|
||||
if isinstance(item, dict) and key in item:
|
||||
return item[key]
|
||||
elif isinstance(item, tuple) and len(item) > 1 and isinstance(item[1], dict) and key in item[1]:
|
||||
return item[1][key]
|
||||
# works with entries that are dicts and entries that are 2-tuples with the
|
||||
# entry data at index 1
|
||||
def config_extractor(item, key, default_value=None):
|
||||
if isinstance(item, dict) and key in item:
|
||||
return item[key] if key in item else default_value
|
||||
elif isinstance(item, tuple) and len(item) > 1 and isinstance(item[1], dict) and key in item[1]:
|
||||
return item[1][key] if key in item[1] else default_value
|
||||
|
||||
return None
|
||||
return default_value
|
||||
|
||||
# finally add anything that's not included in our order yet
|
||||
if template_sorting[t]["key"] is not None:
|
||||
# we'll use our config extractor as default key extractor
|
||||
extractor = config_extractor
|
||||
|
||||
# if template type provides custom extractor, make sure its exceptions are handled
|
||||
if "key_extractor" in template_sorting[t] and callable(template_sorting[t]["key_extractor"]):
|
||||
|
|
@ -296,7 +298,20 @@ def index():
|
|||
extractor = create_safe_extractor(template_sorting[t]["key_extractor"])
|
||||
|
||||
sort_key = template_sorting[t]["key"]
|
||||
sorted_missing = sorted(missing_in_order, key=lambda x: extractor(templates[t]["entries"][x], sort_key))
|
||||
|
||||
def key_func(x):
|
||||
config = templates[t]["entries"][x]
|
||||
entry_order = config_extractor(config, "order", default_value=None)
|
||||
return entry_order is None, entry_order, extractor(config, sort_key)
|
||||
|
||||
sorted_missing = sorted(missing_in_order, key=key_func)
|
||||
else:
|
||||
def key_func(x):
|
||||
config = templates[t]["entries"][x]
|
||||
entry_order = config_extractor(config, "order", default_value=None)
|
||||
return entry_order is None, entry_order
|
||||
|
||||
sorted_missing = sorted(missing_in_order, key=key_func)
|
||||
|
||||
if template_sorting[t]["add"] == "prepend":
|
||||
templates[t]["order"] = sorted_missing + templates[t]["order"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue