ExternalHandler A variant Handler for external executable actions (such as bash scripts).
Handler Class representing a reactive flag handler.
discover Discover handlers based on convention.
dispatch Dispatch registered handlers.


exception charms.reactive.bus.BrokenHandlerException(path)

Bases: Exception

class charms.reactive.bus.ExternalHandler(filepath)

Bases: charms.reactive.bus.Handler

A variant Handler for external executable actions (such as bash scripts).

External handlers must adhere to the following protocol:

  • The handler can be any executable
  • When invoked with the --test command-line flag, it should exit with an exit code of zero to indicate that the handler should be invoked, and a non-zero exit code to indicate that it need not be invoked. It can also provide a line of output to be passed to the --invoke call, e.g., to indicate which sub-handlers should be invoked. The handler should not perform its action when given this flag.
  • When invoked with the --invoke command-line flag (which will be followed by any output returned by the --test call), the handler should perform its action(s).

Call the external handler to be invoked.

classmethod register(filepath)

Call the external handler to test whether it should be invoked.

class charms.reactive.bus.FlagWatch

Bases: object

classmethod change(flag)
classmethod commit()
classmethod iteration(i)
key = 'reactive.state_watch'
classmethod reset()
classmethod watch(watcher, flags)
class charms.reactive.bus.Handler(action, suffix=None)

Bases: object

Class representing a reactive flag handler.


Add arguments to be passed to the action when invoked.

Parameters:args – Any sequence or iterable, which will be lazily evaluated to provide args. Subsequent calls to add_args() can be used to add additional arguments.

Add a callback to be run after the action is invoked.


Add a new predicate callback to this handler.

classmethod clear()

Clear all registered handlers.

classmethod get(action, suffix=None)

Get or register a handler for the given action.

  • action (func) – Callback that is called when invoking the Handler
  • suffix (func) – Optional suffix for the handler’s ID
classmethod get_handlers()

Get all registered handlers.


Whether or not this Handler has had any args added via add_args().


Invoke this handler.


Register flags as being relevant to this handler.

Relevant flags will be used to determine if the handler should be re-invoked due to changes in the set of active flags. If this handler has already been invoked during this dispatch() run and none of its relevant flags have been set or removed since then, then the handler will be skipped.

This is also used for linting and composition purposes, to determine if a layer has unhandled flags.


Check the predicate(s) and return True if this handler should be invoked.

Discover handlers based on convention.

Handlers will be loaded from the following directories and their subdirectories:

  • $CHARM_DIR/reactive/
  • $CHARM_DIR/hooks/reactive/
  • $CHARM_DIR/hooks/relations/

They can be Python files, in which case they will be imported and decorated functions registered. Or they can be executables, in which case they must adhere to the ExternalHandler protocol.


Dispatch registered handlers.

When dispatching in restricted mode, only matching hook handlers are executed.

Handlers are dispatched according to the following rules:

  • Handlers are repeatedly tested and invoked in iterations, until the system settles into quiescence (that is, until no new handlers match to be invoked).
  • In the first iteration, @hook and @action handlers will be invoked, if they match.
  • In subsequent iterations, other handlers are invoked, if they match.
  • Added flags will not trigger new handlers until the next iteration, to ensure that chained flags are invoked in a predictable order.
  • Removed flags will cause the current set of matched handlers to be re-tested, to ensure that no handler is invoked after its matching flag has been removed.
  • Other than the guarantees mentioned above, the order in which matching handlers are invoked is undefined.
  • Flags are preserved between hook and action invocations, and all matching handlers are re-invoked for every hook and action. There are decorators and helpers to prevent unnecessary reinvocations, such as only_once().