dbus-fast 2.44.6__cp313-cp313-manylinux_2_36_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of dbus-fast might be problematic. Click here for more details.
- dbus_fast/__init__.py +82 -0
- dbus_fast/__version__.py +10 -0
- dbus_fast/_private/__init__.py +1 -0
- dbus_fast/_private/_cython_compat.py +14 -0
- dbus_fast/_private/address.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/_private/address.pxd +15 -0
- dbus_fast/_private/address.py +117 -0
- dbus_fast/_private/constants.py +20 -0
- dbus_fast/_private/marshaller.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/_private/marshaller.pxd +110 -0
- dbus_fast/_private/marshaller.py +228 -0
- dbus_fast/_private/unmarshaller.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/_private/unmarshaller.pxd +261 -0
- dbus_fast/_private/unmarshaller.py +902 -0
- dbus_fast/_private/util.py +176 -0
- dbus_fast/aio/__init__.py +5 -0
- dbus_fast/aio/message_bus.py +578 -0
- dbus_fast/aio/message_reader.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/aio/message_reader.pxd +13 -0
- dbus_fast/aio/message_reader.py +49 -0
- dbus_fast/aio/proxy_object.py +207 -0
- dbus_fast/auth.py +126 -0
- dbus_fast/constants.py +152 -0
- dbus_fast/errors.py +84 -0
- dbus_fast/glib/__init__.py +3 -0
- dbus_fast/glib/message_bus.py +515 -0
- dbus_fast/glib/proxy_object.py +319 -0
- dbus_fast/introspection.py +683 -0
- dbus_fast/message.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/message.pxd +76 -0
- dbus_fast/message.py +387 -0
- dbus_fast/message_bus.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/message_bus.pxd +75 -0
- dbus_fast/message_bus.py +1310 -0
- dbus_fast/proxy_object.py +358 -0
- dbus_fast/py.typed +0 -0
- dbus_fast/send_reply.py +61 -0
- dbus_fast/service.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/service.pxd +50 -0
- dbus_fast/service.py +682 -0
- dbus_fast/signature.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/signature.pxd +31 -0
- dbus_fast/signature.py +481 -0
- dbus_fast/unpack.cpython-313-x86_64-linux-gnu.so +0 -0
- dbus_fast/unpack.pxd +13 -0
- dbus_fast/unpack.py +24 -0
- dbus_fast/validators.py +199 -0
- dbus_fast-2.44.6.dist-info/METADATA +263 -0
- dbus_fast-2.44.6.dist-info/RECORD +51 -0
- dbus_fast-2.44.6.dist-info/WHEEL +4 -0
- dbus_fast-2.44.6.dist-info/licenses/LICENSE +22 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import xml.etree.ElementTree as ET
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
from .. import introspection as intr
|
|
7
|
+
from .._private.util import replace_fds_with_idx, replace_idx_with_fds
|
|
8
|
+
from ..constants import ErrorType, MessageFlag
|
|
9
|
+
from ..errors import DBusError
|
|
10
|
+
from ..message import Message
|
|
11
|
+
from ..message_bus import BaseMessageBus
|
|
12
|
+
from ..proxy_object import BaseProxyInterface, BaseProxyObject
|
|
13
|
+
from ..signature import Variant
|
|
14
|
+
from ..unpack import unpack_variants as unpack
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from .message_bus import MessageBus as AioMessageBus
|
|
18
|
+
|
|
19
|
+
NO_REPLY_EXPECTED_VALUE = MessageFlag.NO_REPLY_EXPECTED.value
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ProxyInterface(BaseProxyInterface):
|
|
23
|
+
"""A class representing a proxy to an interface exported on the bus by
|
|
24
|
+
another client for the asyncio :class:`MessageBus
|
|
25
|
+
<dbus_fast.aio.MessageBus>` implementation.
|
|
26
|
+
|
|
27
|
+
This class is not meant to be constructed directly by the user. Use
|
|
28
|
+
:func:`ProxyObject.get_interface()
|
|
29
|
+
<dbus_fast.aio.ProxyObject.get_interface>` on a asyncio proxy object to get
|
|
30
|
+
a proxy interface.
|
|
31
|
+
|
|
32
|
+
This class exposes methods to call DBus methods, listen to signals, and get
|
|
33
|
+
and set properties on the interface that are created dynamically based on
|
|
34
|
+
the introspection data passed to the proxy object that made this proxy
|
|
35
|
+
interface.
|
|
36
|
+
|
|
37
|
+
A *method call* takes this form:
|
|
38
|
+
|
|
39
|
+
.. code-block:: python3
|
|
40
|
+
|
|
41
|
+
result = await interface.call_[METHOD](*args)
|
|
42
|
+
|
|
43
|
+
Where ``METHOD`` is the name of the method converted to snake case.
|
|
44
|
+
|
|
45
|
+
DBus methods are exposed as coroutines that take arguments that correpond
|
|
46
|
+
to the *in args* of the interface method definition and return a ``result``
|
|
47
|
+
that corresponds to the *out arg*. If the method has more than one out arg,
|
|
48
|
+
they are returned within a :class:`list`.
|
|
49
|
+
|
|
50
|
+
To *listen to a signal* use this form:
|
|
51
|
+
|
|
52
|
+
.. code-block:: python3
|
|
53
|
+
|
|
54
|
+
interface.on_[SIGNAL](callback)
|
|
55
|
+
|
|
56
|
+
To *stop listening to a signal* use this form:
|
|
57
|
+
|
|
58
|
+
.. code-block:: python3
|
|
59
|
+
|
|
60
|
+
interface.off_[SIGNAL](callback)
|
|
61
|
+
|
|
62
|
+
Where ``SIGNAL`` is the name of the signal converted to snake case.
|
|
63
|
+
|
|
64
|
+
DBus signals are exposed with an event-callback interface. The provided
|
|
65
|
+
``callback`` will be called when the signal is emitted with arguments that
|
|
66
|
+
correspond to the *out args* of the interface signal definition.
|
|
67
|
+
|
|
68
|
+
To *get or set a property* use this form:
|
|
69
|
+
|
|
70
|
+
.. code-block:: python3
|
|
71
|
+
|
|
72
|
+
value = await interface.get_[PROPERTY]()
|
|
73
|
+
await interface.set_[PROPERTY](value)
|
|
74
|
+
|
|
75
|
+
Where ``PROPERTY`` is the name of the property converted to snake case.
|
|
76
|
+
|
|
77
|
+
DBus property getters and setters are exposed as coroutines. The ``value``
|
|
78
|
+
must correspond to the type of the property in the interface definition.
|
|
79
|
+
|
|
80
|
+
If the service returns an error for a DBus call, a :class:`DBusError
|
|
81
|
+
<dbus_fast.DBusError>` will be raised with information about the error.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
bus: AioMessageBus
|
|
85
|
+
|
|
86
|
+
def _add_method(self, intr_method: intr.Method) -> None:
|
|
87
|
+
async def method_fn(
|
|
88
|
+
*args, flags=MessageFlag.NONE, unpack_variants: bool = False
|
|
89
|
+
):
|
|
90
|
+
input_body, unix_fds = replace_fds_with_idx(
|
|
91
|
+
intr_method.in_signature, list(args)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
msg = await self.bus.call(
|
|
95
|
+
Message(
|
|
96
|
+
destination=self.bus_name,
|
|
97
|
+
path=self.path,
|
|
98
|
+
interface=self.introspection.name,
|
|
99
|
+
member=intr_method.name,
|
|
100
|
+
signature=intr_method.in_signature,
|
|
101
|
+
body=input_body,
|
|
102
|
+
flags=flags,
|
|
103
|
+
unix_fds=unix_fds,
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if flags is not None and flags.value & NO_REPLY_EXPECTED_VALUE:
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
BaseProxyInterface._check_method_return(msg, intr_method.out_signature)
|
|
111
|
+
|
|
112
|
+
out_len = len(intr_method.out_args)
|
|
113
|
+
|
|
114
|
+
body = replace_idx_with_fds(msg.signature_tree, msg.body, msg.unix_fds)
|
|
115
|
+
|
|
116
|
+
if not out_len:
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
if unpack_variants:
|
|
120
|
+
body = unpack(body)
|
|
121
|
+
|
|
122
|
+
if out_len == 1:
|
|
123
|
+
return body[0]
|
|
124
|
+
return body
|
|
125
|
+
|
|
126
|
+
method_name = f"call_{BaseProxyInterface._to_snake_case(intr_method.name)}"
|
|
127
|
+
setattr(self, method_name, method_fn)
|
|
128
|
+
|
|
129
|
+
def _add_property(
|
|
130
|
+
self,
|
|
131
|
+
intr_property: intr.Property,
|
|
132
|
+
) -> None:
|
|
133
|
+
async def property_getter(
|
|
134
|
+
*, flags=MessageFlag.NONE, unpack_variants: bool = False
|
|
135
|
+
):
|
|
136
|
+
msg = await self.bus.call(
|
|
137
|
+
Message(
|
|
138
|
+
destination=self.bus_name,
|
|
139
|
+
path=self.path,
|
|
140
|
+
interface="org.freedesktop.DBus.Properties",
|
|
141
|
+
member="Get",
|
|
142
|
+
signature="ss",
|
|
143
|
+
body=[self.introspection.name, intr_property.name],
|
|
144
|
+
)
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
BaseProxyInterface._check_method_return(msg, "v")
|
|
148
|
+
variant = msg.body[0]
|
|
149
|
+
if variant.signature != intr_property.signature:
|
|
150
|
+
raise DBusError(
|
|
151
|
+
ErrorType.CLIENT_ERROR,
|
|
152
|
+
f'property returned unexpected signature "{variant.signature}"',
|
|
153
|
+
msg,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
body = replace_idx_with_fds("v", msg.body, msg.unix_fds)[0].value
|
|
157
|
+
|
|
158
|
+
if unpack_variants:
|
|
159
|
+
return unpack(body)
|
|
160
|
+
return body
|
|
161
|
+
|
|
162
|
+
async def property_setter(val: Any) -> None:
|
|
163
|
+
variant = Variant(intr_property.signature, val)
|
|
164
|
+
|
|
165
|
+
body, unix_fds = replace_fds_with_idx(
|
|
166
|
+
"ssv", [self.introspection.name, intr_property.name, variant]
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
msg = await self.bus.call(
|
|
170
|
+
Message(
|
|
171
|
+
destination=self.bus_name,
|
|
172
|
+
path=self.path,
|
|
173
|
+
interface="org.freedesktop.DBus.Properties",
|
|
174
|
+
member="Set",
|
|
175
|
+
signature="ssv",
|
|
176
|
+
body=body,
|
|
177
|
+
unix_fds=unix_fds,
|
|
178
|
+
)
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
BaseProxyInterface._check_method_return(msg)
|
|
182
|
+
|
|
183
|
+
snake_case = BaseProxyInterface._to_snake_case(intr_property.name)
|
|
184
|
+
setattr(self, f"get_{snake_case}", property_getter)
|
|
185
|
+
setattr(self, f"set_{snake_case}", property_setter)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class ProxyObject(BaseProxyObject):
|
|
189
|
+
"""The proxy object implementation for the GLib :class:`MessageBus <dbus_fast.glib.MessageBus>`.
|
|
190
|
+
|
|
191
|
+
For more information, see the :class:`BaseProxyObject <dbus_fast.proxy_object.BaseProxyObject>`.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
def __init__(
|
|
195
|
+
self,
|
|
196
|
+
bus_name: str,
|
|
197
|
+
path: str,
|
|
198
|
+
introspection: intr.Node | str | ET.Element,
|
|
199
|
+
bus: BaseMessageBus,
|
|
200
|
+
) -> None:
|
|
201
|
+
super().__init__(bus_name, path, introspection, bus, ProxyInterface)
|
|
202
|
+
|
|
203
|
+
def get_interface(self, name: str) -> ProxyInterface:
|
|
204
|
+
return super().get_interface(name)
|
|
205
|
+
|
|
206
|
+
def get_children(self) -> list[ProxyObject]:
|
|
207
|
+
return super().get_children()
|
dbus_fast/auth.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
import os
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from .errors import AuthError
|
|
6
|
+
|
|
7
|
+
UID_NOT_SPECIFIED = -1
|
|
8
|
+
|
|
9
|
+
# The auth interface here is unstable. I would like to eventually open this up
|
|
10
|
+
# for people to define their own custom authentication protocols, but I'm not
|
|
11
|
+
# familiar with what's needed for that exactly. To work with any message bus
|
|
12
|
+
# implementation would require abstracting out all the IO. Async operations
|
|
13
|
+
# might be challenging because different IO backends have different ways of
|
|
14
|
+
# doing that. I might just end up giving the raw socket and leaving it all up
|
|
15
|
+
# to the user, but it would be nice to have a little guidance in the interface
|
|
16
|
+
# since a lot of it is strongly specified. If you have a need for this, contact
|
|
17
|
+
# the project maintainer to help stabilize this interface.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class _AuthResponse(enum.Enum):
|
|
21
|
+
OK = "OK"
|
|
22
|
+
REJECTED = "REJECTED"
|
|
23
|
+
DATA = "DATA"
|
|
24
|
+
ERROR = "ERROR"
|
|
25
|
+
AGREE_UNIX_FD = "AGREE_UNIX_FD"
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def parse(klass, line: str) -> tuple["_AuthResponse", list[str]]:
|
|
29
|
+
args = line.split(" ")
|
|
30
|
+
response = klass(args[0])
|
|
31
|
+
return response, args[1:]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# UNSTABLE
|
|
35
|
+
class Authenticator:
|
|
36
|
+
"""The base class for authenticators for :class:`MessageBus <dbus_fast.message_bus.BaseMessageBus>` authentication.
|
|
37
|
+
|
|
38
|
+
In the future, the library may allow extending this class for custom authentication protocols.
|
|
39
|
+
|
|
40
|
+
:seealso: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def _authentication_start(self, negotiate_unix_fd: bool = False) -> str:
|
|
44
|
+
raise NotImplementedError(
|
|
45
|
+
"authentication_start() must be implemented in the inheriting class"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def _receive_line(self, line: str) -> str:
|
|
49
|
+
raise NotImplementedError(
|
|
50
|
+
"receive_line() must be implemented in the inheriting class"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def _format_line(line: str) -> bytes:
|
|
55
|
+
return f"{line}\r\n".encode()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class AuthExternal(Authenticator):
|
|
59
|
+
"""An authenticator class for the external auth protocol for use with the
|
|
60
|
+
:class:`MessageBus <dbus_fast.message_bus.BaseMessageBus>`.
|
|
61
|
+
|
|
62
|
+
:param uid: The uid to use when connecting to the message bus. Use UID_NOT_SPECIFIED to use the uid known to the kernel.
|
|
63
|
+
:vartype uid: int
|
|
64
|
+
|
|
65
|
+
:sealso: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(self, uid: Optional[int] = None) -> None:
|
|
69
|
+
self.negotiate_unix_fd: bool = False
|
|
70
|
+
self.negotiating_fds: bool = False
|
|
71
|
+
self.uid: Optional[int] = uid
|
|
72
|
+
|
|
73
|
+
def _authentication_start(self, negotiate_unix_fd: bool = False) -> str:
|
|
74
|
+
self.negotiate_unix_fd = negotiate_unix_fd
|
|
75
|
+
uid = self.uid
|
|
76
|
+
if uid == UID_NOT_SPECIFIED:
|
|
77
|
+
return "AUTH EXTERNAL"
|
|
78
|
+
if uid is None:
|
|
79
|
+
uid = os.getuid()
|
|
80
|
+
hex_uid = str(uid).encode().hex()
|
|
81
|
+
return f"AUTH EXTERNAL {hex_uid}"
|
|
82
|
+
|
|
83
|
+
def _receive_line(self, line: str) -> str:
|
|
84
|
+
response, args = _AuthResponse.parse(line)
|
|
85
|
+
|
|
86
|
+
if response is _AuthResponse.OK:
|
|
87
|
+
if self.negotiate_unix_fd:
|
|
88
|
+
self.negotiating_fds = True
|
|
89
|
+
return "NEGOTIATE_UNIX_FD"
|
|
90
|
+
return "BEGIN"
|
|
91
|
+
|
|
92
|
+
if response is _AuthResponse.AGREE_UNIX_FD:
|
|
93
|
+
return "BEGIN"
|
|
94
|
+
|
|
95
|
+
if response is _AuthResponse.DATA and self.uid == UID_NOT_SPECIFIED:
|
|
96
|
+
return "DATA"
|
|
97
|
+
|
|
98
|
+
raise AuthError(f"authentication failed: {response.value}: {args}")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class AuthAnonymous(Authenticator):
|
|
102
|
+
"""An authenticator class for the anonymous auth protocol for use with the
|
|
103
|
+
:class:`MessageBus <dbus_fast.message_bus.BaseMessageBus>`.
|
|
104
|
+
|
|
105
|
+
:sealso: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
def _authentication_start(self, negotiate_unix_fd: bool = False) -> str:
|
|
109
|
+
if negotiate_unix_fd:
|
|
110
|
+
raise AuthError(
|
|
111
|
+
"anonymous authentication does not support negotiating unix fds right now"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
return "AUTH ANONYMOUS"
|
|
115
|
+
|
|
116
|
+
def _receive_line(self, line: str) -> str:
|
|
117
|
+
response, args = _AuthResponse.parse(line)
|
|
118
|
+
|
|
119
|
+
if response != _AuthResponse.OK:
|
|
120
|
+
raise AuthError(f"authentication failed: {response.value}: {args}")
|
|
121
|
+
|
|
122
|
+
return "BEGIN"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# The following line provides backwards compatibility, remove at some point? --jrd
|
|
126
|
+
AuthAnnonymous = AuthAnonymous
|
dbus_fast/constants.py
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from enum import Enum, IntFlag
|
|
2
|
+
from functools import cached_property
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BusType(Enum):
|
|
6
|
+
"""An enum that indicates a type of bus. On most systems, there are
|
|
7
|
+
normally two different kinds of buses running.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
SESSION = 1 #: A bus for the current graphical user session.
|
|
11
|
+
SYSTEM = 2 #: A persistent bus for the whole machine.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MessageType(Enum):
|
|
15
|
+
"""An enum that indicates a type of message."""
|
|
16
|
+
|
|
17
|
+
METHOD_CALL = 1 #: An outgoing method call.
|
|
18
|
+
METHOD_RETURN = 2 #: A return to a previously sent method call
|
|
19
|
+
ERROR = 3 #: A return to a method call that has failed
|
|
20
|
+
SIGNAL = 4 #: A broadcast signal to subscribed connections
|
|
21
|
+
|
|
22
|
+
@cached_property
|
|
23
|
+
def value(self) -> int:
|
|
24
|
+
"""Return the value."""
|
|
25
|
+
return self._value_
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
MESSAGE_TYPE_MAP = {field.value: field for field in MessageType}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class MessageFlag(IntFlag):
|
|
32
|
+
"""Flags that affect the behavior of sent and received messages"""
|
|
33
|
+
|
|
34
|
+
NONE = 0
|
|
35
|
+
NO_REPLY_EXPECTED = 1 #: The method call does not expect a method return.
|
|
36
|
+
NO_AUTOSTART = 2
|
|
37
|
+
ALLOW_INTERACTIVE_AUTHORIZATION = 4
|
|
38
|
+
|
|
39
|
+
@cached_property
|
|
40
|
+
def value(self) -> int:
|
|
41
|
+
"""Return the value."""
|
|
42
|
+
return self._value_
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# This is written out because of https://github.com/python/cpython/issues/98976
|
|
46
|
+
MESSAGE_FLAG_MAP = {
|
|
47
|
+
0: MessageFlag.NONE,
|
|
48
|
+
1: MessageFlag.NO_REPLY_EXPECTED,
|
|
49
|
+
2: MessageFlag.NO_AUTOSTART,
|
|
50
|
+
4: MessageFlag.ALLOW_INTERACTIVE_AUTHORIZATION,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class NameFlag(IntFlag):
|
|
55
|
+
"""A flag that affects the behavior of a name request."""
|
|
56
|
+
|
|
57
|
+
NONE = 0
|
|
58
|
+
ALLOW_REPLACEMENT = 1 #: If another client requests this name, let them have it.
|
|
59
|
+
REPLACE_EXISTING = 2 #: If another client owns this name, try to take it.
|
|
60
|
+
DO_NOT_QUEUE = 4 #: Name requests normally queue and wait for the owner to release the name. Do not enter this queue.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class RequestNameReply(Enum):
|
|
64
|
+
"""An enum that describes the result of a name request."""
|
|
65
|
+
|
|
66
|
+
PRIMARY_OWNER = 1 #: The bus owns the name.
|
|
67
|
+
IN_QUEUE = 2 #: The bus is in a queue and may receive the name after it is relased by the primary owner.
|
|
68
|
+
EXISTS = 3 #: The name has an owner and NameFlag.DO_NOT_QUEUE was given.
|
|
69
|
+
ALREADY_OWNER = 4 #: The bus already owns the name.
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ReleaseNameReply(Enum):
|
|
73
|
+
"""An enum that describes the result of a name release request"""
|
|
74
|
+
|
|
75
|
+
RELEASED = 1
|
|
76
|
+
NON_EXISTENT = 2
|
|
77
|
+
NOT_OWNER = 3
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class PropertyAccess(Enum):
|
|
81
|
+
"""An enum that describes whether a DBus property can be gotten or set with
|
|
82
|
+
the ``org.freedesktop.DBus.Properties`` interface.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
READ = "read" #: The property is readonly.
|
|
86
|
+
WRITE = "write" #: The property is writeonly.
|
|
87
|
+
READWRITE = "readwrite" #: The property can be read or written to.
|
|
88
|
+
|
|
89
|
+
def readable(self) -> bool:
|
|
90
|
+
"""Get whether the property can be read."""
|
|
91
|
+
return self == PropertyAccess.READ or self == PropertyAccess.READWRITE
|
|
92
|
+
|
|
93
|
+
def writable(self) -> bool:
|
|
94
|
+
"""Get whether the property can be written to."""
|
|
95
|
+
return self == PropertyAccess.WRITE or self == PropertyAccess.READWRITE
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class ArgDirection(Enum):
|
|
99
|
+
"""For an introspected argument, indicates whether it is an input parameter or a return value."""
|
|
100
|
+
|
|
101
|
+
IN = "in"
|
|
102
|
+
OUT = "out"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class ErrorType(str, Enum):
|
|
106
|
+
"""An enum for the type of an error for a message reply.
|
|
107
|
+
|
|
108
|
+
:seealso: http://man7.org/linux/man-pages/man3/sd-bus-errors.3.html
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
SERVICE_ERROR = "com.dubstepdish.dbus.next.ServiceError" #: A custom error to indicate an exported service threw an exception.
|
|
112
|
+
INTERNAL_ERROR = "com.dubstepdish.dbus.next.InternalError" #: A custom error to indicate something went wrong with the library.
|
|
113
|
+
CLIENT_ERROR = "com.dubstepdish.dbus.next.ClientError" #: A custom error to indicate something went wrong with the client.
|
|
114
|
+
|
|
115
|
+
FAILED = "org.freedesktop.DBus.Error.Failed"
|
|
116
|
+
NO_MEMORY = "org.freedesktop.DBus.Error.NoMemory"
|
|
117
|
+
SERVICE_UNKNOWN = "org.freedesktop.DBus.Error.ServiceUnknown"
|
|
118
|
+
NAME_HAS_NO_OWNER = "org.freedesktop.DBus.Error.NameHasNoOwner"
|
|
119
|
+
NO_REPLY = "org.freedesktop.DBus.Error.NoReply"
|
|
120
|
+
IO_ERROR = "org.freedesktop.DBus.Error.IOError"
|
|
121
|
+
BAD_ADDRESS = "org.freedesktop.DBus.Error.BadAddress"
|
|
122
|
+
NOT_SUPPORTED = "org.freedesktop.DBus.Error.NotSupported"
|
|
123
|
+
LIMITS_EXCEEDED = "org.freedesktop.DBus.Error.LimitsExceeded"
|
|
124
|
+
ACCESS_DENIED = "org.freedesktop.DBus.Error.AccessDenied"
|
|
125
|
+
AUTH_FAILED = "org.freedesktop.DBus.Error.AuthFailed"
|
|
126
|
+
NO_SERVER = "org.freedesktop.DBus.Error.NoServer"
|
|
127
|
+
TIMEOUT = "org.freedesktop.DBus.Error.Timeout"
|
|
128
|
+
NO_NETWORK = "org.freedesktop.DBus.Error.NoNetwork"
|
|
129
|
+
ADDRESS_IN_USE = "org.freedesktop.DBus.Error.AddressInUse"
|
|
130
|
+
DISCONNECTED = "org.freedesktop.DBus.Error.Disconnected"
|
|
131
|
+
INVALID_ARGS = "org.freedesktop.DBus.Error.InvalidArgs"
|
|
132
|
+
FILE_NOT_FOUND = "org.freedesktop.DBus.Error.FileNotFound"
|
|
133
|
+
FILE_EXISTS = "org.freedesktop.DBus.Error.FileExists"
|
|
134
|
+
UNKNOWN_METHOD = "org.freedesktop.DBus.Error.UnknownMethod"
|
|
135
|
+
UNKNOWN_OBJECT = "org.freedesktop.DBus.Error.UnknownObject"
|
|
136
|
+
UNKNOWN_INTERFACE = "org.freedesktop.DBus.Error.UnknownInterface"
|
|
137
|
+
UNKNOWN_PROPERTY = "org.freedesktop.DBus.Error.UnknownProperty"
|
|
138
|
+
PROPERTY_READ_ONLY = "org.freedesktop.DBus.Error.PropertyReadOnly"
|
|
139
|
+
UNIX_PROCESS_ID_UNKNOWN = "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
|
|
140
|
+
INVALID_SIGNATURE = "org.freedesktop.DBus.Error.InvalidSignature"
|
|
141
|
+
INCONSISTENT_MESSAGE = "org.freedesktop.DBus.Error.InconsistentMessage"
|
|
142
|
+
TIMED_OUT = "org.freedesktop.DBus.Error.TimedOut"
|
|
143
|
+
MATCH_RULE_NOT_FOUND = "org.freedesktop.DBus.Error.MatchRuleNotFound"
|
|
144
|
+
MATCH_RULE_INVALID = "org.freedesktop.DBus.Error.MatchRuleInvalid"
|
|
145
|
+
INTERACTIVE_AUTHORIZATION_REQUIRED = (
|
|
146
|
+
"org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"
|
|
147
|
+
)
|
|
148
|
+
INVALID_FILE_CONTENT = "org.freedesktop.DBus.Error.InvalidFileContent"
|
|
149
|
+
SELINUX_SECURITY_CONTEXT_UNKNOWN = (
|
|
150
|
+
"org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"
|
|
151
|
+
)
|
|
152
|
+
OBJECT_PATH_IN_USE = "org.freedesktop.DBus.Error.ObjectPathInUse"
|
dbus_fast/errors.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from typing import Optional, Union
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SignatureBodyMismatchError(ValueError):
|
|
5
|
+
pass
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class InvalidSignatureError(ValueError):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class InvalidAddressError(ValueError):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AuthError(Exception):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class InvalidMessageError(ValueError):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class InvalidIntrospectionError(ValueError):
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class InterfaceNotFoundError(Exception):
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SignalDisabledError(Exception):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class InvalidBusNameError(TypeError):
|
|
37
|
+
def __init__(self, name: str) -> None:
|
|
38
|
+
super().__init__(f"invalid bus name: {name}")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class InvalidObjectPathError(TypeError):
|
|
42
|
+
def __init__(self, path: str) -> None:
|
|
43
|
+
super().__init__(f"invalid object path: {path}")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class InvalidInterfaceNameError(TypeError):
|
|
47
|
+
def __init__(self, name: str) -> None:
|
|
48
|
+
super().__init__(f"invalid interface name: {name}")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class InvalidMemberNameError(TypeError):
|
|
52
|
+
def __init__(self, member: str) -> None:
|
|
53
|
+
super().__init__(f"invalid member name: {member}")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
from .constants import ErrorType, MessageType # noqa: E402
|
|
57
|
+
from .message import Message # noqa: E402
|
|
58
|
+
from .validators import assert_interface_name_valid # noqa: E402
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class DBusError(Exception):
|
|
62
|
+
def __init__(
|
|
63
|
+
self, type_: Union[ErrorType, str], text: str, reply: Optional[Message] = None
|
|
64
|
+
) -> None:
|
|
65
|
+
super().__init__(text)
|
|
66
|
+
|
|
67
|
+
if type(type_) is ErrorType:
|
|
68
|
+
type_ = type_.value
|
|
69
|
+
|
|
70
|
+
assert_interface_name_valid(type_) # type: ignore[arg-type]
|
|
71
|
+
if reply is not None and type(reply) is not Message:
|
|
72
|
+
raise TypeError("reply must be of type Message")
|
|
73
|
+
|
|
74
|
+
self.type = type_
|
|
75
|
+
self.text = text
|
|
76
|
+
self.reply = reply
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def _from_message(msg: Message) -> "DBusError":
|
|
80
|
+
assert msg.message_type == MessageType.ERROR
|
|
81
|
+
return DBusError(msg.error_name or "unknown", msg.body[0], reply=msg)
|
|
82
|
+
|
|
83
|
+
def _as_message(self, msg: Message) -> Message:
|
|
84
|
+
return Message.new_error(msg, self.type, self.text)
|