From b853432e57afd4d7e282f33c733d9ebed9abf787 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Thu, 12 Jun 2025 16:49:23 +0200 Subject: [PATCH] Iterate interfaces in the MRO reversed order Iterating the MRO in the reversed order will allow to add interfaces to the given object in a well-defined way - always starting from the base class. Such ordering will be compatible with adding interfaces manually one by one. --- src/sdbus/dbus_proxy_async_interface_base.py | 2 +- src/sdbus/dbus_proxy_async_interfaces.py | 5 +++-- src/sdbus/dbus_proxy_sync_interface_base.py | 2 +- src/sdbus/dbus_proxy_sync_interfaces.py | 4 ++-- test/test_sdbus_async.py | 16 +++++++++++++++- test/test_sdbus_block.py | 16 +++++++++++++++- 6 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/sdbus/dbus_proxy_async_interface_base.py b/src/sdbus/dbus_proxy_async_interface_base.py index 0d0dd58..6fb927e 100644 --- a/src/sdbus/dbus_proxy_async_interface_base.py +++ b/src/sdbus/dbus_proxy_async_interface_base.py @@ -295,7 +295,7 @@ def _dbus_iter_interfaces_meta( cls, ) -> Iterator[tuple[str, DbusClassMeta]]: - for base in cls.__mro__: + for base in reversed(cls.__mro__): meta = DBUS_CLASS_TO_META.get(base) if meta is None: continue diff --git a/src/sdbus/dbus_proxy_async_interfaces.py b/src/sdbus/dbus_proxy_async_interfaces.py index 7964b0b..303aaff 100644 --- a/src/sdbus/dbus_proxy_async_interfaces.py +++ b/src/sdbus/dbus_proxy_async_interfaces.py @@ -105,6 +105,7 @@ async def properties_get_all_dict( class DbusInterfaceCommonAsync( - DbusPeerInterfaceAsync, DbusPropertiesInterfaceAsync, - DbusIntrospectableAsync): + DbusPropertiesInterfaceAsync, + DbusIntrospectableAsync, + DbusPeerInterfaceAsync): ... diff --git a/src/sdbus/dbus_proxy_sync_interface_base.py b/src/sdbus/dbus_proxy_sync_interface_base.py index dfd3bda..6358c74 100644 --- a/src/sdbus/dbus_proxy_sync_interface_base.py +++ b/src/sdbus/dbus_proxy_sync_interface_base.py @@ -171,7 +171,7 @@ def _dbus_iter_interfaces_meta( cls, ) -> Iterator[tuple[str, DbusClassMeta]]: - for base in cls.__mro__: + for base in reversed(cls.__mro__): meta = DBUS_CLASS_TO_META.get(base) if meta is None: continue diff --git a/src/sdbus/dbus_proxy_sync_interfaces.py b/src/sdbus/dbus_proxy_sync_interfaces.py index 90cc21f..b14e73b 100644 --- a/src/sdbus/dbus_proxy_sync_interfaces.py +++ b/src/sdbus/dbus_proxy_sync_interfaces.py @@ -94,9 +94,9 @@ def properties_get_all_dict( class DbusInterfaceCommon( - DbusPeerInterface, + DbusPropertiesInterface, DbusIntrospectable, - DbusPropertiesInterface): + DbusPeerInterface): ... diff --git a/test/test_sdbus_async.py b/test/test_sdbus_async.py index ccf341c..7e1d885 100644 --- a/test/test_sdbus_async.py +++ b/test/test_sdbus_async.py @@ -948,9 +948,23 @@ class TwoInterface( async def two(self) -> int: return 2 - class CombinedInterface(OneInterface, TwoInterface): + class CombinedInterface(TwoInterface, OneInterface): ... + test_combined = CombinedInterface() + test_combined_interfaces = [ + iface for iface, _ in test_combined._dbus_iter_interfaces_meta() + ] + + # Verify the order of reported interfaces on the combined class. + self.assertEqual(test_combined_interfaces, [ + "org.freedesktop.DBus.Peer", + "org.freedesktop.DBus.Introspectable", + "org.freedesktop.DBus.Properties", + "org.example.one", + "org.example.two", + ]) + async def test_extremely_large_string(self) -> None: test_object, test_object_connection = initialize_object() diff --git a/test/test_sdbus_block.py b/test/test_sdbus_block.py index e267f28..ef650d3 100644 --- a/test/test_sdbus_block.py +++ b/test/test_sdbus_block.py @@ -92,9 +92,23 @@ class TwoInterface( def two(self) -> int: raise NotImplementedError - class CombinedInterface(OneInterface, TwoInterface): + class CombinedInterface(TwoInterface, OneInterface): ... + test_combined = CombinedInterface("org.test", "/") + test_combined_interfaces = [ + iface for iface, _ in test_combined._dbus_iter_interfaces_meta() + ] + + # Verify the order of reported interfaces on the combined class. + self.assertEqual(test_combined_interfaces, [ + "org.freedesktop.DBus.Peer", + "org.freedesktop.DBus.Introspectable", + "org.freedesktop.DBus.Properties", + "org.example.one", + "org.example.two", + ]) + if __name__ == '__main__': main()