Files
overub/core/events.py
2025-12-21 17:12:32 +01:00

47 lines
1.5 KiB
Python

from dataclasses import dataclass, field
from typing import Any, Awaitable, Callable, Dict, List, Tuple
from core.error_handler import capture_errors
from core.logger import get_logger
logger = get_logger("core.events")
EventHandler = Callable[["Event"], Awaitable[None]]
@dataclass
class Event:
name: str
payload: Dict[str, Any] = field(default_factory=dict)
cancelled: bool = False
def cancel(self) -> None:
self.cancelled = True
class EventDispatcher:
def __init__(self) -> None:
self._handlers: Dict[str, List[Tuple[int, EventHandler]]] = {}
def on(self, event_name: str, handler: EventHandler, priority: int = 50) -> None:
handlers = self._handlers.setdefault(event_name, [])
handlers.append((priority, capture_errors(handler)))
handlers.sort(key=lambda item: item[0])
def off(self, event_name: str, handler: EventHandler) -> None:
if event_name not in self._handlers:
return
self._handlers[event_name] = [
item for item in self._handlers[event_name] if item[1] != handler
]
async def emit(self, event_name: str, **payload: Any) -> Event:
event = Event(name=event_name, payload=payload)
handlers = list(self._handlers.get(event_name, []))
for _, handler in handlers:
await handler(event)
if event.cancelled:
logger.debug("Event %s cancelled", event_name)
break
return event