Introduction
Hooks make it easy to tweak, replace, or extend coma
.
Types of Hooks
At the highest level, hooks belong to one of two types:
- parser
Parser hooks are called when a command is
register()
ed and are meant to add_arguments() to the underlying ArgumentParser bound to the command.- invocation
Invocation hooks are called by
wake()
if, and only if, the command to which they are globallyinitiate()
d or locallyregister()
ed is invoked.
Invocation hooks further belong to one of three sub-types:
- config
A config hook is meant to initialize or affect the config objects that are globally
initiate()
d or locallyregister()
ed to a command.- init
An init hook is meant to instantiate or affect the command itself.
Warning
For function-based commands, the function is internally wrapped in another object, and it is this wrapper object that an init hook receives.
- run
A run hook is meant to execute or surround the execution of the command.
For all three hook sub-types above (config, init, and run), each is further split into three sub-sub-types:
- pre
A pre hook is called immediately before a main hook as a way to add additional behavior.
- main
A main hook is generally meant to perform the bulk of the work.
- post
A post hook is called immediately after a main hook as a way to add additional behavior.
Altogether, there are 9 invocation hooks.
Hook Pipeline
As stated above, parser hooks are called at the time a command is
register()
ed, whereas the invocation hooks are
called if, and only if, the corresponding command is invoked.
The following keywords are used to initiate()
,
register()
, and/or forget()
hooks:
Type |
Sub-Type |
Sub-Sub-Type |
Keyword |
---|---|---|---|
parser |
N/A |
N/A |
|
invocation |
config |
pre |
|
main |
|
||
post |
|
||
init |
pre |
|
|
main |
|
||
post |
|
||
run |
pre |
|
|
main |
|
||
post |
|
The invocation hook pipeline consists of calling all the invocation hooks, in the order listed here, one immediately following the other, with no other code in between. In other words, the invocation hooks make up the entirety of the hook pipeline.
Default Hook Pipeline
Rather than being hard-coded, coma
’s default behavior is, almost entirely, a
result of having certain specific default hooks initiate()
d.
The upshot is that there is almost no part of coma
’s default behavior that cannot
be tweaked, replaced, or extended through clever use of hooks.
The default hooks are:
- parser
The default
parser_hook
iscoma.hooks.parser_hook.default()
. This hook uses add_argument() to add, for each config, a parser argument of the form--{config_id}-path
where{config_id}
is the config’s identifier. This enables an explicit file path to the serialized config to be specified on the command line.- pre config
N/A
- main config
The default
config_hook
iscoma.hooks.config_hook.default()
. This hook does a lot of the heaving lifting for manifestingcoma
’s default behavior regarding configs. In short, for each config, this hook:Attempts to load the config from file. This can interact with the default
parser_hook
.If the config file isn’t found, a config object with default attribute values is instantiated, and the default config object is serialized.
Note
YAML is used for serialization by default (since it is the only format that
omegaconf
supports), butcoma
also natively supports JSON. See here for full details on configuration files.- post config
The default
post_config_hook
iscoma.hooks.post_config_hook.default()
. This hook is responsible for overriding config attribute values with any that are specified on the command line inomegaconf
’s dot-list notation. See here for full details on command line overrides.- pre init
N/A
- main init
The default
init_hook
iscoma.hooks.init_hook.default()
. This hook instantiates the command object by invoking it with all configs given, in order, as positional arguments.- post init
N/A
- pre run
N/A
- main run
The default
run_hook
iscoma.hooks.run_hook.default()
. This hook calls the command object’srun()
method with no parameters.- post run
N/A
Note
For each of the default hooks, factory functions are provided that can create
new variations on these defaults. For example, coma.hooks.run_hook.factory()
can be used to change the command execution method name from run()
to
something else. See here to explore all
factory options.
Note
If you are finding that the factory functions for the parser hook, main config hook, and/or post config hook are insufficient, consider making use of the many config-related utilities found here to help you in writing your own custom hooks.
Global and Local Hooks
Hooks can be initiate()
d globally to affect coma
’s
behavior towards all commands or register()
ed locally
to only affect coma
’s behavior towards a specific 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
register()
in conjunction with
forget()
. See here for details.