coma.core

Implementation of the core coma user interface.

Module Attributes

@command(cmd: Callable | type | None = None, *, name: str | None = None, parser_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, pre_config_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, config_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, post_config_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, pre_init_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, init_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, post_init_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, pre_run_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, run_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, post_run_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.SHARED, signature_inspector: SignatureInspectorProtocol | None = None, persistence_manager: PersistenceManager | None = None, parser_kwargs: dict[str, Any] | None = None, **supplemental_configs: Any)[source]

Registers a command that might be invoked upon waking from a coma.

Registers a command with ArgumentParser.add_subparsers().add_parser() using the given registration data (name, hooks, config declarations, persistence manager, and supplemental configs) and the given parser kwargs.

Note

coma’s architecture follows the Template design pattern with hooks intended to add or modify behavior. Pre-defined hooks specify coma’s default behavior. Pre-defined hook factories enable one-line deployment of small tweaks on the core default behavior. coma has very few baked in assumptions. Nearly all behavior can be drastically changed with user-defined hooks. For detailed tutorials and usage examples of both the default behavior and implementation of user-defined hooks, see the extensive online docs.

Usage modes:

As a decorator:

@command(name="command_name", ...)
def my_cmd(...):
    ...

As a normal function call:

def my_cmd(main_cfg: SomeConfig, **extra_cli_configs):
    ...

coma.command(name="command_name", cmd=my_cmd, ...)

Both decorator and procedural modes also accept a class argument:

@coma.command(name="command_name", ...)
class MyCmd(...):
    def run(self):
        ...

or:

class MyCmd(...):
    def run(self):
        ...

coma.command(name="command_name", cmd=MyCmd, ...)

Note

It is invalid to specify the cmd parameter in decorator mode.

Note

Throughout, we refer to “the command”, which applies regardless of usage mode (decorator or procedural) and regardless of whether the command object is a function or a class (my_cmd or MyCmd, respectively, in the above examples). The “command signature” refers directly to the function signature if the command is a function, or to the signature of the __init__() method if the command is a class.

Note

When the command is a function, it gets wrapped in a class internally. Therefore, unless you really know what you are doing, it is unwise to inspect or change the command in any user-supplied hooks. Instead, rely on the registered command name (which is guaranteed to be unique) to delegate reused functionality across the hooks.

Details:

The command’s signature is inspected (using signature_inspector) to infer and separate Config s from other parameters. A rich set of options exist for declaring which parameters are config or regular parameters. See SignatureInspector for details.

Additional configs not present in the command signature can be supplied through supplemental_configs. These can be helpful for providing additional information to the hooks beyond what the command itself requires.

All hooks default to the SHARED sentinel, which means they get replaced at runtime with the corresponding shared hook from wake(). Setting a hook to None disables that hook entirely. Setting a hook to the DEFAULT sentinel, means it gets replaced at runtime with the corresponding pre-defined default hook. Because all the shared hooks default to DEFAULT, SHARED and DEFAULT might feel interchangeable. However, once a shared hook in wake() is replaced with a user-defined hook, they act differently. Setting a hook to DEFAULT here recovers the default functionality for this specific command, whereas SHARED uses the user-defined replacement.

Note

Hooks can be “plain” objects as just described, or they can be (recursive) sequences of such “plain” objects. This syntax acts as a convenient shorthand that enables composing larger hooks from smaller components without having to define a wrapper hook whose only purpose is to compose component hooks.

Parameters:
  • name (CommandName) – Any (unique) valid command name according to argparse. If None, cmd.__name__.lower() is used instead.

  • cmd (Command, optional) – A command class or function. If None, use decorator mode. If given, use procedural mode.

  • parser_hook (AugmentedHook) – An optional command-specific hook with parser hook semantics.

  • pre_config_hook (AugmentedHook) – An optional command-specific hook with pre config hook semantics.

  • config_hook (AugmentedHook) – An optional command-specific hook with config hook semantics.

  • post_config_hook (AugmentedHook) – An optional command-specific hook with post config hook semantics.

  • pre_init_hook (AugmentedHook) – An optional command-specific hook with pre init hook semantics.

  • init_hook (AugmentedHook) – An optional command-specific hook with init hook semantics.

  • post_init_hook (AugmentedHook) – An optional command-specific hook with post init hook semantics.

  • pre_run_hook (AugmentedHook) – An optional command-specific hook with pre run hook semantics.

  • run_hook (AugmentedHook) – An optional command-specific hook with run hook semantics.

  • post_run_hook (AugmentedHook) – An optional command-specific hook with post run hook semantics.

  • signature_inspector (SignatureInspectorProtocol, optional) – The SignatureInspectorProtocol to use for inspecting the cmd object’s signature. If None, a SignatureInspector with default parameters is used.

  • persistence_manager (PersistenceManager, optional) – Manager for the serializing of configs. If None, a manager with default parameters is used.

  • parser_kwargs (Parameters, optional) – Keyword arguments passed along to the ArgumentParser sub-parser that will be created just for this command.

  • **supplemental_configs (Any) – Additional configs not present in the command signature. Any omegaconf-compatible config type is valid.

