plugable: Specify plugin base classes and modules using API properties

https://fedorahosted.org/freeipa/ticket/3090

Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
This commit is contained in:
Jan Cholasta
2015-06-15 13:36:26 +00:00
parent 4b277d0477
commit 2b12bca660
4 changed files with 36 additions and 18 deletions

View File

@@ -899,16 +899,16 @@ else:
class API(plugable.API): class API(plugable.API):
def __init__(self, allowed): bases = (Command, Object, Method, Backend, Updater)
super(API, self).__init__(allowed, ['ipalib.plugins.*'])
def bootstrap(self, parser=None, **overrides):
super(API, self).bootstrap(parser, **overrides)
@property
def modules(self):
result = ('ipalib.plugins.*',)
if self.env.in_server: if self.env.in_server:
self.modules.append('ipaserver.plugins.*') result += ('ipaserver.plugins.*',)
if self.env.context in ('installer', 'updates'): if self.env.context in ('installer', 'updates'):
self.modules.append('ipaserver.install.plugins.*') result += ('ipaserver.install.plugins.*',)
return result
def create_api(mode='dummy'): def create_api(mode='dummy'):
@@ -926,7 +926,7 @@ def create_api(mode='dummy'):
- `backend.Backend` - `backend.Backend`
""" """
api = API((Command, Object, Method, Backend, Updater)) api = API()
if mode is not None: if mode is not None:
api.env.mode = mode api.env.mode = mode
assert mode != 'production' assert mode != 'production'

View File

@@ -306,24 +306,31 @@ class API(ReadOnly):
register = Registrar() register = Registrar()
def __init__(self, allowed, modules): def __init__(self):
super(API, self).__init__() super(API, self).__init__()
self.__plugins = {base: {} for base in allowed} self.__plugins = {}
self.modules = modules
self.__done = set() self.__done = set()
self.env = Env() self.env = Env()
@property
def bases(self):
raise NotImplementedError
@property
def modules(self):
raise NotImplementedError
def __len__(self): def __len__(self):
""" """
Return the number of plugin namespaces in this API object. Return the number of plugin namespaces in this API object.
""" """
return len(self.__plugins) return len(self.bases)
def __iter__(self): def __iter__(self):
""" """
Iterate (in ascending order) through plugin namespace names. Iterate (in ascending order) through plugin namespace names.
""" """
return (base.__name__ for base in self.__plugins) return (base.__name__ for base in self.bases)
def __contains__(self, name): def __contains__(self, name):
""" """
@@ -614,10 +621,11 @@ class API(ReadOnly):
# Find the base class or raise SubclassError: # Find the base class or raise SubclassError:
found = False found = False
for (base, sub_d) in self.__plugins.iteritems(): for base in self.bases:
if not issubclass(klass, base): if not issubclass(klass, base):
continue continue
sub_d = self.__plugins.setdefault(base, {})
found = True found = True
if sub_d.get(klass.__name__) is klass: if sub_d.get(klass.__name__) is klass:
@@ -647,7 +655,7 @@ class API(ReadOnly):
if not found: if not found:
raise errors.PluginSubclassError( raise errors.PluginSubclassError(
plugin=klass, plugin=klass,
bases=self.__plugins.keys(), bases=self.bases,
) )
def finalize(self): def finalize(self):
@@ -664,8 +672,9 @@ class API(ReadOnly):
plugins = {} plugins = {}
plugin_info = {} plugin_info = {}
for base, sub_d in self.__plugins.iteritems(): for base in self.bases:
name = base.__name__ name = base.__name__
sub_d = self.__plugins.get(base, {})
members = [] members = []
for klass in sub_d.itervalues(): for klass in sub_d.itervalues():

View File

@@ -121,7 +121,12 @@ class Advice(Plugin):
raise NotImplementedError raise NotImplementedError
advise_api = API((Advice,), ('ipaserver.advise.plugins.*',))
class AdviseAPI(API):
bases = (Advice,)
modules = ('ipaserver.advise.plugins.*',)
advise_api = AdviseAPI()
class IpaAdvise(admintool.AdminTool): class IpaAdvise(admintool.AdminTool):

View File

@@ -202,7 +202,11 @@ class test_API(ClassChecker):
def method(self, n): def method(self, n):
return n + 1 return n + 1
api = plugable.API([base0, base1], []) class API(plugable.API):
bases = (base0, base1)
modules = ()
api = API()
api.env.mode = 'unit_test' api.env.mode = 'unit_test'
api.env.in_tree = True api.env.in_tree = True
r = api.add_plugin r = api.add_plugin