mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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>
This commit is contained in:
@@ -900,15 +900,15 @@ else:
|
|||||||
|
|
||||||
class API(plugable.API):
|
class API(plugable.API):
|
||||||
def __init__(self, allowed):
|
def __init__(self, allowed):
|
||||||
super(API, self).__init__(allowed, ['ipalib'])
|
super(API, self).__init__(allowed, ['ipalib.plugins.*'])
|
||||||
|
|
||||||
def bootstrap(self, parser=None, **overrides):
|
def bootstrap(self, parser=None, **overrides):
|
||||||
super(API, self).bootstrap(parser, **overrides)
|
super(API, self).bootstrap(parser, **overrides)
|
||||||
|
|
||||||
if self.env.in_server:
|
if self.env.in_server:
|
||||||
self.packages.append('ipaserver')
|
self.modules.append('ipaserver.plugins.*')
|
||||||
if self.env.context in ('installer', 'updates'):
|
if self.env.context in ('installer', 'updates'):
|
||||||
self.packages.append('ipaserver/install/plugins')
|
self.modules.append('ipaserver.install.plugins.*')
|
||||||
|
|
||||||
|
|
||||||
def create_api(mode='dummy'):
|
def create_api(mode='dummy'):
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import optparse
|
|||||||
import errors
|
import errors
|
||||||
import textwrap
|
import textwrap
|
||||||
import collections
|
import collections
|
||||||
|
import importlib
|
||||||
|
|
||||||
from config import Env
|
from config import Env
|
||||||
import text
|
import text
|
||||||
@@ -79,7 +80,7 @@ def find_modules_in_dir(src_dir):
|
|||||||
module = name[:-len(suffix)]
|
module = name[:-len(suffix)]
|
||||||
if module == '__init__':
|
if module == '__init__':
|
||||||
continue
|
continue
|
||||||
yield (module, pyfile)
|
yield module
|
||||||
|
|
||||||
|
|
||||||
class Registry(object):
|
class Registry(object):
|
||||||
@@ -429,9 +430,9 @@ class API(DictProxy):
|
|||||||
|
|
||||||
register = Registrar()
|
register = Registrar()
|
||||||
|
|
||||||
def __init__(self, allowed, packages):
|
def __init__(self, allowed, modules):
|
||||||
self.__plugins = {base: {} for base in allowed}
|
self.__plugins = {base: {} for base in allowed}
|
||||||
self.packages = packages
|
self.modules = modules
|
||||||
self.__d = dict()
|
self.__d = dict()
|
||||||
self.__done = set()
|
self.__done = set()
|
||||||
self.env = Env()
|
self.env = Env()
|
||||||
@@ -609,56 +610,55 @@ class API(DictProxy):
|
|||||||
self.__do_if_not_done('bootstrap')
|
self.__do_if_not_done('bootstrap')
|
||||||
if self.env.mode in ('dummy', 'unit_test'):
|
if self.env.mode in ('dummy', 'unit_test'):
|
||||||
return
|
return
|
||||||
for package in self.packages:
|
for module in self.modules:
|
||||||
self.import_plugins(package)
|
self.import_plugins(module)
|
||||||
for klass, kwargs in self.register.iteritems():
|
for klass, kwargs in self.register.iteritems():
|
||||||
self.add_plugin(klass, **kwargs)
|
self.add_plugin(klass, **kwargs)
|
||||||
|
|
||||||
# FIXME: This method has no unit test
|
# 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, '.')
|
if module.endswith('.*'):
|
||||||
subpackage = '%s.plugins' % package
|
subpackage = module[:-2]
|
||||||
try:
|
try:
|
||||||
parent = __import__(package)
|
plugins = importlib.import_module(subpackage)
|
||||||
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:
|
except ImportError, e:
|
||||||
self.log.error(
|
self.log.error("cannot import plugins sub-package %s: %s",
|
||||||
'cannot import plugins sub-package %s: %s', subpackage, e
|
subpackage, e)
|
||||||
)
|
raise
|
||||||
raise e
|
package, dot, part = subpackage.rpartition('.')
|
||||||
|
parent = sys.modules[package]
|
||||||
|
|
||||||
parent_dir = path.dirname(path.abspath(parent.__file__))
|
parent_dir = path.dirname(path.abspath(parent.__file__))
|
||||||
plugins_dir = path.dirname(path.abspath(plugins.__file__))
|
plugins_dir = path.dirname(path.abspath(plugins.__file__))
|
||||||
if parent_dir == plugins_dir:
|
if parent_dir == plugins_dir:
|
||||||
raise errors.PluginsPackageError(
|
raise errors.PluginsPackageError(
|
||||||
name=subpackage, file=plugins.__file__
|
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):
|
self.log.debug("importing all plugin modules in %s...", subpackage)
|
||||||
fullname = '%s.%s' % (subpackage, name)
|
modules = find_modules_in_dir(plugins_dir)
|
||||||
self.log.debug('importing plugin module %r', pyfile)
|
modules = ['.'.join((subpackage, name)) for name in modules]
|
||||||
|
else:
|
||||||
|
modules = [module]
|
||||||
|
|
||||||
|
for name in modules:
|
||||||
|
self.log.debug("importing plugin module %s", name)
|
||||||
try:
|
try:
|
||||||
__import__(fullname)
|
importlib.import_module(name)
|
||||||
except errors.SkipPluginModule, e:
|
except errors.SkipPluginModule, e:
|
||||||
self.log.debug(
|
self.log.debug("skipping plugin module %s: %s", name, e.reason)
|
||||||
'skipping plugin module %s: %s', fullname, e.reason
|
|
||||||
)
|
|
||||||
except StandardError, e:
|
except StandardError, e:
|
||||||
if self.env.startup_traceback:
|
if self.env.startup_traceback:
|
||||||
import 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
|
raise
|
||||||
|
|
||||||
def add_plugin(self, klass, override=False):
|
def add_plugin(self, klass, override=False):
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class Advice(Plugin):
|
|||||||
|
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
advise_api = API((Advice,), ('ipaserver/advise/plugins',))
|
advise_api = API((Advice,), ('ipaserver.advise.plugins.*',))
|
||||||
|
|
||||||
|
|
||||||
class IpaAdvise(admintool.AdminTool):
|
class IpaAdvise(admintool.AdminTool):
|
||||||
|
|||||||
Reference in New Issue
Block a user