See also

wake(*import_commands: Any, parser: ArgumentParser | None = None, cli_args: Sequence[str] | None = None, cli_namespace: Any | None = None, parser_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.DEFAULT, pre_config_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = None, config_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.DEFAULT, post_config_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = None, pre_init_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = None, init_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.DEFAULT, post_init_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = None, pre_run_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = None, run_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = HookSentinels.DEFAULT, post_run_hook: Callable[[T], T | None] | HookSentinels | None | Sequence[Callable[[T], T | None] | HookSentinels | None] = None, **subparsers_kwargs) None[source]

Wakes from a coma.

Starts up coma with an optional argument parser, optional shared hooks, and optional subparsers keyword arguments. Any shared hooks are applied globally to every registered command.

Note

coma’s architecture follows the Template design pattern with hooks intended to add or modify behavior. Pre-defined hooks specify coma’s default behavior. Pre-defined hook factories enable one-line deployment of small tweaks on the core default behavior. coma has very few baked in assumptions. Nearly all behavior can be drastically changed with user-defined hooks. For detailed tutorials and usage examples of both the default behavior and implementation of user-defined hooks, see the extensive online docs.

All hooks default to the DEFAULT sentinel, which means they get replaced at runtime with the corresponding pre-defined default hook. Setting a hook to None disables it. The SHARED sentinel is not allowed in wake() since it would lead to infinite regress. See command() for usage of SHARED.

Note

Hooks can be “plain” objects as just described, or they can be (recursive) sequences of such “plain” objects. This syntax acts as a convenient shorthand that enables composing larger hooks from smaller components without having to define a wrapper hook whose only purpose is to compose component hooks.

Note

A command is only registered (via command()) if the module in which the command is declared is imported at runtime. This is standard Python behavior: non-imported code is not interpreted by the VM and not available at runtime. This is a bit obscured by the behind-the-scenes magic done by command(). But this magic only works if the command code runs (via being imported) at some point before the call to wake().

One way to achieve this is by having a from . import module statement in the top-level __init__.py for every module with a command. That forces each command module to be imported. Alternatively, a common pattern is to put lightweight (one-line) command() wrappers around calls to the main/workhorse functions all in a single module (typically, the same module that calls wake()). Finally, a third alternative is to pass all commands scattered throughout a codebase to *import_commands. The contents of *import_commands is fully ignored by wake(). However, it forces the Python VM to import each of the provided modules, thus registering the commands. Providing the imported commands to *import_commands is not required (merely importing them is enough), but doing so prevents linters from complaining of unused import statements.

Example:

@coma.command
def cmd(...):
    ...

if __name__ == "__main__":
    coma.wake(parser=..., parser_hook=..., ...)
Parameters:
  • *import_commands (Any) – Fully ignored. Optional mechanism to forcibly import commands scattered throughout a codebase.

  • parser (argparse.ArgumentParser, optional) – Top-level ArgumentParser to use. If None, an ArgumentParser with default parameters is used instead.

  • cli_args (Sequence[str], optional) – Command line arguments to use with parser. If None, sys.argv is used instead.

  • cli_namespace (Any, optional) – The namespace object to pass to parse_known_args(). If None, use the argparse default.

  • parser_hook (AugmentedHook) – An optional shared hook with parser hook semantics.

  • pre_config_hook (AugmentedHook) – An optional shared hook with pre config hook semantics.

  • config_hook (AugmentedHook) – An optional shared hook with config hook semantics.

  • post_config_hook (AugmentedHook) – An optional shared hook with post config hook semantics.

  • pre_init_hook (AugmentedHook) – An optional shared hook with pre init hook semantics.

  • init_hook (AugmentedHook) – An optional shared hook with init hook semantics.

  • post_init_hook (AugmentedHook) – An optional shared hook with post init hook semantics.

  • pre_run_hook (AugmentedHook) – An optional shared hook with pre run hook semantics.

  • run_hook (AugmentedHook) – An optional shared hook with run hook semantics.

  • post_run_hook (AugmentedHook) – An optional shared hook with post run hook semantics.

  • **subparsers_kwargs (Any) – Keyword arguments to pass along to ArgumentParser.add_subparsers()

Raises:
  • WakeException – If no commands are registered or the command line arguments fail to invoke a command.

  • ValueError – If any Hook argument is or contains the SHARED sentinel, which would lead to infinite regress.

  • Others – As may be raised by argparse or any of the hooks or commands.

See also

  • The online docs for detailed tutorials and examples.

  • command()

class WakeException[source]

Raised when wake() fails.