Skip to content

Commit

Permalink
updated eb
Browse files Browse the repository at this point in the history
  • Loading branch information
spacemanspiff2007 committed Oct 10, 2024
1 parent 1d81ba0 commit 996ba9b
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ ignore = [

# https://docs.astral.sh/ruff/rules/#refactor-r
"PLR1711", # Useless return statement at end of function

# https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf
"RUF005", # Consider {expression} instead of concatenation
]


Expand Down
2 changes: 1 addition & 1 deletion src/HABApp/__check_dependency_packages__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_dependencies() -> list[str]:
]


def check_dependency_packages():
def check_dependency_packages() -> None:
"""Imports all dependencies and reports failures"""

missing: dict[str, ModuleNotFoundError] = {}
Expand Down
14 changes: 10 additions & 4 deletions src/HABApp/core/internals/event_bus/base_listener.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from typing import Any, Final


class EventBusBaseListener:
def __init__(self, topic: str, **kwargs) -> None:
def __init__(self, topic: str, **kwargs: Any) -> None:
super().__init__(**kwargs)
assert isinstance(topic, str)
self.topic: str = topic
if not isinstance(topic, str):
raise TypeError()
if not topic:
raise ValueError()
self.topic: Final = topic

def notify_listeners(self, event):
def notify_listeners(self, event: Any) -> None:
raise NotImplementedError()

def describe(self) -> str:
Expand Down
41 changes: 24 additions & 17 deletions src/HABApp/core/internals/event_bus/event_bus.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
import threading
from typing import Any, TypeVar
from typing import Any

from HABApp.core.const.log import TOPIC_EVENTS
from HABApp.core.events import ComplexEventValue, ValueChangeEvent
Expand All @@ -11,15 +11,15 @@
event_log = logging.getLogger(TOPIC_EVENTS)
habapp_log = logging.getLogger('HABApp')

_TYPE_LISTENER = TypeVar('_TYPE_LISTENER', bound=EventBusBaseListener)


class EventBus:
__slots__ = ('_lock', '_listeners')

def __init__(self) -> None:
self._lock = threading.Lock()
self._listeners: dict[str, list[EventBusBaseListener]] = {}
self._listeners: dict[str, tuple[EventBusBaseListener, ...]] = {}

def post_event(self, topic: str, event: Any):
def post_event(self, topic: str, event: Any) -> None:
assert isinstance(topic, str), type(topic)

if not isinstance(event, str):
Expand All @@ -42,43 +42,50 @@ def post_event(self, topic: str, event: Any):
pass

# Notify all listeners
listeners = self._listeners.get(topic, None)
if listeners is not None:
if (listeners := self._listeners.get(topic, None)) is not None:
for listener in listeners:
listener.notify_listeners(event)
return None

def add_listener(self, listener: _TYPE_LISTENER):
assert isinstance(listener, EventBusBaseListener)
assert isinstance(listener.topic, str) and listener.topic
def add_listener(self, listener: EventBusBaseListener) -> None:
if not isinstance(listener, EventBusBaseListener):
raise TypeError()
if not isinstance(topic := listener.topic, str):
raise TypeError()
if not topic:
raise ValueError()

with self._lock:
item_listeners = self._listeners.setdefault(listener.topic, [])
item_listeners = self._listeners.get(topic, ())

# don't add the same listener twice
if listener in item_listeners:
habapp_log.warning(f'Event listener for {listener.describe()} has already been added!')
return None

# add listener
item_listeners.append(listener)
self._listeners[topic] = item_listeners + (listener,)
habapp_log.debug(f'Added event listener for {listener.describe()}')
return None

def remove_listener(self, listener: _TYPE_LISTENER):
assert isinstance(listener, EventBusBaseListener)
assert isinstance(listener.topic, str) and listener.topic
def remove_listener(self, listener: EventBusBaseListener) -> None:
if not isinstance(listener, EventBusBaseListener):
raise TypeError()
if not isinstance(topic := listener.topic, str):
raise TypeError()
if not topic:
raise ValueError()

with self._lock:
item_listeners = self._listeners.get(listener.topic, [])
item_listeners = self._listeners.get(listener.topic, ())

# print warning if we try to remove it twice
if listener not in item_listeners:
habapp_log.warning(f'Event listener for {listener.describe()} has already been removed!')
return None

# remove listener
item_listeners.remove(listener)
self._listeners[topic] = tuple(o for o in item_listeners if o is not listener)
habapp_log.debug(f'Removed event listener for {listener.describe()}')
return None

Expand Down
26 changes: 20 additions & 6 deletions tests/test_core/test_event_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,32 @@ def test_repr(sync_worker) -> None:


def test_str_event(sync_worker) -> None:
event_history = []
"""Test simple event and add/remove"""
event_history1 = []
event_history2 = []
eb = EventBus()

def append_event(event) -> None:
event_history.append(event)
func = wrap_func(append_event)
event_history1.append(event)
func1 = wrap_func(append_event)

listener = EventBusListener('str_test', func, NoEventFilter())
eb.add_listener(listener)
def append_event2(event) -> None:
event_history2.append(event)
func2 = wrap_func(append_event2)

listener1 = EventBusListener('str_test', func1, NoEventFilter())
eb.add_listener(listener1)
listener2 = EventBusListener('str_test', func2, NoEventFilter())
eb.add_listener(listener2)

eb.post_event('str_test', 'str_event')
assert event_history == ['str_event']
assert event_history1 == ['str_event']
assert event_history2 == ['str_event']

eb.remove_listener(listener1)
eb.post_event('str_test', 'str_event_2')
assert event_history1 == ['str_event']
assert event_history2 == ['str_event', 'str_event_2']


def test_multiple_events(sync_worker) -> None:
Expand Down

0 comments on commit 996ba9b

Please sign in to comment.