Skip to content

Commit

Permalink
Make D-Bus element objects always have interface_name attribute
Browse files Browse the repository at this point in the history
Use the common metaclass to set the value of `interface_name`.

If the D-Bus element is defined in the class without the interface
name passed raise a TypeError.
  • Loading branch information
igo95862 committed Dec 2, 2023
1 parent effe5d8 commit c1d87bf
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 20 deletions.
22 changes: 19 additions & 3 deletions src/sdbus/dbus_common_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@


class DbusSomethingCommon:
def __init__(self) -> None:
self.interface_name: Optional[str] = None
self.serving_enabled: bool = True
interface_name: str
serving_enabled: bool


class DbusSomethingAsync(DbusSomethingCommon):
Expand Down Expand Up @@ -78,6 +77,23 @@ def __new__(cls, name: str,
except NotImplementedError:
...

for attr_name, attr in namespace.items():
if not isinstance(attr, DbusSomethingCommon):
continue

# TODO: Fix async metaclass copying all methods
if hasattr(attr, "interface_name"):
continue

if interface_name is None:
raise TypeError(
f"Defined D-Bus element {attr_name!r} without "
f"interface name in the class {name!r}."
)

attr.interface_name = interface_name
attr.serving_enabled = serving_enabled

new_cls = super().__new__(cls, name, bases, namespace)

return new_cls
Expand Down
2 changes: 0 additions & 2 deletions src/sdbus/dbus_proxy_async_interface_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ def __new__(cls, name: str,
)

if isinstance(value, DbusSomethingAsync):
value.interface_name = interface_name
value.serving_enabled = serving_enabled
dbus_declared_members[key] = value

if isinstance(value, DbusMethodAsync):
Expand Down
1 change: 0 additions & 1 deletion src/sdbus/dbus_proxy_async_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ async def _call_dbus_async(self, *args: Any) -> Any:
assert interface._attached_bus is not None
assert interface._remote_service_name is not None
assert interface._remote_object_path is not None
assert self.dbus_method.interface_name is not None
new_call_message = interface._attached_bus. \
new_method_call_message(
interface._remote_service_name,
Expand Down
3 changes: 0 additions & 3 deletions src/sdbus/dbus_proxy_async_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ async def get_async(self) -> T:
assert interface._remote_service_name is not None
assert interface._remote_object_path is not None
assert self.dbus_property.property_name is not None
assert self.dbus_property.interface_name is not None
new_call_message = interface._attached_bus. \
new_property_get_message(
interface._remote_service_name,
Expand Down Expand Up @@ -162,7 +161,6 @@ def _reply_set_sync(self, message: SdBusMessage) -> None:

self.dbus_property.property_setter(interface, data_to_set_to)

assert self.dbus_property.interface_name is not None
try:
properties_changed = getattr(interface, 'properties_changed')
except AttributeError:
Expand Down Expand Up @@ -217,7 +215,6 @@ async def set_async(self, complete_object: T) -> None:
assert interface._remote_service_name is not None
assert interface._remote_object_path is not None
assert self.dbus_property.property_name is not None
assert self.dbus_property.interface_name is not None
new_call_message = interface._attached_bus. \
new_property_set_message(
interface._remote_service_name,
Expand Down
2 changes: 0 additions & 2 deletions src/sdbus/dbus_proxy_async_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ async def _get_dbus_queue(self) -> Queue[SdBusMessage]:
assert interface._attached_bus is not None
assert interface._remote_service_name is not None
assert interface._remote_object_path is not None
assert self.dbus_signal.interface_name is not None
assert self.dbus_signal.signal_name is not None

return await interface._attached_bus.get_signal_queue_async(
Expand Down Expand Up @@ -201,7 +200,6 @@ def _emit_message(self, args: T) -> None:

assert interface._attached_bus is not None
assert interface._serving_object_path is not None
assert self.dbus_signal.interface_name is not None
assert self.dbus_signal.signal_name is not None

signal_message = interface._attached_bus.new_signal_message(
Expand Down
2 changes: 0 additions & 2 deletions src/sdbus/dbus_proxy_sync_interface_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ def __new__(cls, name: str,
)

if isinstance(value, DbusSomethingSync):
value.interface_name = interface_name
value.serving_enabled = serving_enabled
declared_interfaces.add(key)

if isinstance(value, DbusMethodSync):
Expand Down
1 change: 0 additions & 1 deletion src/sdbus/dbus_proxy_sync_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def __init__(self,
self.__doc__ = dbus_method.__doc__

def _call_dbus_sync(self, *args: Any) -> Any:
assert self.dbus_method.interface_name is not None
new_call_message = self.interface._attached_bus. \
new_method_call_message(
self.interface._remote_service_name,
Expand Down
2 changes: 0 additions & 2 deletions src/sdbus/dbus_proxy_sync_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ def __get__(self,
"This is probably an error as it will block "
"other asyncio methods for considerable time."
)
assert self.interface_name is not None

new_call_message = obj._attached_bus. \
new_property_get_message(
Expand Down Expand Up @@ -97,7 +96,6 @@ def __set__(self, obj: DbusInterfaceBase, value: T) -> None:
assert obj._remote_service_name is not None
assert obj._remote_object_path is not None
assert self.property_name is not None
assert self.interface_name is not None
new_call_message = obj._attached_bus. \
new_property_set_message(
obj._remote_service_name,
Expand Down
24 changes: 21 additions & 3 deletions test/test_sdbus_async_bad_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
from unittest import TestCase
from unittest import main as unittest_main

from sdbus.dbus_common_funcs import PROPERTY_FLAGS_MASK, count_bits

from sdbus import (
DbusDeprecatedFlag,
DbusInterfaceCommonAsync,
Expand All @@ -34,11 +32,15 @@
dbus_property_async,
dbus_signal_async,
)
from sdbus.dbus_common_funcs import PROPERTY_FLAGS_MASK, count_bits

from .common_test_util import skip_if_no_asserts, skip_if_no_name_validations


class TestInterface(DbusInterfaceCommonAsync):
class TestInterface(
DbusInterfaceCommonAsync,
interface_name="org.example.test",
):
@dbus_method_async(result_signature="i")
async def test_int(self) -> int:
return 1
Expand Down Expand Up @@ -170,6 +172,22 @@ class TestInheritence2(TestInterface):
async def test_unrelated(self) -> int:
return 2

def test_dbus_elements_without_interface_name(self) -> None:
with self.assertRaisesRegex(TypeError, "without interface name"):

class NoInterfaceName(DbusInterfaceCommonAsync):
@dbus_method_async()
async def example(self) -> None:
...

def test_dbus_elements_without_interface_name_subclass(self) -> None:
with self.assertRaisesRegex(TypeError, "without interface name"):

class NoInterfaceName(TestInterface):
@dbus_method_async()
async def example(self) -> None:
...


if __name__ == "__main__":
unittest_main()
13 changes: 12 additions & 1 deletion test/test_sdbus_block_bad_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
from .common_test_util import skip_if_no_name_validations


class GoodDbusInterface(DbusInterfaceCommon):
class GoodDbusInterface(
DbusInterfaceCommon,
interface_name="org.example.test",
):
@dbus_method()
def test_method(self) -> None:
raise NotImplementedError
Expand Down Expand Up @@ -118,6 +121,14 @@ class BadPropertyName(
def test(self) -> str:
return "test"

def test_dbus_elements_without_interface_name(self) -> None:
with self.assertRaisesRegex(TypeError, "without interface name"):

class NoInterfaceName(DbusInterfaceCommon):
@dbus_method()
def example(self) -> None:
...


if __name__ == "__main__":
unittest_main()

0 comments on commit c1d87bf

Please sign in to comment.