Skip to content

Commit edf2404

Browse files
committed
Add sdbus.utils.inspect.inspect_dbus_path
If called on a D-Bus proxy returns path of the proxied object. If called on a local D-Bus object returns the exported D-Bus path. If object is not exported raises ``LookupError``. If called on an object that is unrelated to D-Bus raises ``TypeError``. The object's path is inspected in the context of the given bus and if the object is attached to a different bus the ``LookupError`` will be raised. If the bus argument is not given or is ``None`` the default bus will be checked against.
1 parent 87aefaa commit edf2404

3 files changed

Lines changed: 190 additions & 0 deletions

File tree

docs/utils.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,37 @@ Available under ``sdbus.utils.parse`` subpackage.
8484
:returns: Dictionary where keys are paths and values are tuples of managed objects classes and their properties data.
8585

8686
*New in version 0.12.0.*
87+
88+
Inspect utilities
89+
+++++++++++++++++
90+
91+
Inspect D-Bus objects and retrieve their D-Bus related attributes
92+
such as D-Bus object paths and etc...
93+
Available under ``sdbus.utils.inspect`` subpackage.
94+
95+
.. py:currentmodule:: sdbus.utils.inspect
96+
97+
.. py:function:: inspect_dbus_path(obj, bus=None)
98+
99+
Returns the D-Bus path of an object.
100+
101+
If called on a D-Bus proxy returns path of the proxied object.
102+
103+
If called on a local D-Bus object returns the exported D-Bus path.
104+
If object is not exported raises ``LookupError``.
105+
106+
If called on an object that is unrelated to D-Bus raises ``TypeError``.
107+
108+
The object's path is inspected in the context of the given bus and if the
109+
object is attached to a different bus the ``LookupError`` will be raised.
110+
If the bus argument is not given or is ``None`` the default bus will be
111+
checked against.
112+
113+
:param object obj: Object to inspect.
114+
:param SdBus bus:
115+
Bus to inspect against.
116+
If not given or ``None`` the default bus will be used.
117+
:rtype: str
118+
:returns: D-Bus path of the object.
119+
120+
*New in version 0.13.0.*

src/sdbus/utils/inspect.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# SPDX-License-Identifier: LGPL-2.1-or-later
2+
3+
# Copyright (C) 2024 igo95862
4+
5+
# This file is part of python-sdbus
6+
7+
# This library is free software; you can redistribute it and/or
8+
# modify it under the terms of the GNU Lesser General Public
9+
# License as published by the Free Software Foundation; either
10+
# version 2.1 of the License, or (at your option) any later version.
11+
12+
# This library is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
# Lesser General Public License for more details.
16+
17+
# You should have received a copy of the GNU Lesser General Public
18+
# License along with this library; if not, write to the Free Software
19+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
from __future__ import annotations
21+
22+
from typing import TYPE_CHECKING
23+
24+
from ..dbus_common_elements import DbusLocalObjectMeta, DbusRemoteObjectMeta
25+
from ..dbus_common_funcs import get_default_bus
26+
from ..dbus_proxy_async_interface_base import DbusInterfaceBaseAsync
27+
from ..dbus_proxy_sync_interface_base import DbusInterfaceBase
28+
29+
if TYPE_CHECKING:
30+
from typing import Optional, Union
31+
32+
from ..sd_bus_internals import SdBus
33+
34+
35+
def _inspect_dbus_path_proxy(
36+
obj: object,
37+
dbus_meta: DbusRemoteObjectMeta,
38+
bus: SdBus,
39+
) -> str:
40+
if bus != dbus_meta.attached_bus:
41+
raise LookupError(
42+
f"D-Bus proxy {obj!r} at {dbus_meta.object_path!r} path "
43+
f"is not attached to bus {bus!r}"
44+
)
45+
46+
return dbus_meta.object_path
47+
48+
49+
def _inspect_dbus_path_local(
50+
obj: object,
51+
dbus_meta: DbusLocalObjectMeta,
52+
bus: SdBus,
53+
) -> str:
54+
attached_bus = dbus_meta.attached_bus
55+
object_path = dbus_meta.serving_object_path
56+
if attached_bus is None or object_path is None:
57+
raise LookupError(
58+
f"Local D-Bus object {obj!r} is not exported to any D-Bus"
59+
)
60+
61+
if bus != attached_bus:
62+
raise LookupError(
63+
f"Local D-Bus object {obj!r} at {dbus_meta.serving_object_path!r} "
64+
f"path is not attached to bus {bus!r}"
65+
)
66+
67+
return object_path
68+
69+
70+
def inspect_dbus_path(
71+
obj: Union[DbusInterfaceBase, DbusInterfaceBaseAsync],
72+
bus: Optional[SdBus] = None,
73+
) -> str:
74+
if bus is None:
75+
bus = get_default_bus()
76+
77+
if isinstance(obj, DbusInterfaceBase):
78+
return _inspect_dbus_path_proxy(obj, obj._dbus, bus)
79+
elif isinstance(obj, DbusInterfaceBaseAsync):
80+
dbus_meta = obj._dbus
81+
if isinstance(dbus_meta, DbusRemoteObjectMeta):
82+
return _inspect_dbus_path_proxy(obj, dbus_meta, bus)
83+
else:
84+
return _inspect_dbus_path_local(obj, dbus_meta, bus)
85+
else:
86+
raise TypeError(f"Expected D-Bus object got {obj!r}")

