Skip to content

Commit

Permalink
Added DbusSignalAsync.catch method, identical to __aiter__
Browse files Browse the repository at this point in the history
  • Loading branch information
igo95862 committed Jun 26, 2022
1 parent f57749f commit 46642d8
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
9 changes: 6 additions & 3 deletions docs/asyncio_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,18 @@ Decorators

Signals have following methods:

.. py:method:: __aiter__()
.. py:method:: catch()
Signal can be used as an async generator for loop:
``async for x in something.some_signal:``
Catch D-Bus signals using the async generator for loop:
``async for x in something.some_signal.catch():``

This is main way to await for new events.

Both remote and local objects operate the same way.

Signal objects can also be async iterated directly:
``async for x in something.some_signal``

.. py:method:: emit(args)
Emit a new signal with *args* data.
Expand Down
31 changes: 27 additions & 4 deletions src/sdbus/dbus_proxy_async_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,20 @@ def __get__(self,
class DbusSignalBinded(Generic[T], DbusBindedAsync):
def __init__(self,
dbus_signal: DbusSignalAsync[T],
interface: DbusInterfaceBaseAsync):
interface: Optional[DbusInterfaceBaseAsync]):
self.dbus_signal = dbus_signal
self.interface_ref = weak_ref(interface)
if interface is not None:
self.interface_ref: Optional[weak_ref[DbusInterfaceBaseAsync]] \
= weak_ref(interface)
else:
self.interface_ref = None

self.__doc__ = dbus_signal.__doc__

async def _get_dbus_queue(self) -> Queue[SdBusMessage]:
assert self.interface_ref is not None, (
"Called method from class?"
)
interface = self.interface_ref()
assert interface is not None

Expand All @@ -87,12 +94,18 @@ async def _get_dbus_queue(self) -> Queue[SdBusMessage]:
def _cleanup_local_queue(
self,
queue_ref: weak_ref[Queue[T]]) -> None:
assert self.interface_ref is not None, (
"Called method from class?"
)
interface = self.interface_ref()
assert interface is not None

interface._local_signal_queues[self.dbus_signal].remove(queue_ref)

def _get_local_queue(self) -> Queue[T]:
assert self.interface_ref is not None, (
"Called method from class?"
)
interface = self.interface_ref()
assert interface is not None

Expand All @@ -110,8 +123,10 @@ def _get_local_queue(self) -> Queue[T]:

return new_queue

async def __aiter__(self) -> AsyncGenerator[T, None]:

async def catch(self) -> AsyncGenerator[T, None]:
assert self.interface_ref is not None, (
"Called method from class?"
)
interface = self.interface_ref()
assert interface is not None

Expand All @@ -128,7 +143,12 @@ async def __aiter__(self) -> AsyncGenerator[T, None]:
next_data = await data_queue.get()
yield next_data

__aiter__ = catch

def _emit_message(self, args: T) -> None:
assert self.interface_ref is not None, (
"Called method from class?"
)
interface = self.interface_ref()
assert interface is not None

Expand All @@ -155,6 +175,9 @@ def _emit_message(self, args: T) -> None:
signal_message.send()

def emit(self, args: T) -> None:
assert self.interface_ref is not None, (
"Called method from class?"
)
interface = self.interface_ref()
assert interface is not None

Expand Down
4 changes: 2 additions & 2 deletions test/test_sd_bus_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ async def test_emits_properties_changed(self) -> None:
loop = get_running_loop()

async def catch_property_emit_connection() -> str:
async for x in test_object_connection.properties_changed:
async for x in test_object_connection.properties_changed.catch():
for v in x[1].values():
probably_str = v[1]
if isinstance(probably_str, str):
Expand All @@ -475,7 +475,7 @@ async def catch_property_emit_connection() -> str:
raise ValueError

async def catch_property_emit_local() -> str:
async for x in test_object.properties_changed:
async for x in test_object.properties_changed.catch():
for v in x[1].values():
probably_str = v[1]
if isinstance(probably_str, str):
Expand Down

0 comments on commit 46642d8

Please sign in to comment.