Command
The @command decorator is a lightweight wrapper around
register(), which acts as a convenience for simple use cases.
The advantage of this decorator is to remove the boilerplate of
register()ing a command when its registration is a one-to-one
mapping to the command signature. For example, consider the following multi-config
registration:
from dataclasses import dataclass
import coma
@dataclass
class Config1:
...
@dataclass
class Config2:
...
def greet(cfg_1: Config1, cfg_2: Config2, cfg_3: dict):
print("Hello World!")
print(cfg_1)
print(cfg_2)
print(cfg_3)
if __name__ == "__main__":
coma.register("greet", greet, cfg_1=Config1, cfg_2=Config2, cfg_3={})
coma.wake()
Notice that the function signature of greet is a one-to-one mapping to the
registration. Specifically, each parameter of the function signature is a config, and
the parameter name and type annotation of each config in the function signature matches
a config identifier and type pair in the registration. As such, we can use the
@command decorator to remove the boilerplate registration:
from dataclasses import dataclass
from coma import command
import coma
@dataclass
class Config1:
...
@dataclass
class Config2:
...
@command("greet")
def greet(cfg_1: Config1, cfg_2: Config2, cfg_3: dict):
print("Hello World!")
print(cfg_1)
print(cfg_2)
print(cfg_3)
if __name__ == "__main__":
# Removed call to coma.register()
coma.wake()
This decorator works in simple use cases. It does not work if the decorated object’s
signature contains non-config parameters (which is a rare and advanced use case). It also
does not work with forget() (a more common, if still slightly
advanced use case). For such advanced uses cases, an explicit call to
register() must be made instead.
Note
When the command is defined as a class instead of a function, it is the signature
of the class’s __init__() method that must match the registration format.
Just like register(), the @command decorator accepts
local hooks and parser keywords arguments. These are passed directly to
register() without modification or processing:
from dataclasses import dataclass
from coma import command
import coma
@command(
"greet",
parser_hook=...,
pre_config_hook=...,
config_hook=...,
post_config_hook=...,
pre_init_hook=...,
init_hook=...,
post_init_hook=...,
pre_run_hook=...,
run_hook=...,
post_run_hook=...,
parser_kwargs=...,
)
def greet():
print("Hello World!")
if __name__ == "__main__":
coma.wake()
Warning
Be aware that, under the hood, the @command decorator delays the call to
register() until after the call to
initiate(). This should not cause issues, but may lead to
unintended side effects if mucking around with Python’s inspect module on the
Coma singleton object (which you should not do unless you really know what
you are doing).