Source code for aiomisc.signal

import inspect
from typing import Any, Callable, FrozenSet, Set, TypeVar, Union


T = TypeVar("T")
ReceiverType = Callable[..., Any]
_ReceiverSetType = Union[Set[ReceiverType], FrozenSet[ReceiverType]]


[docs]class Signal: __slots__ = ("_receivers", "_is_frozen") def __init__(self) -> None: self._receivers = set() # type: _ReceiverSetType
[docs] def connect(self, receiver: ReceiverType) -> None: if self.is_frozen: raise RuntimeError( "Can't connect receiver (%r) to the frozen signal", receiver, ) if not inspect.iscoroutinefunction(receiver): raise RuntimeError("%r is not a coroutine function", receiver) self._receivers.add(receiver) # type: ignore
[docs] def disconnect(self, receiver: ReceiverType) -> None: if self.is_frozen: raise RuntimeError( "Can't connect receiver (%r) to the frozen signal", receiver, ) self._receivers.discard(receiver) # type: ignore
[docs] async def call(self, *args: Any, **kwargs: Any) -> None: for receiver in self._receivers: await receiver(*args, **kwargs)
[docs] def copy(self) -> "Signal": clone = Signal() # unfreeze on copy clone._receivers = set(self._receivers) return clone
@property def is_frozen(self) -> bool: return isinstance(self._receivers, frozenset)
[docs] def freeze(self) -> None: self._receivers = frozenset(self._receivers)
[docs]def receiver(s: Signal) -> Callable[..., Callable[..., T]]: def decorator(func: Callable[..., T]) -> Callable[..., T]: s.connect(func) return func return decorator