forked from spladug/harold
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plugin.py
69 lines (50 loc) · 1.91 KB
/
plugin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import imp
import copy
import inspect
PLUGIN_DIRECTORY = '.'
class Plugin(object):
def __init__(self):
self.services = []
def add_service(self, service):
self.services.append(service)
def _import_plugin_modules(config):
plugins = {}
dependencies = {}
for plugin_name in config.plugin_names():
file, pathname, description = imp.find_module(plugin_name, ['.'])
plugin = imp.load_module(plugin_name, file, pathname, description)
plugins[plugin_name] = plugin
args, varargs, kw, defaults = inspect.getargspec(plugin.make_plugin)
dependencies[plugin_name] = set(args)
return plugins, dependencies
def _topological_sort(dependencies):
dependencies = copy.deepcopy(dependencies)
startup_order = []
satisfied_plugins = ['config'] # config is a known-safe starting point
while satisfied_plugins:
satisfied = satisfied_plugins.pop()
startup_order.append(satisfied)
for plugin, deps in dependencies.items():
if satisfied in deps:
deps.remove(satisfied)
if len(deps) == 0:
satisfied_plugins.append(plugin)
del dependencies[plugin]
assert len(dependencies) == 0
return startup_order
def load_plugins(config):
plugins, dependencies = _import_plugin_modules(config)
startup_order = _topological_sort(dependencies)
initialized_plugins = {'config': config}
for plugin in startup_order:
if plugin == 'config':
continue
module = plugins[plugin]
args = dict((name, initialized)
for name, initialized in initialized_plugins.iteritems()
if name in dependencies[plugin])
p = module.make_plugin(**args)
if p:
initialized_plugins[plugin] = p
return (ip for name, ip in initialized_plugins.iteritems()
if name != 'config')