test/test_sdbus_utils.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# SPDX-License-Identifier: LGPL-2.1-or-later
2+
3+
# Copyright (C) 2024 igo95862
4+
5+
# This file is part of python-sdbus
6+
7+
# This library is free software; you can redistribute it and/or
8+
# modify it under the terms of the GNU Lesser General Public
9+
# License as published by the Free Software Foundation; either
10+
# version 2.1 of the License, or (at your option) any later version.
11+
12+
# This library is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
# Lesser General Public License for more details.
16+
17+
# You should have received a copy of the GNU Lesser General Public
18+
# License along with this library; if not, write to the Free Software
19+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
from __future__ import annotations
21+
22+
from sdbus.unittest import IsolatedDbusTestCase
23+
from sdbus.utils.inspect import inspect_dbus_path
24+
25+
from sdbus import (
26+
DbusInterfaceCommon,
27+
DbusInterfaceCommonAsync,
28+
sd_bus_open_user,
29+
)
30+
31+
TEST_PATH = "/test"
32+
33+
34+
class TestSdbusUtilsInspect(IsolatedDbusTestCase):
35+
def test_inspect_dbus_path_block(self) -> None:
36+
proxy = DbusInterfaceCommon("example.org", TEST_PATH)
37+
38+
self.assertEqual(inspect_dbus_path(proxy), TEST_PATH)
39+
40+
new_bus = sd_bus_open_user()
41+
42+
with self.assertRaisesRegex(LookupError, "is not attached to bus"):
43+
inspect_dbus_path(proxy, new_bus)
44+
45+
def test_inspect_dbus_path_async_proxy(self) -> None:
46+
proxy = DbusInterfaceCommonAsync.new_proxy("example.org", TEST_PATH)
47+
48+
self.assertEqual(inspect_dbus_path(proxy), TEST_PATH)
49+
50+
new_bus = sd_bus_open_user()
51+
52+
with self.assertRaisesRegex(LookupError, "is not attached to bus"):
53+
inspect_dbus_path(proxy, new_bus)
54+
55+
def test_inspect_dbus_path_async_local(self) -> None:
56+
local_obj = DbusInterfaceCommonAsync()
57+
58+
with self.assertRaisesRegex(
59+
LookupError, "is not exported to any D-Bus",
60+
):
61+
inspect_dbus_path(local_obj)
62+
63+
local_obj.export_to_dbus(TEST_PATH)
64+
65+
self.assertEqual(inspect_dbus_path(local_obj), TEST_PATH)
66+
67+
new_bus = sd_bus_open_user()
68+
69+
with self.assertRaisesRegex(LookupError, "is not attached to bus"):
70+
inspect_dbus_path(local_obj, new_bus)

0 commit comments

Comments
 (0)