event#

bamengine.core.decorators.event(cls=None, *, name=None, after=None, before=None, replace=None, **dataclass_kwargs)[source]#

Decorator to define an Event with automatic inheritance and dataclass.

This decorator dramatically simplifies Event definition by: 1. Making the class inherit from Event (if not already) 2. Applying @dataclass(slots=True) 3. Handling registration automatically 4. Optionally storing pipeline hook metadata for explicit positioning

Parameters:
  • cls (type | None) – The class to decorate (provided automatically when used without parens)

  • name (str | None) – Optional custom name for the event. If None, uses class name (snake_case).

  • after (str | None) – Insert this event immediately after the target event in the pipeline. Hooks are applied explicitly via sim.use_events() or pipeline.apply_hooks().

  • before (str | None) – Insert this event immediately before the target event in the pipeline.

  • replace (str | None) – Replace the target event with this event in the pipeline.

  • **dataclass_kwargs (Any) – Additional keyword arguments to pass to @dataclass. By default, slots=True is set.

Returns:

The decorated class or a decorator function

Return type:

type | Callable

Raises:

ValueError – If more than one of after, before, or replace is specified.

Examples

Simplest usage (no inheritance needed):

>>> from bamengine import Simulation
>>> @event
... class Planning:
...     def execute(self, sim: Simulation) -> None:
...         pass  # implementation

With custom name:

>>> @event(name="my_planning")
... class Planning:
...     def execute(self, sim: Simulation) -> None:
...         pass  # implementation

With pipeline hook (inserted after another event):

>>> @event(after="firms_pay_dividends")
... class MyCustomEvent:
...     def execute(self, sim: Simulation) -> None:
...         pass  # Applied via sim.use_events(MyCustomEvent)

With pipeline hook (inserted before another event):

>>> @event(before="firms_adjust_price")
... class PrePricingCheck:
...     def execute(self, sim: Simulation) -> None:
...         pass  # Applied via sim.use_events(PrePricingCheck)

With pipeline hook (replaces another event):

>>> @event(replace="firms_decide_desired_production")
... class CustomProductionRule:
...     def execute(self, sim: Simulation) -> None:
...         pass  # This event replaces the original

Notes

Pipeline hooks are stored as class attributes (_hook_after, _hook_before, _hook_replace) and applied explicitly via sim.use_events() or pipeline.apply_hooks().

Multiple events can target the same hook point. They are inserted in the order passed to apply_hooks() (first = closest to target event).

See also

Pipeline

Pipeline that applies hooks

use_events()

Apply hooks to simulation