Skip to content

Protocols

Protocol definitions for duck-typing compatibility across the simulation framework.

Protocol definitions for duck-typed simulation components.

This module defines structural types (Protocols) that allow any class with the right methods to participate in a simulation, without requiring inheritance from Entity.

Two approaches are supported: 1. Inherit from Entity (traditional, explicit contract) 2. Implement the Simulatable protocol (duck typing, no inheritance required)

Example using duck typing

class MyClient: def init(self, name: str): self.name = name self._clock: Clock | None = None

def set_clock(self, clock: Clock) -> None:
    self._clock = clock

@property
def now(self) -> Instant:
    return self._clock.now

def handle_event(self, event: Event) -> list[Event] | None:
    # process event
    return []

Or use the @simulatable decorator for automatic clock injection: from happysimulator.core.decorators import simulatable

@simulatable
class MyClient:
    def __init__(self, name: str):
        self.name = name

    def handle_event(self, event: Event) -> list[Event] | None:
        print(f"Processing at {self.now}")  # self.now is injected
        return []

Simulatable

Bases: Protocol

Protocol for objects that can participate in a simulation.

Any class that implements these methods can be used as an entity in the simulation, without inheriting from Entity. The @runtime_checkable decorator allows isinstance() checks at runtime.

Required attributes

name: Identifier for logging and debugging.

Required methods

set_clock: Called by Simulation to inject the shared clock. handle_event: Process incoming events and return reactions.

Optional methods

has_capacity: Override to model resource constraints (defaults to True).

set_clock

set_clock(clock: Clock) -> None

Receive the simulation clock for time-aware operations.

Called automatically by Simulation during initialization. Store the clock to access simulation time via clock.now.

handle_event

handle_event(event: Event) -> HandleEventReturn

Process an incoming event and return any resulting events.

Returns:

Name Type Description
Generator HandleEventReturn

For multi-step processes. Yield delays; optionally return events on completion.

HandleEventReturn

list[Event] | Event | None: For immediate, single-step responses.

HasCapacity

Bases: Protocol

Optional protocol for entities with resource constraints.

Entities that implement has_capacity() can signal when they're unable to accept additional work (e.g., server at max connections).

has_capacity

has_capacity() -> bool

Check if this entity can accept additional work.