Skip to content

Commit e3d5192

Browse files
committed
Move code exporting attributes to the attribute's classes
1 parent d958754 commit e3d5192

7 files changed

+226
-138
lines changed

src/sdbus/dbus_common_elements.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2020
from __future__ import annotations
2121

22+
from abc import ABC, abstractmethod
2223
from inspect import getfullargspec
2324
from typing import TYPE_CHECKING, Generic, TypeVar
2425

@@ -44,15 +45,21 @@
4445

4546
SelfMeta = TypeVar('SelfMeta', bound="DbusInterfaceMetaCommon")
4647

48+
from .dbus_proxy_async_interface_base import DbusExportHandle
4749
from .sd_bus_internals import SdBus, SdBusInterface
4850

4951
T = TypeVar('T')
5052

5153

52-
class DbusMemberCommon:
54+
class DbusMemberCommon(ABC):
5355
interface_name: str
5456
serving_enabled: bool
5557

58+
@property
59+
@abstractmethod
60+
def member_name(self) -> str:
61+
...
62+
5663

5764
class DbusMemberAsync(DbusMemberCommon):
5865
...
@@ -230,6 +237,10 @@ def _rebuild_args(
230237

231238
return new_args_list
232239

240+
@property
241+
def member_name(self) -> str:
242+
return self.method_name
243+
233244

234245
class DbusPropertyCommon(DbusMemberCommon):
235246
def __init__(self,
@@ -261,6 +272,10 @@ def __init__(self,
261272
self.property_signature = property_signature
262273
self.flags = flags
263274

275+
@property
276+
def member_name(self) -> str:
277+
return self.property_name
278+
264279

265280
class DbusSignalCommon(DbusMemberCommon):
266281
def __init__(self,
@@ -290,12 +305,29 @@ def __init__(self,
290305
self.__doc__ = original_method.__doc__
291306
self.__annotations__ = original_method.__annotations__
292307

308+
@property
309+
def member_name(self) -> str:
310+
return self.signal_name
293311

294-
class DbusBoundAsync:
295-
...
312+
313+
class DbusBoundMember(ABC):
314+
@property
315+
@abstractmethod
316+
def member(self) -> DbusMemberCommon:
317+
...
318+
319+
320+
class DbusLocalMemberAsync(DbusBoundMember):
321+
@abstractmethod
322+
def _append_to_interface(
323+
self,
324+
interface: SdBusInterface,
325+
handle: DbusExportHandle,
326+
) -> None:
327+
...
296328

297329

298-
class DbusBoundSync:
330+
class DbusProxyMemberAsync(DbusBoundMember):
299331
...
300332

301333

src/sdbus/dbus_proxy_async_interface_base.py

Lines changed: 38 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@
2323
from inspect import getmembers
2424
from itertools import chain
2525
from types import MethodType
26-
from typing import TYPE_CHECKING, Any, Callable, cast
26+
from typing import TYPE_CHECKING, Any, Callable, Protocol, cast
2727
from warnings import warn
2828
from weakref import WeakKeyDictionary, WeakValueDictionary
2929

3030
from .dbus_common_elements import (
3131
DbusClassMeta,
3232
DbusInterfaceMetaCommon,
33+
DbusLocalMemberAsync,
3334
DbusLocalObjectMeta,
3435
DbusMemberAsync,
3536
DbusMemberCommon,
@@ -39,12 +40,8 @@
3940
DbusRemoteObjectMeta,
4041
)
4142
from .dbus_common_funcs import get_default_bus
42-
from .dbus_proxy_async_method import DbusLocalMethodAsync, DbusMethodAsync
43-
from .dbus_proxy_async_property import (
44-
DbusLocalPropertyAsync,
45-
DbusPropertyAsync,
46-
)
47-
from .dbus_proxy_async_signal import DbusLocalSignalAsync, DbusSignalAsync
43+
from .dbus_proxy_async_method import DbusMethodAsync
44+
from .dbus_proxy_async_property import DbusPropertyAsync
4845
from .sd_bus_internals import SdBusInterface
4946

5047
if TYPE_CHECKING:
@@ -61,8 +58,7 @@
6158
Union,
6259
)
6360

64-
from .dbus_common_elements import DbusBoundAsync
65-
from .sd_bus_internals import SdBus, SdBusSlot
61+
from .sd_bus_internals import SdBus
6662

6763
T = TypeVar('T')
6864
Self = TypeVar('Self', bound="DbusInterfaceBaseAsync")
@@ -239,15 +235,9 @@ def _map_dbus_elements(
239235
if attr.interface_name != interface_name:
240236
return
241237

242-
if isinstance(attr, DbusMethodAsync):
243-
meta.dbus_member_to_python_attr[attr.method_name] = attr_name
244-
meta.python_attr_to_dbus_member[attr_name] = attr.method_name
245-
elif isinstance(attr, DbusPropertyAsync):
246-
meta.dbus_member_to_python_attr[attr.property_name] = attr_name
247-
meta.python_attr_to_dbus_member[attr_name] = attr.property_name
248-
elif isinstance(attr, DbusSignalAsync):
249-
meta.dbus_member_to_python_attr[attr.signal_name] = attr_name
250-
meta.python_attr_to_dbus_member[attr_name] = attr.signal_name
238+
if isinstance(attr, DbusMemberAsync):
239+
meta.dbus_member_to_python_attr[attr.member_name] = attr_name
240+
meta.python_attr_to_dbus_member[attr_name] = attr.member_name
251241
else:
252242
raise TypeError(f"Unknown D-Bus element: {attr!r}")
253243

@@ -344,23 +334,14 @@ def export_to_dbus(
344334
local_object_meta.attached_bus = bus
345335
local_object_meta.serving_object_path = object_path
346336
# TODO: can be optimized with a single loop
347-
interface_map: Dict[str, List[DbusBoundAsync]] = {}
337+
interface_map: Dict[str, List[DbusLocalMemberAsync]] = {}
348338

349339
for key, value in getmembers(self):
350340
assert not isinstance(value, DbusMemberAsync)
351341

352-
if isinstance(value, DbusLocalMethodAsync):
353-
interface_name = value.dbus_method.interface_name
354-
if not value.dbus_method.serving_enabled:
355-
continue
356-
elif isinstance(value, DbusLocalPropertyAsync):
357-
interface_name = value.dbus_property.interface_name
358-
if not value.dbus_property.serving_enabled:
359-
continue
360-
elif isinstance(value, DbusLocalSignalAsync):
361-
interface_name = value.dbus_signal.interface_name
362-
if not value.dbus_signal.serving_enabled:
363-
continue
342+
if isinstance(value, DbusLocalMemberAsync) and \
343+
value.member.serving_enabled:
344+
interface_name = value.member.interface_name
364345
else:
365346
continue
366347

@@ -372,54 +353,21 @@ def export_to_dbus(
372353

373354
interface_member_list.append(value)
374355

356+
export_handle = DbusExportHandle()
357+
375358
for interface_name, member_list in interface_map.items():
376359
new_interface = SdBusInterface()
377360
for dbus_something in member_list:
378-
if isinstance(dbus_something, DbusLocalMethodAsync):
379-
new_interface.add_method(
380-
dbus_something.dbus_method.method_name,
381-
dbus_something.dbus_method.input_signature,
382-
dbus_something.dbus_method.input_args_names,
383-
dbus_something.dbus_method.result_signature,
384-
dbus_something.dbus_method.result_args_names,
385-
dbus_something.dbus_method.flags,
386-
dbus_something._dbus_reply_call,
387-
)
388-
elif isinstance(dbus_something, DbusLocalPropertyAsync):
389-
getter = dbus_something._dbus_reply_get
390-
dbus_property = dbus_something.dbus_property
391-
392-
if (
393-
dbus_property.property_setter is not None
394-
and
395-
dbus_property.property_setter_is_public
396-
):
397-
setter = dbus_something._dbus_reply_set
398-
else:
399-
setter = None
400-
401-
new_interface.add_property(
402-
dbus_property.property_name,
403-
dbus_property.property_signature,
404-
getter,
405-
setter,
406-
dbus_property.flags,
407-
)
408-
elif isinstance(dbus_something, DbusLocalSignalAsync):
409-
new_interface.add_signal(
410-
dbus_something.dbus_signal.signal_name,
411-
dbus_something.dbus_signal.signal_signature,
412-
dbus_something.dbus_signal.args_names,
413-
dbus_something.dbus_signal.flags,
414-
)
415-
else:
416-
raise TypeError
417-
361+
dbus_something._append_to_interface(new_interface,
362+
export_handle)
418363
bus.add_interface(new_interface, object_path,
419364
interface_name)
420365
local_object_meta.activated_interfaces.append(new_interface)
421366

422-
return DbusExportHandle(local_object_meta)
367+
assert new_interface.slot is not None
368+
export_handle.append(new_interface.slot)
369+
370+
return export_handle
423371

424372
def _connect(
425373
self,
@@ -475,13 +423,23 @@ def new_proxy(
475423
return new_object
476424

477425

426+
class Closeable(Protocol):
427+
def close(self) -> None:
428+
...
429+
430+
478431
class DbusExportHandle:
479-
def __init__(self, local_meta: DbusLocalObjectMeta):
480-
self._dbus_slots: List[SdBusSlot] = [
481-
i.slot
482-
for i in local_meta.activated_interfaces
483-
if i.slot is not None
484-
]
432+
def __init__(self, *items: Closeable) -> None:
433+
self._items = list(items)
434+
435+
def append(self, item: Closeable) -> None:
436+
self._items.append(item)
437+
438+
def close(self) -> None:
439+
while self._items:
440+
self._items.pop().close()
441+
442+
stop = close # for backwards compatibility
485443

486444
async def __aenter__(self) -> DbusExportHandle:
487445
return self
@@ -495,16 +453,12 @@ def __exit__(
495453
exc_value: Any,
496454
traceback: Any,
497455
) -> None:
498-
self.stop()
456+
self.close()
499457

500458
async def __aexit__(
501459
self,
502460
exc_type: Any,
503461
exc_value: Any,
504462
traceback: Any,
505463
) -> None:
506-
self.stop()
507-
508-
def stop(self) -> None:
509-
for slot in self._dbus_slots:
510-
slot.close()
464+
self.close()

src/sdbus/dbus_proxy_async_method.py

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,24 @@
2626
from weakref import ref as weak_ref
2727

2828
from .dbus_common_elements import (
29-
DbusBoundAsync,
29+
DbusBoundMember,
30+
DbusLocalMemberAsync,
3031
DbusMemberAsync,
3132
DbusMethodCommon,
3233
DbusMethodOverride,
34+
DbusProxyMemberAsync,
3335
DbusRemoteObjectMeta,
3436
)
3537
from .dbus_exceptions import DbusFailedError
36-
from .sd_bus_internals import DbusNoReplyFlag
38+
from .sd_bus_internals import DbusNoReplyFlag, SdBusInterface
3739

3840
if TYPE_CHECKING:
3941
from typing import Any, Callable, Optional, Sequence, Type, TypeVar, Union
4042

41-
from .dbus_proxy_async_interface_base import DbusInterfaceBaseAsync
43+
from .dbus_proxy_async_interface_base import (
44+
DbusExportHandle,
45+
DbusInterfaceBaseAsync,
46+
)
4247
from .sd_bus_internals import SdBusMessage
4348

4449
T = TypeVar('T')
@@ -85,19 +90,25 @@ def __get__(
8590
return self
8691

8792

88-
class DbusBoundMethodAsyncBase(DbusBoundAsync):
93+
class DbusBoundMethodAsyncBase(DbusBoundMember):
94+
def __init__(self, dbus_method: DbusMethodAsync) -> None:
95+
self.dbus_method = dbus_method
96+
97+
@property
98+
def member(self) -> DbusMemberAsync:
99+
return self.dbus_method
89100

90101
def __call__(self, *args: Any, **kwargs: Any) -> Any:
91102
raise NotImplementedError
92103

93104

94-
class DbusProxyMethodAsync(DbusBoundMethodAsyncBase):
105+
class DbusProxyMethodAsync(DbusBoundMethodAsyncBase, DbusProxyMemberAsync):
95106
def __init__(
96107
self,
97108
dbus_method: DbusMethodAsync,
98109
proxy_meta: DbusRemoteObjectMeta,
99110
):
100-
self.dbus_method = dbus_method
111+
super().__init__(dbus_method)
101112
self.proxy_meta = proxy_meta
102113

103114
self.__doc__ = dbus_method.__doc__
@@ -145,17 +156,32 @@ def __call__(self, *args: Any, **kwargs: Any) -> Any:
145156
return self._dbus_async_call(new_call_message)
146157

147158

148-
class DbusLocalMethodAsync(DbusBoundMethodAsyncBase):
159+
class DbusLocalMethodAsync(DbusBoundMethodAsyncBase, DbusLocalMemberAsync):
149160
def __init__(
150161
self,
151162
dbus_method: DbusMethodAsync,
152163
local_object: DbusInterfaceBaseAsync,
153164
):
154-
self.dbus_method = dbus_method
165+
super().__init__(dbus_method)
155166
self.local_object_ref = weak_ref(local_object)
156167

157168
self.__doc__ = dbus_method.__doc__
158169

170+
def _append_to_interface(
171+
self,
172+
interface: SdBusInterface,
173+
handle: DbusExportHandle,
174+
) -> None:
175+
interface.add_method(
176+
self.dbus_method.method_name,
177+
self.dbus_method.input_signature,
178+
self.dbus_method.input_args_names,
179+
self.dbus_method.result_signature,
180+
self.dbus_method.result_args_names,
181+
self.dbus_method.flags,
182+
self._dbus_reply_call,
183+
)
184+
159185
def __call__(self, *args: Any, **kwargs: Any) -> Any:
160186
local_object = self.local_object_ref()
161187
if local_object is None:
@@ -232,6 +258,12 @@ async def _dbus_reply_call(
232258
reply_message.send()
233259

234260

261+
# aliases for backwards compatibility
262+
DbusMethodAsyncBaseBind = DbusBoundMethodAsyncBase
263+
DbusMethodAsyncLocalBind = DbusLocalMethodAsync
264+
DbusMethodAsyncProxyBind = DbusProxyMethodAsync
265+
266+
235267
def dbus_method_async(
236268
input_signature: str = "",
237269
result_signature: str = "",

0 commit comments

Comments
 (0)