Forget
forget()
is a context manager designed for more advanced
use cases. It enables you to selectively forget global configs or hooks from an
initiate()
d coma.
Forgetting Global Hooks
coma
’s behavior can be easily tweaked, replaced, or extended using hooks.
These are covered in great detail in their own tutorial.
Here, the emphasis is on the difference between 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. When a local hook is being
register()
ed, the corresponding global hook can
only be replaced using forget()
.
For example, suppose we have a class-based command with a handle()
method
instead of the run()
method that coma
expects by default:
class HandleCommand:
def handle(self):
print("Hello Handle!")
In order to use this command, we need to tell coma
to:
Stop looking for
run()
. We willforget()
the existing global hook that does this.Start looking for
handle()
instead. We willregister()
a new local hook to do this.
import coma
class HandleCommand:
def handle(self):
print("Hello Handle!")
class RunCommand:
def run(self):
print("Hello Run!")
if __name__ == "__main__":
with coma.forget(run_hook=True):
coma.register("handle", HandleCommand,
run_hook=coma.hooks.run_hook.factory("handle"))
coma.register("run", RunCommand)
coma.wake()
In this example, we locally register()
ed a
run_hook
that tells coma
to call handle()
and we used the
forget()
context manager to get coma
to temporarily
forget its default run_hook
, which attempts to call run()
instead.
Note
coma
provides factory functions for some of the more common hooks.
In this example, we used coma.hooks.run_hook.factory()
, which
simply creates a function that in turn calls the provided attribute (in this
case, "handle"
) of the command object.
Because forget()
is a context manager, any commands
registered outside its context are unaffected. In this example, RunCommand
still functions normally.
$ python main.py handle
Hello Handle!
$ python main.py run
Hello Run!
Forgetting Global Configs
As with hooks, configs can be initiate()
d globally to all
commands or register()
ed locally to a specific command.
Let’s revisit the second of the Multiple Configurations examples
from the introductory tutorial to see how we can implement it
differently with forget()
:
from dataclasses import dataclass
import coma
@dataclass
class Greeting:
message: str = "Hello"
@dataclass
class Receiver:
entity: str = "World!"
if __name__ == "__main__":
coma.register("greet", lambda g, r: print(g.message, r.entity), Greeting, Receiver)
coma.register("leave", lambda r: print("Goodbye", r.entity), Receiver)
coma.wake()
Notice how, in the original example, the Receiver
config is
register()
ed (locally) to both commands. Instead, we
can initiate()
a coma with both configs so that they
are (globally) supplied to all commands, then forget()
the Greeting
config just for the leave
command:
from dataclasses import dataclass
import coma
@dataclass
class Greeting:
message: str = "Hello"
@dataclass
class Receiver:
entity: str = "World!"
if __name__ == "__main__":
coma.initiate(Greeting, Receiver)
coma.register("greet", lambda g, r: print(g.message, r.entity))
with coma.forget("greeting"):
coma.register("leave", lambda r: print("Goodbye", r.entity))
coma.wake()
Notice that forget()
takes the config identifier (in this case,
we used the default identifier, which is "greeting"
), not the config itself.
Note
Configs need to be uniquely identified per-command, but not across commands.