Dispatchers
- class domprob.dispatchers.basic.BasicDispatcher(*instruments)[source]
Bases:
DispatcherProtocolDispatches observations to registered instruments.
This class manages: - Finding the appropriate instrument for a given observation. - Dispatching announcements to the relevant instruments.
- Parameters:
*instruments (_Instrument) – Variable number of instrument instances.
Example
>>> from abc import ABC, abstractmethod >>> >>> class BaseInstrument(ABC): ... @abstractmethod ... def add(self): ... pass ... >>> class LoggerInstrument: ... @staticmethod ... def add(): ... return "Log message added!" ... >>> class AnalyticsInstrument: ... @staticmethod ... def add(): ... return "Analytics entry added!" ... >>> dispatcher = BasicDispatcher(LoggerInstrument(), AnalyticsInstrument()) >>> dispatcher BasicDispatcher(instruments=('<domprob.dispatchers.basic.LoggerInstrument object at 0x...>', '<domprob.dispatchers.basic.AnalyticsInstrument object at 0x...>')) >>> >>> from domprob import announcement, BaseObservation >>> >>> class SomeObservation(BaseObservation): ... @announcement(LoggerInstrument) ... @announcement(AnalyticsInstrument) ... def foo(self, instrument: BaseInstrument) -> None: ... print(instrument.add()) ... >>> obs = SomeObservation() >>> dispatcher.dispatch(obs) Analytics entry added! Log message added!
- __repr__()[source]
Return a string representation of the dispatcher.
- Returns:
- A string representation of the dispatcher and its
instruments.
- Return type:
str
Example
>>> from abc import ABC, abstractmethod >>> >>> class BaseInstrument(ABC): ... @abstractmethod ... def add(self): ... pass ... >>> class LoggerInstrument: ... @staticmethod ... def add(): ... return "Log message added!" ... >>> class AnalyticsInstrument: ... @staticmethod ... def add(): ... return "Analytics entry added!" ... >>> dispatcher = BasicDispatcher(LoggerInstrument(), AnalyticsInstrument()) >>> repr(dispatcher) "BasicDispatcher(instruments=('<domprob.dispatchers.basic.LoggerInstrument object at 0x...>', '<domprob.dispatchers.basic.AnalyticsInstrument object at 0x...>'))"
- _abc_impl = <_abc._abc_data object>
- _dispatch_ann(observation, announcement)[source]
Process an announcement by identifying the required instrument.
This method retrieves the correct instrument instance based on the announcement and calls _instrum_announce.
- Parameters:
observation (_Obs) – The observation being processed.
announcement (_Ann) – The announcement method to invoke.
- Return type:
None
- static _dispatch_instrum_ann(observation, announcement, instrument)[source]
Invoke an announcement method on an instrument.
This method triggers the specified announcement method on the given instrument instance if it is available.
- Parameters:
observation (_Obs) – The observation being processed.
announcement (_Ann) – The announcement method to invoke.
instrument (_Instrument | None) – The target instrument instance, if available.
- Return type:
None
- _is_protocol = False
- _is_runtime_protocol = True
- dispatch(observation)[source]
Dispatch an observation to all applicable instruments.
This method retrieves all announcements from the observation and processes them.
- Parameters:
observation (_Obs) – The observation to process.
- Return type:
None
Example
>>> from abc import ABC, abstractmethod >>> >>> class BaseInstrument(ABC): ... @abstractmethod ... def add(self): ... pass ... >>> class LoggerInstrument: ... @staticmethod ... def add(): ... return "Log message added!" ... >>> class AnalyticsInstrument: ... @staticmethod ... def add(): ... return "Analytics entry added!" ... >>> dispatcher = BasicDispatcher(LoggerInstrument(), AnalyticsInstrument()) >>> dispatcher BasicDispatcher(instruments=('<domprob.dispatchers.basic.LoggerInstrument object at 0x...>', '<domprob.dispatchers.basic.AnalyticsInstrument object at 0x...>')) >>> >>> from domprob import announcement, BaseObservation >>> >>> class SomeObservation(BaseObservation): ... @announcement(LoggerInstrument) ... @announcement(AnalyticsInstrument) ... def foo(self, instrument: BaseInstrument) -> None: ... print(instrument.add()) ... >>> obs = SomeObservation() >>> dispatcher.dispatch(obs) Analytics entry added! Log message added!
- class domprob.dispatchers.basic.InstrumentImpRegistry(*instruments)[source]
Bases:
Collection[_Instrument]Registry for instrument implementations, allowing lookup and caching.
This class acts as a collection that stores instruments and supports:
Efficient retrieval of instruments by type.
Caching of previously looked-up instruments for performance optimization.
- Parameters:
*instruments (_Instrument) – Variable number of instrument instances to store.
Example
>>> class LoggerInstrument: ... @staticmethod ... def add(): ... return "Log message added!" ... >>> class AnalyticsInstrument: ... @staticmethod ... def add(): ... return "Analytics entry added!" ... >>> logger = LoggerInstrument() >>> analytics = AnalyticsInstrument() >>> >>> registry = InstrumentImpRegistry(logger, analytics) >>> logger_ = registry.get(LoggerInstrument) >>> >>> logger == logger_ True >>> print(registry.get(object)) None
- __contains__(item)[source]
Check if an instrument exists in the registry.
- Parameters:
item (
object) – The instrument instance or class to check.- Returns:
True if the instrument is present, otherwise False.
- Return type:
bool
Example
>>> class LoggerInstrument: ... @staticmethod ... def add(): ... return "Log message added!" ... >>> class AnalyticsInstrument: ... @staticmethod ... def add(): ... return "Analytics entry added!" ... >>> logger = LoggerInstrument() >>> analytics = AnalyticsInstrument() >>> >>> registry = InstrumentImpRegistry(logger, analytics) >>> logger in registry True >>> object in registry False
- __iter__()[source]
Iterate over stored instruments.
- Returns:
An iterator over the instruments.
- Return type:
Iterator[_Instrument]
Example
>>> class LoggerInstrument: ... @staticmethod ... def add(): ... return "Log message added!" ... >>> class AnalyticsInstrument: ... @staticmethod ... def add(): ... return "Analytics entry added!" ... >>> logger = LoggerInstrument() >>> analytics = AnalyticsInstrument() >>> >>> registry = InstrumentImpRegistry(logger, analytics) >>> >>> for instrument in registry: ... print(instrument.add()) ... Log message added! Analytics entry added!
- __len__()[source]
Return the number of stored instruments.
- Returns:
The number of instruments in the registry.
- Return type:
int
Example
>>> class LoggerInstrument: ... @staticmethod ... def add(): ... return "Log message added!" ... >>> class AnalyticsInstrument: ... @staticmethod ... def add(): ... return "Analytics entry added!" ... >>> logger = LoggerInstrument() >>> analytics = AnalyticsInstrument() >>> >>> registry = InstrumentImpRegistry(logger, analytics) >>> >>> len(registry) 2
- __repr__()[source]
Return a string representation of the registry.
- Returns:
The string representation of the registry.
- Return type:
str
- _abc_impl = <_abc._abc_data object>
- static _is_hashable(obj)[source]
Check if an object is hashable.
- Parameters:
obj (Any) – The object to check.
- Returns:
True if the object is hashable, False otherwise.
- Return type:
bool
- get(instrument_cls, required=False)[source]
Retrieve an instrument instance by its class type.
If the instrument class is hashable, results are cached for efficiency.
- Parameters:
instrument_cls (
type[TypeVar(_Instrument, bound=Any)]) – The class type of the instrument to retrieve.required (
bool) – If True, raises a KeyError if the instrument is not found. If False, returns None.
- Returns:
- The retrieved instrument instance or
None if not found.
- Return type:
_Instrument | None
- Raises:
KeyError – If required is True and the instrument is not found.
Example
>>> class LoggerInstrument: ... @staticmethod ... def add(): ... return "Log message added!" ... >>> class AnalyticsInstrument: ... @staticmethod ... def add(): ... return "Analytics entry added!" ... >>> logger = LoggerInstrument() >>> analytics = AnalyticsInstrument() >>> >>> registry = InstrumentImpRegistry(logger) >>> >>> registry.get(LoggerInstrument).add() 'Log message added!' >>> registry.get(AnalyticsInstrument, required=True) Traceback (most recent call last): ... KeyError: 'Instrument `AnalyticsInstrument` not found in available implementations: `<domprob.dispatchers.basic.LoggerInstrument object at 0x...>`'
- exception domprob.dispatchers.basic.ReqInstrumException(observation, announcement, req_supp_instrum, *instrum_imps)[source]
Bases:
DispatcherExceptionException raised when a required instrument is missing an implementation of the same type for an observation announcement.
An instrument is marked as required with the required flag in the @announcement decorator:
>>> from domprob import announcement, BaseObservation >>> >>> class SomeObservation(BaseObservation): ... ... @announcement(..., required=True) ... def some_method(self, instrument: ...) -> None: ... ... ...
- Parameters:
observation (_Obs) – The observation instance where the missing instrument was required.
announcement (_Ann) – The announcement method that failed due to the missing instrument.
req_supp_instr (type[_Instrument]) – The instrument type that was expected but not found.
*instrum_imps (_Instrument) – The available instrument instances at the time of the failure.
- __repr__()
Return repr(self).
- add_note(object, /)
Exception.add_note(note) – add a note to the exception
- args
- property msg: str
Constructs a descriptive error message for the exception.
- Returns:
- A formatted string detailing the missing instrument,
the observation method where it was required, and the available instrument implementations.
- Return type:
str
- with_traceback(object, /)
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception domprob.dispatchers.dispatcher.DispatcherException[source]
Bases:
DomprobExceptionBase exception for errors occurring within dispatchers.
This exception is raised when an error occurs while processing observations within a dispatcher.
It inherits from DomprobException, allowing it to be caught alongside other domain-specific exceptions.
- __repr__()
Return repr(self).
- add_note(object, /)
Exception.add_note(note) – add a note to the exception
- args
- with_traceback(object, /)
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- class domprob.dispatchers.dispatcher.DispatcherProtocol(*args, **kwargs)[source]
Bases:
ProtocolProtocol defining the structure for dispatchers handling domain observations.
Classes implementing this protocol must define:
dispatch(): Processes an ObservationProtocol and returns a result.
__repr__(): Provides a string representation of the dispatcher.
This protocol is @runtime_checkable, meaning isinstance(dispatcher, DispatcherProtocol) can be used to verify conformance at runtime.
Example
>>> from domprob.dispatchers.dispatcher import DispatcherProtocol >>> from domprob.observations.observation import ObservationProtocol >>> >>> class ConcreteDispatcher: ... @staticmethod ... def dispatch(self, observation: ObservationProtocol) -> str: ... return "Processed observation" ... ... def __repr__(self) -> str: ... return "ConcreteDispatcher()" ... >>> dispatcher = ConcreteDispatcher() >>> assert isinstance(dispatcher, DispatcherProtocol)
- _abc_impl = <_abc._abc_data object>
- _is_protocol = True
- _is_runtime_protocol = True
- dispatch(observation)[source]
Dispatch an observation and return a result.
- Parameters:
observation (ObservationProtocol[_P, _R]) – The observation to process.
- Returns:
The result of processing the observation.
- Return type:
_R
Example
>>> from domprob import announcement, BaseObservation >>> from domprob.dispatchers.dispatcher import DispatcherProtocol >>> from domprob.observations.observation import ObservationProtocol >>> >>> class MyDispatcher: ... @staticmethod ... def dispatch(observation: ObservationProtocol) -> str: ... return "Handled" ... >>> dispatcher = MyDispatcher() >>> >>> class SomeInstrument: ... pass ... >>> class Obs(BaseObservation): ... @announcement(SomeInstrument) ... def foo(self, instrument: SomeInstrument) -> str: ... pass ... >>> result = dispatcher.dispatch(Obs()) >>> print(result) Handled