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
|
class PluginManager(object):
def __init__(self, plugins):
self._plugins = plugins
def __iter__(self):
return iter(self._plugins)
def __len__(self):
return len(self._plugins)
def __getitem__(self, index):
return self._plugins[index]
def produce(self, *args, **kwargs):
"""Produce a new set of plugins, treating the current set as plugin
factories.
"""
new_plugins = []
for p in self._plugins:
r = p(*args, **kwargs)
new_plugins.append(r)
return PluginManager(new_plugins)
def call(self, methodname, *args, **kwargs):
"""Call a common method on all the plugins, if it exists."""
for plugin in self._plugins:
method = getattr(plugin, methodname, None)
if method is None:
continue
yield method(*args, **kwargs)
def first(self, methodname, *args, **kwargs):
"""Call a common method on all the plugins, if it exists. Return the
first result (the first non-None)
"""
for r in self.call(methodname, *args, **kwargs):
if r is not None:
return r
raise ValueError("No plugins returned a non-None value")
def pipe(self, methodname, first_arg, *args, **kwargs):
"""Call a common method on all the plugins, if it exists. The return
value of each call becomes the replaces the first argument in the given
argument list to pass to the next.
Useful to utilize plugins as sets of filters.
"""
for plugin in self._plugins:
method = getattr(plugin, methodname, None)
if method is None:
continue
r = method(first_arg, *args, **kwargs)
if r is not None:
first_arg = r
return r
|