feat: add support for finding message handlers when interface is None (#403)
This commit is contained in:
parent
c7cc0f23af
commit
bfd48a3a38
@ -58,6 +58,8 @@ cdef class BaseMessageBus:
|
||||
)
|
||||
cdef _find_message_handler(self, Message msg)
|
||||
|
||||
cdef _find_any_message_handler_matching_signature(self, dict interfaces, Message msg)
|
||||
|
||||
cdef _setup_socket(self)
|
||||
|
||||
cpdef _call(self, Message msg, object callback)
|
||||
|
||||
@ -906,10 +906,12 @@ class BaseMessageBus:
|
||||
return partial(self._callback_method_handler, interface, method)
|
||||
|
||||
def _find_message_handler(self, msg: _Message) -> HandlerType | None:
|
||||
"""Find the message handler for for METHOD_CALL messages."""
|
||||
if TYPE_CHECKING:
|
||||
assert msg.interface is not None
|
||||
assert msg.member is not None
|
||||
assert msg.path is not None
|
||||
|
||||
if "org.freedesktop.DBus." in msg.interface:
|
||||
if msg.interface is not None and "org.freedesktop.DBus." in msg.interface:
|
||||
if (
|
||||
msg.interface == "org.freedesktop.DBus.Introspectable"
|
||||
and msg.member == "Introspect"
|
||||
@ -932,19 +934,33 @@ class BaseMessageBus:
|
||||
):
|
||||
return self._default_get_managed_objects_handler
|
||||
|
||||
if (
|
||||
msg.path is not None
|
||||
and msg.member is not None
|
||||
and (interfaces := self._path_exports.get(msg.path)) is not None
|
||||
and (interface := interfaces.get(msg.interface)) is not None
|
||||
and (
|
||||
if (interfaces := self._path_exports.get(msg.path)) is None:
|
||||
return None
|
||||
|
||||
if msg.interface is None:
|
||||
return self._find_any_message_handler_matching_signature(interfaces, msg)
|
||||
|
||||
if (interface := interfaces.get(msg.interface)) is not None and (
|
||||
handler := ServiceInterface._get_enabled_handler_by_name_signature(
|
||||
interface, self, msg.member, msg.signature
|
||||
)
|
||||
) is not None:
|
||||
return handler
|
||||
|
||||
return None
|
||||
|
||||
def _find_any_message_handler_matching_signature(
|
||||
self, interfaces: dict[str, ServiceInterface], msg: _Message
|
||||
) -> HandlerType | None:
|
||||
# No interface, so we need to search all interfaces for the method
|
||||
# with a matching signature
|
||||
for interface in interfaces.values():
|
||||
if (
|
||||
handler := ServiceInterface._get_enabled_handler_by_name_signature(
|
||||
interface, self, msg.member, msg.signature
|
||||
)
|
||||
)
|
||||
is not None
|
||||
):
|
||||
return handler
|
||||
) is not None:
|
||||
return handler
|
||||
return None
|
||||
|
||||
def _default_introspect_handler(self, msg: Message, send_reply: SendReply) -> None:
|
||||
|
||||
@ -61,7 +61,7 @@ class ExampleInterface(ServiceInterface):
|
||||
@method()
|
||||
def throws_dbus_error(self):
|
||||
assert type(self) is ExampleInterface
|
||||
raise DBusError("test.error", "an error ocurred")
|
||||
raise DBusError("test.error", "an error occurred")
|
||||
|
||||
|
||||
class AsyncInterface(ServiceInterface):
|
||||
@ -112,7 +112,7 @@ class AsyncInterface(ServiceInterface):
|
||||
@method()
|
||||
def throws_dbus_error(self):
|
||||
assert type(self) is AsyncInterface
|
||||
raise DBusError("test.error", "an error ocurred")
|
||||
raise DBusError("test.error", "an error occurred")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("interface_class", [ExampleInterface, AsyncInterface])
|
||||
@ -124,12 +124,14 @@ async def test_methods(interface_class):
|
||||
interface = interface_class("test.interface")
|
||||
export_path = "/test/path"
|
||||
|
||||
async def call(member, signature="", body=[], flags=MessageFlag.NONE):
|
||||
async def call(
|
||||
member, signature="", body=[], flags=MessageFlag.NONE, interface=interface.name
|
||||
):
|
||||
return await bus2.call(
|
||||
Message(
|
||||
destination=bus1.unique_name,
|
||||
path=export_path,
|
||||
interface=interface.name,
|
||||
interface=interface,
|
||||
member=member,
|
||||
signature=signature,
|
||||
body=body,
|
||||
@ -165,6 +167,31 @@ async def test_methods(interface_class):
|
||||
assert reply.signature == signature
|
||||
assert reply.body == body
|
||||
|
||||
# Wrong interface should be a failure
|
||||
reply = await call(
|
||||
"echo_containers", signature, body, interface="org.abc.xyz.Props"
|
||||
)
|
||||
assert reply.message_type == MessageType.ERROR, reply.body[0]
|
||||
assert reply.error_name == "org.freedesktop.DBus.Error.UnknownMethod", reply.body[0]
|
||||
assert reply.body == [
|
||||
'org.abc.xyz.Props.echo_containers with signature "asva{sv}(s(s(v)))" could not be found'
|
||||
]
|
||||
|
||||
# No interface should result in finding anything that matches the member name
|
||||
# and the signature
|
||||
reply = await call("echo_containers", signature, body, interface=None)
|
||||
assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0]
|
||||
assert reply.signature == signature
|
||||
assert reply.body == body
|
||||
|
||||
# No interface should result in finding anything that matches the member name
|
||||
# and the signature, but in this case it will be nothing because
|
||||
# the signature is wrong
|
||||
reply = await call("echo_containers", "as", body, interface=None)
|
||||
assert reply.message_type == MessageType.ERROR, reply.body[0]
|
||||
assert reply.error_name == "org.freedesktop.DBus.Error.UnknownMethod", reply.body[0]
|
||||
assert reply.body == ['None.echo_containers with signature "as" could not be found']
|
||||
|
||||
reply = await call("ping")
|
||||
assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0]
|
||||
assert reply.signature == ""
|
||||
@ -177,7 +204,7 @@ async def test_methods(interface_class):
|
||||
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"]
|
||||
assert reply.body == ["an error occurred"]
|
||||
|
||||
reply = await call("ping", flags=MessageFlag.NO_REPLY_EXPECTED)
|
||||
assert reply is None
|
||||
@ -188,6 +215,13 @@ async def test_methods(interface_class):
|
||||
reply = await call("throws_dbus_error", flags=MessageFlag.NO_REPLY_EXPECTED)
|
||||
assert reply is None
|
||||
|
||||
reply = await call("does_not_exist")
|
||||
assert reply.message_type == MessageType.ERROR, reply.body[0]
|
||||
assert reply.error_name == "org.freedesktop.DBus.Error.UnknownMethod", reply.body[0]
|
||||
assert reply.body == [
|
||||
'test.interface.does_not_exist with signature "" could not be found'
|
||||
]
|
||||
|
||||
bus1.disconnect()
|
||||
bus2.disconnect()
|
||||
bus1._sock.close()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user