help, makeapi: do not use hardcoded plugin package name

Iterate over all plugin packages defined in the API to find the given
topic module. The last module found has priority.

This will allow topics to be defined in client-side plugins.

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

Reviewed-By: David Kupka <dkupka@redhat.com>
This commit is contained in:
Jan Cholasta 2016-05-16 14:15:19 +02:00
parent cd5ecdbaee
commit fe18adb258
2 changed files with 43 additions and 22 deletions

View File

@ -691,17 +691,26 @@ class help(frontend.Local):
topic = None
_PLUGIN_BASE_MODULE = 'ipalib.plugins'
def _get_topic(self, topic):
module_name = '%s.%s' % (self._PLUGIN_BASE_MODULE, topic)
try:
module = sys.modules[module_name]
except KeyError:
module = importlib.import_module(module_name)
doc = u''
parent_topic = None
doc = unicode(module.__doc__ or '').strip()
parent_topic = getattr(module, 'topic', None)
for package in self.api.packages:
module_name = '%s.%s' % (package.__name__, topic)
try:
module = sys.modules[module_name]
except KeyError:
try:
module = importlib.import_module(module_name)
except ImportError:
continue
if module.__doc__ is not None:
doc = unicode(module.__doc__ or '').strip()
try:
parent_topic = module.topic
except AttributeError:
pass
return doc, parent_topic
@ -763,7 +772,6 @@ class help(frontend.Local):
outfile = sys.stdout
writer = self._writer(outfile)
name = from_cli(key)
mod_name = '%s.%s' % (self._PLUGIN_BASE_MODULE, name)
if key is None:
self.api.parser.print_help(outfile)
return
@ -777,7 +785,8 @@ class help(frontend.Local):
if cmd.NO_CLI:
raise HelpError(topic=name)
self.Backend.cli.build_parser(cmd).print_help(outfile)
elif mod_name in sys.modules:
elif any(name in t[2] for t in self._topics.values()
if type(t[2]) is dict):
self.print_commands(name, outfile)
elif name == "commands":
mcl = max(len(s) for s in (self.Command))
@ -827,8 +836,7 @@ class help(frontend.Local):
commands = self._topics[t][2][topic][2]
break
m = '%s.%s' % (self._PLUGIN_BASE_MODULE, topic)
doc = (unicode(_(sys.modules[m].__doc__)) or '').strip()
doc, _topic = self._get_topic(topic)
if topic not in self.Command and len(commands) == 0:
raise HelpError(topic=topic)

31
makeapi
View File

@ -171,23 +171,36 @@ def validate_doc():
while topic is not None:
if not topics.setdefault(topic, 0):
# First time seeing this module, validate the module contents
module = 'ipalib.plugins.%s' % topic
try:
mod = sys.modules[module]
except KeyError:
mod = importlib.import_module(module)
doc = None
next_topic = None
# See if there is a module topic, if so validate it
next_topic = getattr(mod, 'topic', None)
for package in api.packages:
module = '%s.%s' % (package.__name__, topic)
try:
mod = sys.modules[module]
except KeyError:
try:
mod = importlib.import_module(module)
except ImportError:
continue
if mod.__doc__ is not None:
doc = mod.__doc__
# See if there is a module topic, if so validate it
try:
next_topic = mod.topic
except AttributeError:
pass
# Does the module have documentation?
if mod.__doc__ is None:
if doc is None:
src_file = inspect.getsourcefile(mod)
n_missing_mod_doc += 1
print("%s: module \"%s\" has no doc" %
(src_file, module))
# Yes the module has doc, but is it internationalized?
elif not is_i18n(mod.__doc__):
elif not is_i18n(doc):
src_file = inspect.getsourcefile(cmd_class)
n_missing_mod_i18n += 1
print("%s: module \"%s\" doc is not internationalized" %