-
Notifications
You must be signed in to change notification settings - Fork 44
[WIP] Events, LED #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,67 @@ | ||||||||||||||||||||||||||||||||||||||||||
| import logging | ||||||||||||||||||||||||||||||||||||||||||
| from typing import Any, Callable, Dict, List, Optional | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| _LOGGER = logging.getLogger(__name__) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| class EventBus: | ||||||||||||||||||||||||||||||||||||||||||
| """A simple synchronous publish/subscribe event bus.""" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def __init__(self): | ||||||||||||||||||||||||||||||||||||||||||
| # A dictionary to hold listeners for specific string topics | ||||||||||||||||||||||||||||||||||||||||||
| self.topics: Dict[str, List[Callable[[Any], None]]] = {} | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def subscribe(self, topic: str, listener: Callable[[Any], None]) -> None: | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
| Subscribes a listener to a topic. | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # _LOGGER.debug(f'EventBus subscribe {topic}') | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if topic not in self.topics: | ||||||||||||||||||||||||||||||||||||||||||
| self.topics[topic] = [] | ||||||||||||||||||||||||||||||||||||||||||
| self.topics[topic].append(listener) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def publish(self, topic: str, data: [dict, None]) -> None: | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
| Publishes an event to all subscribed listeners. | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # _LOGGER.debug(f'EventBus publish {topic}') | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| data['__topic'] = topic | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| listeners = self.topics.get(topic, []) | ||||||||||||||||||||||||||||||||||||||||||
| for listener in listeners: | ||||||||||||||||||||||||||||||||||||||||||
| listener(data) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # Client helpers for subscriptions | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # The decorator to mark methods for subscription. | ||||||||||||||||||||||||||||||||||||||||||
| def subscribe(func: Callable) -> Callable: | ||||||||||||||||||||||||||||||||||||||||||
| """Decorator to mark a method for event bus subscription.""" | ||||||||||||||||||||||||||||||||||||||||||
| func._event_bus_subscribe = True | ||||||||||||||||||||||||||||||||||||||||||
| return func | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+41
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] Configurable handler metadata:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Nitpick] An event bus is based off events - not topics, it would scale far more easily to have event handlers react to |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| class EventHandler: | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
| A base class for components that subscribe to events. | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| Subclasses should define event handlers as methods decorated with `@subscribe`. | ||||||||||||||||||||||||||||||||||||||||||
| The method name will automatically be used as the event topic. | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, state: Any): | ||||||||||||||||||||||||||||||||||||||||||
| self.state = state | ||||||||||||||||||||||||||||||||||||||||||
| self._subscribe_all_methods() | ||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.debug(f"EventHandler {self.__class__.__name__} has subscribed to all decorated methods.") | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def _subscribe_all_methods(self): | ||||||||||||||||||||||||||||||||||||||||||
| """Finds and subscribes all methods decorated with @subscribe.""" | ||||||||||||||||||||||||||||||||||||||||||
| for method_name in dir(self): | ||||||||||||||||||||||||||||||||||||||||||
| method = getattr(self, method_name) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if hasattr(method, '_event_bus_subscribe'): | ||||||||||||||||||||||||||||||||||||||||||
| # The topic is the name of the method itself. | ||||||||||||||||||||||||||||||||||||||||||
| self.state.event_bus.subscribe(method_name, method) | ||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.debug(f"Subscribed method '{method_name}' to topic '{method_name}'") | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] Based on below suggestion:
When publishing events, use
asyncio.create_taskto publish the event.