42from .. common
import ConsolePrinter, ensure_namespace, get_name, import_item
60def init(args=None, **kwargs):
62 Imports and initializes all plugins from auto and from given arguments.
64 @param args arguments as namespace or dictionary, case-insensitive
65 @param args.plugin list of Python modules or classes to import,
66 as ["my.module", "other.module.SomeClass", ],
67 or module or class instances
68 @param args.stop_on_error stop execution on any error like failing to load plugin
69 @param kwargs any and all arguments as keyword overrides, case-insensitive
71 args = ensure_namespace(args, DEFAULT_ARGS, **kwargs)
72 for f
in sorted(glob.glob(os.path.join(os.path.dirname(__file__),
"auto",
"*"))):
73 if not f.lower().endswith((
".py",
".pyc")):
continue
74 name = os.path.splitext(os.path.split(f)[-1])[0]
75 if name.startswith(
"__")
or name
in PLUGINS:
continue
77 modulename =
"%s.auto.%s" % (__package__, name)
79 plugin = import_item(modulename)
80 if callable(getattr(plugin,
"init",
None)): plugin.init(args)
81 PLUGINS[name] = plugin
83 ConsolePrinter.error(
"Error loading plugin %s.", modulename)
84 if args.STOP_ON_ERROR:
raise
93 Imports plugin Python packages, invokes init(args) if any, raises on error.
95 @param args arguments as namespace or dictionary, case-insensitive
96 @param args.plugin list of Python modules or classes to import,
97 as ["my.module", "other.module.SomeClass", ],
98 or module or class instances
99 @param kwargs any and all arguments as keyword overrides, case-insensitive
101 args = ensure_namespace(args, DEFAULT_ARGS, **kwargs)
102 for obj
in args.PLUGIN:
103 name = obj
if isinstance(obj, six.string_types)
else get_name(obj)
104 if name
in PLUGINS:
continue
106 plugin = import_item(name)
if isinstance(obj, six.string_types)
else obj
107 if callable(getattr(plugin,
"init",
None)): plugin.init(args)
108 PLUGINS[name] = plugin
109 except ImportWarning:
112 ConsolePrinter.error(
"Error loading plugin %s.", name)
153 Adds plugin to `--write` in main.ARGUMENTS and MultiSink formats.
155 @param name format name like "csv", added to `--write .. format=FORMAT`
156 @param cls class providing Sink interface
157 @param label plugin label; if multiple plugins add the same option,
158 "label output" in help text is replaced with "label1/label2/.. output"
159 @param options a sequence of (name, help) to add to --write help, like
160 [("template=/my/path.tpl", "custom template to use for HTML output")]
162 MultiSink.FORMAT_CLASSES[name] = cls
163 if options: WRITE_OPTIONS.setdefault(label, []).extend(options)
182 """Populates argument texts with added output labels."""
183 if not OUTPUT_LABELS:
return
186 argslist = sum(main.ARGUMENTS.get(
"groups", {}).values(), main.ARGUMENTS[
"arguments"][:])
187 args = {f: x
for x
in argslist
for f
in x[
"args"]}
188 args.update((id(x), x)
for x
in argslist)
192 for label, flag
in ((l, f)
for l, ff
in OUTPUT_LABELS.items()
for f
in ff):
193 if flag
in args: arglabels.setdefault(id(args[flag]), []).append(label)
194 else: ConsolePrinter.warn(
"Unknown command-line flag %r from output %r.", flag, label)
197 for arg, labels
in ((args[x], ll)
for x, ll
in arglabels.items()):
198 match = re.search(
r"(\A.*?\s*in\s)(\S+)(\s+output.*\Z)", arg[
"help"], re.DOTALL)
200 ConsolePrinter.warn(
"Command-line flag %s has no text on output for labels %s.",
201 arg[
"args"],
", ".join(map(repr, sorted(set(labels)))))
203 labels2 = sorted(set(labels + match.group(2).split(
"/")), key=
lambda x: x.lower())
204 arg[
"help"] = match.expand(
r"\1%s\3" %
"/".join(labels2))
206 OUTPUT_LABELS.clear()
234 """Populates main.ARGUMENTS with added write formats and options."""
236 if not writearg:
return
238 formats = sorted(set(MultiSink.FORMAT_CLASSES))
239 writearg[
"metavar"] =
"TARGET [format=%s] [KEY=VALUE ...]" %
"|".join(formats)
240 if not WRITE_OPTIONS:
return
251 for label, opts
in WRITE_OPTIONS.items():
252 for name, help
in opts:
253 texts.setdefault(name, help)
254 namelabels.setdefault(name, []).append(label)
255 namelens[name] = len(name)
258 maxname = max(x
if x <= MAXNAME
else 0
for x
in namelens.values())
259 for label, opts
in WRITE_OPTIONS.items():
260 for name, help
in opts:
261 inters[name] =
"\n" if len(name) > MAXNAME
else " " * (maxname - len(name) + 2)
262 indent = LEADING +
" " +
" " * (maxname
or MAXNAME)
265 PLACEHOLDER =
"<plugin label replacement>"
266 for name
in list(texts):
267 if len(namelabels[name]) > 1:
268 for label
in namelabels[name]:
269 texts[name] = texts[name].replace(
"%s output" % label, PLACEHOLDER)
270 labels =
"/".join(sorted(filter(bool, namelabels[name]), key=
lambda x: x.lower()))
271 texts[name] = texts[name].replace(PLACEHOLDER, labels +
" output")
273 fmt =
lambda n, h:
"\n".join((indent
if i
or "\n" == inters[n]
else "") + l
274 for i, l
in enumerate(h.splitlines()))
275 text =
"\n".join(sorted(
"".join((LEADING, n, inters[n], fmt(n, h)))
276 for n, h
in texts.items()))
277 writearg[
"help"] +=
"\n" + text
279 WRITE_OPTIONS.clear()