summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/plugable.py25
-rw-r--r--ipalib/tests/test_plugable.py16
2 files changed, 32 insertions, 9 deletions
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index 32cbe033..cafb8c50 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -49,16 +49,27 @@ class Plugin(object):
Base class for all plugins.
"""
- def __init__(self, api):
- self.__api = api
+ __api = None
def __get_api(self):
"""
- Returns the plugable.API object this plugin has been instatiated in.
+ Returns the plugable.API instance passed to Plugin.finalize(), or
+ or returns None if finalize() has not yet been called.
"""
return self.__api
api = property(__get_api)
+ def finalize(self, api):
+ """
+ After all the plugins are instantiated, the plugable.API calls this
+ method, passing itself as the only argument. This is where plugins
+ should check that other plugins they depend upon have actually be
+ loaded.
+ """
+ assert self.__api is None, 'finalize() can only be called once'
+ assert api is not None, 'finalize() argument cannot be None'
+ self.__api = api
+
def __get_name(self):
"""
Returns the class name of this instance.
@@ -280,14 +291,18 @@ class Registrar(object):
class API(ReadOnly):
def __init__(self, registrar):
+ object.__setattr__(self, '_API__plugins', [])
for (base, plugins) in registrar:
ns = NameSpace(self.__plugin_iter(base, plugins))
assert not hasattr(self, base.__name__)
object.__setattr__(self, base.__name__, ns)
+ for plugin in self.__plugins:
+ plugin.finalize(self)
+ assert plugin.api is self
def __plugin_iter(self, base, plugins):
assert issubclass(base.proxy, Proxy)
for cls in plugins:
- plugin = cls(self)
- assert plugin.api is self
+ plugin = cls()
+ self.__plugins.append(plugin)
yield base.proxy(plugin)
diff --git a/ipalib/tests/test_plugable.py b/ipalib/tests/test_plugable.py
index f5d469af..27841e2e 100644
--- a/ipalib/tests/test_plugable.py
+++ b/ipalib/tests/test_plugable.py
@@ -43,17 +43,25 @@ def test_from_cli():
def test_Plugin():
api = 'the api instance'
- p = plugable.Plugin(api)
- assert read_only(p, 'api') is api
+ p = plugable.Plugin()
assert read_only(p, 'name') == 'Plugin'
assert repr(p) == '%s.Plugin()' % plugable.__name__
+ assert read_only(p, 'api') is None
+ raises(AssertionError, p.finalize, None)
+ p.finalize(api)
+ assert read_only(p, 'api') is api
+ raises(AssertionError, p.finalize, api)
class some_plugin(plugable.Plugin):
pass
- p = some_plugin(api)
- assert read_only(p, 'api') is api
+ p = some_plugin()
assert read_only(p, 'name') == 'some_plugin'
assert repr(p) == '%s.some_plugin()' % __name__
+ assert read_only(p, 'api') is None
+ raises(AssertionError, p.finalize, None)
+ p.finalize(api)
+ assert read_only(p, 'api') is api
+ raises(AssertionError, p.finalize, api)
def test_ReadOnly():