Source code for corx.command
import abc
import dataclasses
import datetime
import typing
import uuid
from corx.dispatcher import Dispatchable, Executor, get_dispatcher
__all__ = [
'Command',
'CommandType',
'CommandExecutor'
]
[docs]
@dataclasses.dataclass
class Command(Dispatchable, abc.ABC):
created_at: float = dataclasses.field(init=False, default_factory=datetime.datetime.now().timestamp)
uuid: str = dataclasses.field(init=False, default_factory=lambda: str(uuid.uuid4()))
CommandType = typing.TypeVar('CommandType', bound=typing.Type[Command])
CommandHandlerType = typing.TypeVar('CommandHandlerType', bound=typing.Callable[[Command], typing.Union[typing.Coroutine, typing.Any]])
def handles(command: CommandType):
def wrap(method):
get_dispatcher().register(command, method)
return method
return wrap
[docs]
class CommandExecutor(Executor):
_registry: typing.Dict[CommandType, CommandHandlerType] = dict()
[docs]
def register(self, dispatchable: CommandType, executable: CommandHandlerType):
if dispatchable in self._registry:
raise Exception(f'{dispatchable} is already registered with {self._registry[dispatchable]}.')
self._registry[dispatchable] = executable
[docs]
def execute(self, dispatchable: Command):
command_class: CommandType = type(dispatchable)
handler_method = self._registry.get(command_class)
if handler_method is None:
raise Exception(f'No handler for {command_class.__name__}')
result = handler_method(dispatchable)
if isinstance(result, typing.Coroutine):
self._loop.push(result)