Made hooks and templates sortable

This commit is contained in:
Gina Häußge 2015-09-04 11:25:27 +02:00
parent aa6998ec5e
commit 44c76fa70b
2 changed files with 61 additions and 17 deletions

View file

@ -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):

View file

@ -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"]