diff options
author | Jan Cholasta <jcholast@redhat.com> | 2015-06-15 11:02:07 +0000 |
---|---|---|
committer | Jan Cholasta <jcholast@redhat.com> | 2015-07-01 13:05:30 +0000 |
commit | 481f8ddaa32795c64275438645e45d2c4bbbae26 (patch) | |
tree | cf779df52ac49e3db09b9bd6dc503c7946bda375 | |
parent | 7715d5bb044f891dcf420f230726b72d1695edb6 (diff) | |
download | freeipa-481f8ddaa32795c64275438645e45d2c4bbbae26.tar.gz freeipa-481f8ddaa32795c64275438645e45d2c4bbbae26.tar.xz freeipa-481f8ddaa32795c64275438645e45d2c4bbbae26.zip |
plugable: Specify plugins to import in API by module names
This change removes the automatic plugins sub-package magic and allows
specifying modules in addition to packages.
https://fedorahosted.org/freeipa/ticket/3090
Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
-rw-r--r-- | ipalib/__init__.py | 6 | ||||
-rw-r--r-- | ipalib/plugable.py | 84 | ||||
-rw-r--r-- | ipaserver/advise/base.py | 2 |
3 files changed, 46 insertions, 46 deletions
diff --git a/ipalib/__init__.py b/ipalib/__init__.py index cc1492570..74a812033 100644 --- a/ipalib/__init__.py +++ b/ipalib/__init__.py @@ -900,15 +900,15 @@ else: class API(plugable.API): def __init__(self, allowed): - super(API, self).__init__(allowed, ['ipalib']) + super(API, self).__init__(allowed, ['ipalib.plugins.*']) def bootstrap(self, parser=None, **overrides): super(API, self).bootstrap(parser, **overrides) if self.env.in_server: - self.packages.append('ipaserver') + self.modules.append('ipaserver.plugins.*') if self.env.context in ('installer', 'updates'): - self.packages.append('ipaserver/install/plugins') + self.modules.append('ipaserver.install.plugins.*') def create_api(mode='dummy'): diff --git a/ipalib/plugable.py b/ipalib/plugable.py index 74ac62bae..d98ab731e 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -36,6 +36,7 @@ import optparse import errors import textwrap import collections +import importlib from config import Env import text @@ -79,7 +80,7 @@ def find_modules_in_dir(src_dir): module = name[:-len(suffix)] if module == '__init__': continue - yield (module, pyfile) + yield module class Registry(object): @@ -429,9 +430,9 @@ class API(DictProxy): register = Registrar() - def __init__(self, allowed, packages): + def __init__(self, allowed, modules): self.__plugins = {base: {} for base in allowed} - self.packages = packages + self.modules = modules self.__d = dict() self.__done = set() self.env = Env() @@ -609,56 +610,55 @@ class API(DictProxy): self.__do_if_not_done('bootstrap') if self.env.mode in ('dummy', 'unit_test'): return - for package in self.packages: - self.import_plugins(package) + for module in self.modules: + self.import_plugins(module) for klass, kwargs in self.register.iteritems(): self.add_plugin(klass, **kwargs) # FIXME: This method has no unit test - def import_plugins(self, package): + def import_plugins(self, module): """ - Import modules in ``plugins`` sub-package of ``package``. + Import plugins from ``module``. + + :param module: Name of the module to import. This might be a wildcard + in the form ```package.*``` in which case all modules + from the given package are loaded. """ - package = package.replace(os.path.sep, '.') - subpackage = '%s.plugins' % package - try: - parent = __import__(package) - parts = package.split('.')[1:] - if parts: - for part in parts: - if part == 'plugins': - plugins = subpackage.plugins - subpackage = plugins.__name__ - break - subpackage = parent.__getattribute__(part) - parent = subpackage - else: - plugins = __import__(subpackage).plugins - except ImportError, e: - self.log.error( - 'cannot import plugins sub-package %s: %s', subpackage, e - ) - raise e - parent_dir = path.dirname(path.abspath(parent.__file__)) - plugins_dir = path.dirname(path.abspath(plugins.__file__)) - if parent_dir == plugins_dir: - raise errors.PluginsPackageError( - name=subpackage, file=plugins.__file__ - ) - self.log.debug('importing all plugin modules in %r...', plugins_dir) - for (name, pyfile) in find_modules_in_dir(plugins_dir): - fullname = '%s.%s' % (subpackage, name) - self.log.debug('importing plugin module %r', pyfile) + if module.endswith('.*'): + subpackage = module[:-2] try: - __import__(fullname) - except errors.SkipPluginModule, e: - self.log.debug( - 'skipping plugin module %s: %s', fullname, e.reason + plugins = importlib.import_module(subpackage) + except ImportError, e: + self.log.error("cannot import plugins sub-package %s: %s", + subpackage, e) + raise + package, dot, part = subpackage.rpartition('.') + parent = sys.modules[package] + + parent_dir = path.dirname(path.abspath(parent.__file__)) + plugins_dir = path.dirname(path.abspath(plugins.__file__)) + if parent_dir == plugins_dir: + raise errors.PluginsPackageError( + name=subpackage, file=plugins.__file__ ) + + self.log.debug("importing all plugin modules in %s...", subpackage) + modules = find_modules_in_dir(plugins_dir) + modules = ['.'.join((subpackage, name)) for name in modules] + else: + modules = [module] + + for name in modules: + self.log.debug("importing plugin module %s", name) + try: + importlib.import_module(name) + except errors.SkipPluginModule, e: + self.log.debug("skipping plugin module %s: %s", name, e.reason) except StandardError, e: if self.env.startup_traceback: import traceback - self.log.error('could not load plugin module %r\n%s', pyfile, traceback.format_exc()) + self.log.error("could not load plugin module %s\n%s", name, + traceback.format_exc()) raise def add_plugin(self, klass, override=False): diff --git a/ipaserver/advise/base.py b/ipaserver/advise/base.py index ab8323c53..9913e555d 100644 --- a/ipaserver/advise/base.py +++ b/ipaserver/advise/base.py @@ -121,7 +121,7 @@ class Advice(Plugin): raise NotImplementedError -advise_api = API((Advice,), ('ipaserver/advise/plugins',)) +advise_api = API((Advice,), ('ipaserver.advise.plugins.*',)) class IpaAdvise(admintool.AdminTool): |