70 lines
2.5 KiB
Python
70 lines
2.5 KiB
Python
"""
|
|
Callback registry for decoupled event notifications.
|
|
|
|
Allows interfaces to notify about changes without knowing about features.
|
|
Features can register callbacks to be notified when automations change.
|
|
"""
|
|
|
|
import logging
|
|
from typing import Callable, List, Dict, Any
|
|
import asyncio
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class CallbackRegistry:
|
|
"""Registry for callbacks that can be triggered by interfaces without knowing about features."""
|
|
|
|
def __init__(self):
|
|
self._callbacks: Dict[str, List[Callable]] = {}
|
|
|
|
def register(self, event_type: str, callback: Callable):
|
|
"""Register a callback for a specific event type.
|
|
|
|
Args:
|
|
event_type: Type of event (e.g., 'automation.changed')
|
|
callback: Async or sync callback function
|
|
"""
|
|
if event_type not in self._callbacks:
|
|
self._callbacks[event_type] = []
|
|
self._callbacks[event_type].append(callback)
|
|
logger.debug(f"Registered callback for event type: {event_type}")
|
|
|
|
def unregister(self, event_type: str, callback: Callable):
|
|
"""Unregister a callback for a specific event type."""
|
|
if event_type in self._callbacks:
|
|
try:
|
|
self._callbacks[event_type].remove(callback)
|
|
logger.debug(f"Unregistered callback for event type: {event_type}")
|
|
except ValueError:
|
|
logger.warning(f"Callback not found for event type: {event_type}")
|
|
|
|
async def trigger(self, event_type: str, *args, **kwargs):
|
|
"""Trigger all callbacks registered for an event type.
|
|
|
|
Args:
|
|
event_type: Type of event to trigger
|
|
*args, **kwargs: Arguments to pass to callbacks
|
|
"""
|
|
if event_type not in self._callbacks:
|
|
return
|
|
|
|
callbacks = self._callbacks[event_type].copy() # Copy to avoid modification during iteration
|
|
|
|
for callback in callbacks:
|
|
try:
|
|
if asyncio.iscoroutinefunction(callback):
|
|
await callback(*args, **kwargs)
|
|
else:
|
|
callback(*args, **kwargs)
|
|
except Exception as e:
|
|
logger.error(f"Error executing callback for {event_type}: {str(e)}", exc_info=True)
|
|
|
|
def has_callbacks(self, event_type: str) -> bool:
|
|
"""Check if there are any callbacks registered for an event type."""
|
|
return event_type in self._callbacks and len(self._callbacks[event_type]) > 0
|
|
|
|
|
|
# Global singleton instance
|
|
callbackRegistry = CallbackRegistry()
|
|
|