|
| 1 | +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. |
| 2 | + |
| 3 | +from __future__ import annotations |
| 4 | + |
| 5 | +import threading |
| 6 | +from typing import Any, Callable |
| 7 | + |
| 8 | +EventHandler = Callable[..., Any] |
| 9 | + |
| 10 | + |
| 11 | +class EventHandlerRegistry: |
| 12 | + """Thread-safe (optional) registry of event handlers.""" |
| 13 | + |
| 14 | + def __init__(self, *, use_lock: bool = False) -> None: |
| 15 | + self._handlers: dict[str, list[EventHandler]] = {} |
| 16 | + self._once_ids: set[int] = set() |
| 17 | + self._lock: threading.Lock | None = threading.Lock() if use_lock else None |
| 18 | + |
| 19 | + def _acquire(self) -> None: |
| 20 | + if self._lock is not None: |
| 21 | + self._lock.acquire() |
| 22 | + |
| 23 | + def _release(self) -> None: |
| 24 | + if self._lock is not None: |
| 25 | + self._lock.release() |
| 26 | + |
| 27 | + def add(self, event_type: str, handler: EventHandler, *, once: bool = False) -> None: |
| 28 | + self._acquire() |
| 29 | + try: |
| 30 | + handlers = self._handlers.setdefault(event_type, []) |
| 31 | + handlers.append(handler) |
| 32 | + if once: |
| 33 | + self._once_ids.add(id(handler)) |
| 34 | + finally: |
| 35 | + self._release() |
| 36 | + |
| 37 | + def remove(self, event_type: str, handler: EventHandler) -> None: |
| 38 | + self._acquire() |
| 39 | + try: |
| 40 | + handlers = self._handlers.get(event_type) |
| 41 | + if handlers is not None: |
| 42 | + try: |
| 43 | + handlers.remove(handler) |
| 44 | + except ValueError: |
| 45 | + pass |
| 46 | + self._once_ids.discard(id(handler)) |
| 47 | + finally: |
| 48 | + self._release() |
| 49 | + |
| 50 | + def get_handlers(self, event_type: str) -> list[EventHandler]: |
| 51 | + """Return a snapshot of handlers for the given event type, removing once-handlers.""" |
| 52 | + self._acquire() |
| 53 | + try: |
| 54 | + handlers = self._handlers.get(event_type) |
| 55 | + if not handlers: |
| 56 | + return [] |
| 57 | + result = list(handlers) |
| 58 | + to_remove = [h for h in result if id(h) in self._once_ids] |
| 59 | + for h in to_remove: |
| 60 | + handlers.remove(h) |
| 61 | + self._once_ids.discard(id(h)) |
| 62 | + return result |
| 63 | + finally: |
| 64 | + self._release() |
| 65 | + |
| 66 | + def has_handlers(self, event_type: str) -> bool: |
| 67 | + self._acquire() |
| 68 | + try: |
| 69 | + handlers = self._handlers.get(event_type) |
| 70 | + return bool(handlers) |
| 71 | + finally: |
| 72 | + self._release() |
| 73 | + |
| 74 | + def merge_into(self, target: EventHandlerRegistry) -> None: |
| 75 | + """Move all handlers from this registry into *target*, then clear self.""" |
| 76 | + self._acquire() |
| 77 | + try: |
| 78 | + for event_type, handlers in self._handlers.items(): |
| 79 | + for handler in handlers: |
| 80 | + once = id(handler) in self._once_ids |
| 81 | + target.add(event_type, handler, once=once) |
| 82 | + self._handlers.clear() |
| 83 | + self._once_ids.clear() |
| 84 | + finally: |
| 85 | + self._release() |
0 commit comments