The meat of working with coma
is to :func:`~coma.core.register.register` new
commands with an :func:`~coma.core.initiate.initiate`d coma.
The main use cases for :func:`~coma.core.register.register`, including command
names, command objects, config objects, config identifiers, and
:func:`~coma.core.register.register`ing multiple commands have all been
covered in the :doc:`introductory tutorial <../intro>`. Here, the emphasis is on
local argparse
overrides and local hooks as additional use cases.
By default, coma
uses ArgumentParser.add_subparsers().add_parser()
to create a new ArgumentParser
with default parameters for each :func:`~coma.core.register.register`ed
command. However, you can provide keyword arguments to override the default
parameter values in the internal :obj:`add_parser()` call through the
:obj:`parser_kwargs` parameter to :func:`~coma.core.register.register`.
For example, suppose you want to add command aliases. This can be achieved through the :obj:`aliases` keyword:
import coma
if __name__ == "__main__":
coma.register("greet", lambda: print("Hello World!"),
parser_kwargs=dict(aliases=["gr"]))
coma.wake()
With this alias, :obj:`greet` can now be invoked with just :obj:`gr`:
$ python main.py gr
Hello World!
coma
's behavior can be easily tweaked, replaced, or extended using hooks.
These are covered in great detail :doc:`in their own tutorial <../hooks/index>`.
Here, the emphasis is on the difference between global and local hooks: As with
configs, hooks can be :func:`~coma.core.initiate.initiate`d globally to affect
coma
's behavior towards all commands or :func:`~coma.core.register.register`ed
locally to only affect coma
's behavior towards a specific command.
Let's see how a few local hooks can easily inject additional behavior into a program:
import coma
parser_hook = coma.hooks.parser_hook.factory("--dry-run", action="store_true")
@coma.hooks.hook
def pre_run_hook(known_args):
if known_args.dry_run:
print("Early exit!")
quit()
if __name__ == "__main__":
coma.register("greet", lambda: print("Hello World!"),
parser_hook=parser_hook, pre_run_hook=pre_run_hook)
coma.wake()
In this example, we locally :func:`~coma.core.register.register`ed a :obj:`parser_hook` that adds a new :obj:`--dry-run` flag to the command line as well as a :obj:`pre_run_hook` that exits the program early (before the command is actually executed) if the flag is given on the command line:
$ python main.py greet
Hello World!
$ python main.py greet --dry-run
Early exit!
Note
coma
provides factory functions for some of the more common hooks.
In this example, we used :func:`coma.hooks.parser_hook.factory`, which
simply creates a function that in turn relays the provided parameters to the
add_argument()
method of the underlying ArgumentParser
bound to this command.
Warning
Local hooks are appended to the list of global hooks. Local hooks do not override global hooks. To override a global hook, use :func:`~coma.core.register.register` in conjunction with :func:`~coma.core.forget.forget`. See :doc:`here <./forget>` for details.