import pytest from dbus_fast import ( DBusError, ErrorType, Message, MessageFlag, MessageType, SignatureTree, Variant, ) from dbus_fast.aio import MessageBus from dbus_fast.service import ServiceInterface, method class ExampleInterface(ServiceInterface): def __init__(self, name): super().__init__(name) @method() def echo(self, what: "s") -> "s": assert type(self) is ExampleInterface return what @method() def echo_multiple(self, what1: "s", what2: "s") -> "ss": assert type(self) is ExampleInterface return [what1, what2] @method() def echo_containers( self, array: "as", variant: "v", dict_entries: "a{sv}", struct: "(s(s(v)))" ) -> "asva{sv}(s(s(v)))": assert type(self) is ExampleInterface return [array, variant, dict_entries, struct] @method() def ping(self): assert type(self) is ExampleInterface pass @method(name="renamed") def original_name(self): assert type(self) is ExampleInterface pass @method(disabled=True) def not_here(self): assert type(self) is ExampleInterface pass @method() def throws_unexpected_error(self): assert type(self) is ExampleInterface raise Exception("oops") @method() def throws_dbus_error(self): assert type(self) is ExampleInterface raise DBusError("test.error", "an error ocurred") class AsyncInterface(ServiceInterface): def __init__(self, name): super().__init__(name) @method() async def echo(self, what: "s") -> "s": assert type(self) is AsyncInterface return what @method() async def echo_multiple(self, what1: "s", what2: "s") -> "ss": assert type(self) is AsyncInterface return [what1, what2] @method() async def echo_containers( self, array: "as", variant: "v", dict_entries: "a{sv}", struct: "(s(s(v)))" ) -> "asva{sv}(s(s(v)))": assert type(self) is AsyncInterface return [array, variant, dict_entries, struct] @method() async def ping(self): assert type(self) is AsyncInterface pass @method(name="renamed") async def original_name(self): assert type(self) is AsyncInterface pass @method(disabled=True) async def not_here(self): assert type(self) is AsyncInterface pass @method() async def throws_unexpected_error(self): assert type(self) is AsyncInterface raise Exception("oops") @method() def throws_dbus_error(self): assert type(self) is AsyncInterface raise DBusError("test.error", "an error ocurred") @pytest.mark.parametrize("interface_class", [ExampleInterface, AsyncInterface]) @pytest.mark.asyncio async def test_methods(interface_class): bus1 = await MessageBus().connect() bus2 = await MessageBus().connect() interface = interface_class("test.interface") export_path = "/test/path" async def call(member, signature="", body=[], flags=MessageFlag.NONE): return await bus2.call( Message( destination=bus1.unique_name, path=export_path, interface=interface.name, member=member, signature=signature, body=body, flags=flags, ) ) bus1.export(export_path, interface) body = ["hello world"] reply = await call("echo", "s", body) assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0] assert reply.signature == "s" assert reply.body == body body = ["hello", "world"] reply = await call("echo_multiple", "ss", body) assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0] assert reply.signature == "ss" assert reply.body == body body = [ ["hello", "world"], Variant("v", Variant("(ss)", ["hello", "world"])), {"foo": Variant("t", 100)}, ["one", ["two", [Variant("s", "three")]]], ] signature = "asva{sv}(s(s(v)))" SignatureTree(signature).verify(body) reply = await call("echo_containers", signature, body) assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0] assert reply.signature == signature assert reply.body == body reply = await call("ping") assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0] assert reply.signature == "" assert reply.body == [] reply = await call("throws_unexpected_error") assert reply.message_type == MessageType.ERROR, reply.body[0] assert reply.error_name == ErrorType.SERVICE_ERROR.value, reply.body[0] reply = await call("throws_dbus_error") assert reply.message_type == MessageType.ERROR, reply.body[0] assert reply.error_name == "test.error", reply.body[0] assert reply.body == ["an error ocurred"] reply = await call("ping", flags=MessageFlag.NO_REPLY_EXPECTED) assert reply is None reply = await call("throws_unexpected_error", flags=MessageFlag.NO_REPLY_EXPECTED) assert reply is None reply = await call("throws_dbus_error", flags=MessageFlag.NO_REPLY_EXPECTED) assert reply is None bus1.disconnect() bus2.disconnect() bus1._sock.close() bus2._sock.close()