8 __doc__ =
"a library to ease the writing of sub-command scripts"
9 __author__ =
"Sebastien Binet"
24 ACMD_GROUPNAME =
'acmdlib.commands'
25 """The name under which all commands are grouped
28 ACMD_PARSER = argparse.ArgumentParser(
30 description=
"a general script interface with sub-commands",
33 ACMD_SUBPARSERS = ACMD_PARSER.add_subparsers(
41 """A wrapper class to manage the creation of commands and their arguments
43 this is very heavily inspired from:
44 http://pypi.python.org/pypi/django-boss (MIT licence)
52 plugin_name = kwargs.get(
'name')
or self.
name
57 return self.
fct.__name__.replace(
'_',
'-')
61 if getattr(self.
fct,
'__doc__',
None):
63 return self.
fct.__doc__.splitlines()[0]
67 if getattr(self.
fct,
'__doc__',
None):
68 return textwrap.dedent(self.
fct.__doc__)
72 return self.
parser.add_argument
75 return self.
fct(*args, **kwargs)
78 """Create and register a subparser for this command."""
80 kwargs.setdefault(
'help', self.
help)
81 kwargs.setdefault(
'formatter_class',argparse.RawDescriptionHelpFormatter)
83 kwargs.setdefault(
'name', self.
name)
84 names = (kwargs.get(
'name')
or self.
name).
split(
'.')
86 def _get_subparser(a):
88 for action
in a._subparsers._actions:
89 if isinstance(action, argparse._SubParsersAction):
91 raise RuntimeError(
'could not find adequate subparser')
92 return a.add_subparsers(dest=
'command',
95 def _get_parser(node, idx, names):
97 if name
in node.choices:
98 return node.choices[name]
101 'help' :
'a group of sub-commands',
103 return node.add_parser(**args)
106 node = _get_subparser(parser)
108 for i,n
in enumerate(names[:-1]):
109 node = _get_subparser(parser)
110 parser = _get_parser(node, i, names)
112 node = _get_subparser(parser)
113 kwargs[
'name'] = names[-1]
114 parser = node.add_parser(**kwargs)
121 if hasattr(self.
fct,
'_acmdlib_arguments'):
122 while self.
fct._acmdlib_arguments:
123 args, kwargs = self.
fct._acmdlib_arguments.pop()
126 if hasattr(self.
fct,
'_acmdlib_arguments_mutual'):
127 if not hasattr(self,
'_acmdlib_mutual_group'):
129 while self.
fct._acmdlib_arguments_mutual:
130 args, kwargs = self.
fct._acmdlib_arguments_mutual.pop()
136 """A simple plugin registration.
148 """Check if plugin exists
154 """Load given plugin and return it
157 return importlib.import_module(cls.
_plugins[name])
158 except Exception
as err:
159 print(
"** could not load command [%s]:\n%s" % (name, err))
171 """Decorator to declare that a function is a command.
180 """Decorator to add an argument to a command.
181 Use the `mutual=True` keyword to specify that the argument should belong to a mutual exclusion group.
183 is_mutual = kwargs.pop(
'mutual',
False)
186 if isinstance(fct, Command):
189 if not hasattr(cmd,
'_acmdlib_mutual_group'):
190 cmd._acmdlib_mutual_group = cmd.add_mutually_exclusive_group()
191 cmd._acmdlib_mutual_group.add_argument(*args, **kwargs)
193 cmd.add_argument(*args, **kwargs)
195 store_as =
'_acmdlib_arguments_mutual' if is_mutual
else '_acmdlib_arguments'
196 if not hasattr(fct, store_as):
197 setattr(fct, store_as, [])
198 getattr(fct, store_as).
append((args, kwargs))
204 """Registers a plugin, given a name and value.
206 ex: register('check-file', 'PyUtils.CheckFileLib:fct')
209 return Plugins.register(name, value)