dbus-fast 2.46.1__cp311-cp311-musllinux_1_2_aarch64.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.

Files changed (51) hide show
  1. dbus_fast/__init__.py +82 -0
  2. dbus_fast/__version__.py +10 -0
  3. dbus_fast/_private/__init__.py +1 -0
  4. dbus_fast/_private/_cython_compat.py +14 -0
  5. dbus_fast/_private/address.cpython-311-aarch64-linux-musl.so +0 -0
  6. dbus_fast/_private/address.pxd +15 -0
  7. dbus_fast/_private/address.py +117 -0
  8. dbus_fast/_private/constants.py +20 -0
  9. dbus_fast/_private/marshaller.cpython-311-aarch64-linux-musl.so +0 -0
  10. dbus_fast/_private/marshaller.pxd +110 -0
  11. dbus_fast/_private/marshaller.py +229 -0
  12. dbus_fast/_private/unmarshaller.cpython-311-aarch64-linux-musl.so +0 -0
  13. dbus_fast/_private/unmarshaller.pxd +261 -0
  14. dbus_fast/_private/unmarshaller.py +902 -0
  15. dbus_fast/_private/util.py +177 -0
  16. dbus_fast/aio/__init__.py +5 -0
  17. dbus_fast/aio/message_bus.py +579 -0
  18. dbus_fast/aio/message_reader.cpython-311-aarch64-linux-musl.so +0 -0
  19. dbus_fast/aio/message_reader.pxd +13 -0
  20. dbus_fast/aio/message_reader.py +49 -0
  21. dbus_fast/aio/proxy_object.py +207 -0
  22. dbus_fast/auth.py +125 -0
  23. dbus_fast/constants.py +152 -0
  24. dbus_fast/errors.py +81 -0
  25. dbus_fast/glib/__init__.py +3 -0
  26. dbus_fast/glib/message_bus.py +513 -0
  27. dbus_fast/glib/proxy_object.py +318 -0
  28. dbus_fast/introspection.py +682 -0
  29. dbus_fast/message.cpython-311-aarch64-linux-musl.so +0 -0
  30. dbus_fast/message.pxd +76 -0
  31. dbus_fast/message.py +387 -0
  32. dbus_fast/message_bus.cpython-311-aarch64-linux-musl.so +0 -0
  33. dbus_fast/message_bus.pxd +75 -0
  34. dbus_fast/message_bus.py +1326 -0
  35. dbus_fast/proxy_object.py +357 -0
  36. dbus_fast/py.typed +0 -0
  37. dbus_fast/send_reply.py +61 -0
  38. dbus_fast/service.cpython-311-aarch64-linux-musl.so +0 -0
  39. dbus_fast/service.pxd +50 -0
  40. dbus_fast/service.py +699 -0
  41. dbus_fast/signature.cpython-311-aarch64-linux-musl.so +0 -0
  42. dbus_fast/signature.pxd +31 -0
  43. dbus_fast/signature.py +482 -0
  44. dbus_fast/unpack.cpython-311-aarch64-linux-musl.so +0 -0
  45. dbus_fast/unpack.pxd +13 -0
  46. dbus_fast/unpack.py +24 -0
  47. dbus_fast/validators.py +199 -0
  48. dbus_fast-2.46.1.dist-info/METADATA +262 -0
  49. dbus_fast-2.46.1.dist-info/RECORD +51 -0
  50. dbus_fast-2.46.1.dist-info/WHEEL +4 -0
  51. dbus_fast-2.46.1.dist-info/licenses/LICENSE +22 -0
@@ -0,0 +1,513 @@
1
+ import io
2
+ import logging
3
+ import traceback
4
+ from collections.abc import Callable
5
+
6
+ from .. import introspection as intr
7
+ from .._private.unmarshaller import Unmarshaller
8
+ from ..auth import Authenticator, AuthExternal
9
+ from ..constants import (
10
+ BusType,
11
+ MessageFlag,
12
+ MessageType,
13
+ NameFlag,
14
+ ReleaseNameReply,
15
+ RequestNameReply,
16
+ )
17
+ from ..errors import AuthError
18
+ from ..message import Message
19
+ from ..message_bus import BaseMessageBus
20
+ from .proxy_object import ProxyObject
21
+
22
+ _LOGGER = logging.getLogger(__name__)
23
+
24
+
25
+ # glib is optional
26
+ _import_error = None
27
+ try:
28
+ from gi.repository import GLib
29
+
30
+ _GLibSource = GLib.Source
31
+ except ImportError as e:
32
+ _import_error = e
33
+
34
+ class _GLibSource:
35
+ pass
36
+
37
+
38
+ class _MessageSource(_GLibSource):
39
+ def __init__(self, bus):
40
+ self.unmarshaller = None
41
+ self.bus = bus
42
+
43
+ def prepare(self):
44
+ return (False, -1)
45
+
46
+ def check(self):
47
+ return False
48
+
49
+ def dispatch(self, callback, user_data):
50
+ try:
51
+ while self.bus._stream.readable():
52
+ if not self.unmarshaller:
53
+ self.unmarshaller = Unmarshaller(self.bus._stream)
54
+
55
+ message = self.unmarshaller.unmarshall()
56
+ if message:
57
+ callback(message)
58
+ self.unmarshaller = None
59
+ else:
60
+ break
61
+ except Exception as e:
62
+ self.bus.disconnect()
63
+ self.bus._finalize(e)
64
+ return GLib.SOURCE_REMOVE
65
+
66
+ return GLib.SOURCE_CONTINUE
67
+
68
+
69
+ class _MessageWritableSource(_GLibSource):
70
+ def __init__(self, bus):
71
+ self.bus = bus
72
+ self.buf = b""
73
+ self.message_stream = None
74
+ self.chunk_size = 128
75
+
76
+ def prepare(self):
77
+ return (False, -1)
78
+
79
+ def check(self):
80
+ return False
81
+
82
+ def dispatch(self, callback, user_data):
83
+ try:
84
+ if self.buf:
85
+ self.bus._stream.write(self.buf)
86
+ self.buf = b""
87
+
88
+ if self.message_stream:
89
+ while True:
90
+ self.buf = self.message_stream.read(self.chunk_size)
91
+ if self.buf == b"":
92
+ break
93
+ self.bus._stream.write(self.buf)
94
+ if len(self.buf) < self.chunk_size:
95
+ self.buf = b""
96
+ break
97
+ self.buf = b""
98
+
99
+ self.bus._stream.flush()
100
+
101
+ if not self.bus._buffered_messages:
102
+ return GLib.SOURCE_REMOVE
103
+ message = self.bus._buffered_messages.pop(0)
104
+ self.message_stream = io.BytesIO(message._marshall(False))
105
+ return GLib.SOURCE_CONTINUE
106
+ except BlockingIOError:
107
+ return GLib.SOURCE_CONTINUE
108
+ except Exception as e:
109
+ self.bus._finalize(e)
110
+ return GLib.SOURCE_REMOVE
111
+
112
+
113
+ class _AuthLineSource(_GLibSource):
114
+ def __init__(self, stream):
115
+ self.stream = stream
116
+ self.buf = b""
117
+
118
+ def prepare(self):
119
+ return (False, -1)
120
+
121
+ def check(self):
122
+ return False
123
+
124
+ def dispatch(self, callback, user_data):
125
+ self.buf += self.stream.read()
126
+ if self.buf[-2:] == b"\r\n":
127
+ resp = callback(self.buf.decode()[:-2])
128
+ if resp:
129
+ return GLib.SOURCE_REMOVE
130
+
131
+ return GLib.SOURCE_CONTINUE
132
+
133
+
134
+ class MessageBus(BaseMessageBus):
135
+ """The message bus implementation for use with the GLib main loop.
136
+
137
+ The message bus class is the entry point into all the features of the
138
+ library. It sets up a connection to the DBus daemon and exposes an
139
+ interface to send and receive messages and expose services.
140
+
141
+ You must call :func:`connect() <dbus_fast.glib.MessageBus.connect>` or
142
+ :func:`connect_sync() <dbus_fast.glib.MessageBus.connect_sync>` before
143
+ using this message bus.
144
+
145
+ :param bus_type: The type of bus to connect to. Affects the search path for
146
+ the bus address.
147
+ :type bus_type: :class:`BusType <dbus_fast.BusType>`
148
+ :param bus_address: A specific bus address to connect to. Should not be
149
+ used under normal circumstances.
150
+ :param auth: The authenticator to use, defaults to an instance of
151
+ :class:`AuthExternal <dbus_fast.auth.AuthExternal>`.
152
+ :type auth: :class:`Authenticator <dbus_fast.auth.Authenticator>`
153
+
154
+ :ivar connected: True if this message bus is expected to be able to send
155
+ and receive messages.
156
+ :vartype connected: bool
157
+ :ivar unique_name: The unique name of the message bus connection. It will
158
+ be :class:`None` until the message bus connects.
159
+ :vartype unique_name: str
160
+ """
161
+
162
+ def __init__(
163
+ self,
164
+ bus_address: str | None = None,
165
+ bus_type: BusType = BusType.SESSION,
166
+ auth: Authenticator | None = None,
167
+ ):
168
+ if _import_error:
169
+ raise _import_error
170
+
171
+ super().__init__(bus_address, bus_type, ProxyObject)
172
+ self._main_context = GLib.main_context_default()
173
+ # buffer messages until connect
174
+ self._buffered_messages = []
175
+
176
+ if auth is None:
177
+ self._auth = AuthExternal()
178
+ else:
179
+ self._auth = auth
180
+
181
+ def _on_message(self, msg: Message) -> None:
182
+ try:
183
+ self._process_message(msg)
184
+ except Exception as e:
185
+ _LOGGER.exception(
186
+ f"got unexpected error processing a message: {e}.\n{traceback.format_exc()}"
187
+ )
188
+
189
+ def connect(
190
+ self,
191
+ connect_notify: None
192
+ | (Callable[["MessageBus", Exception | None], None]) = None,
193
+ ):
194
+ """Connect this message bus to the DBus daemon.
195
+
196
+ This method or the synchronous version must be called before the
197
+ message bus can be used.
198
+
199
+ :param connect_notify: A callback that will be called with this message
200
+ bus. May return an :class:`Exception` on connection errors or
201
+ :class:`AuthError <dbus_fast.AuthError>` on authorization errors.
202
+ :type callback: :class:`Callable`
203
+ """
204
+
205
+ def authenticate_notify(exc):
206
+ if exc is not None:
207
+ if connect_notify is not None:
208
+ connect_notify(None, exc)
209
+ return
210
+ self.message_source = _MessageSource(self)
211
+ self.message_source.set_callback(self._on_message)
212
+ self.message_source.attach(self._main_context)
213
+
214
+ self.writable_source = None
215
+
216
+ self.message_source.add_unix_fd(self._fd, GLib.IO_IN)
217
+
218
+ def on_hello(reply, err):
219
+ if err:
220
+ if connect_notify:
221
+ connect_notify(reply, err)
222
+ return
223
+
224
+ self.unique_name = reply.body[0]
225
+
226
+ for m in self._buffered_messages:
227
+ self.send(m)
228
+
229
+ if connect_notify:
230
+ connect_notify(self, err)
231
+
232
+ hello_msg = Message(
233
+ destination="org.freedesktop.DBus",
234
+ path="/org/freedesktop/DBus",
235
+ interface="org.freedesktop.DBus",
236
+ member="Hello",
237
+ serial=self.next_serial(),
238
+ )
239
+
240
+ self._method_return_handlers[hello_msg.serial] = on_hello
241
+ self._stream.write(hello_msg._marshall(False))
242
+ self._stream.flush()
243
+
244
+ self._authenticate(authenticate_notify)
245
+
246
+ def connect_sync(self) -> "MessageBus":
247
+ """Connect this message bus to the DBus daemon.
248
+
249
+ This method or the asynchronous version must be called before the
250
+ message bus can be used.
251
+
252
+ :returns: This message bus for convenience.
253
+ :rtype: :class:`MessageBus <dbus_fast.glib.MessageBus>`
254
+
255
+ :raises:
256
+ - :class:`AuthError <dbus_fast.AuthError>` - If authorization to \
257
+ the DBus daemon failed.
258
+ - :class:`Exception` - If there was a connection error.
259
+ """
260
+ main = GLib.MainLoop()
261
+ connection_error = None
262
+
263
+ def connect_notify(bus, err):
264
+ nonlocal connection_error
265
+ connection_error = err
266
+ main.quit()
267
+
268
+ self.connect(connect_notify)
269
+ main.run()
270
+
271
+ if connection_error:
272
+ raise connection_error
273
+
274
+ return self
275
+
276
+ def call(
277
+ self,
278
+ msg: Message,
279
+ reply_notify: None
280
+ | (Callable[[Message | None, Exception | None], None]) = None,
281
+ ):
282
+ """Send a method call and asynchronously wait for a reply from the DBus
283
+ daemon.
284
+
285
+ :param msg: The method call message to send.
286
+ :type msg: :class:`Message <dbus_fast.Message>`
287
+ :param reply_notify: A callback that will be called with the reply to
288
+ this message. May return an :class:`Exception` on connection errors.
289
+ :type reply_notify: Callable
290
+ """
291
+ BaseMessageBus._check_callback_type(reply_notify)
292
+ self._call(msg, reply_notify)
293
+
294
+ def call_sync(self, msg: Message) -> Message | None:
295
+ """Send a method call and synchronously wait for a reply from the DBus
296
+ daemon.
297
+
298
+ :param msg: The method call message to send.
299
+ :type msg: :class:`Message <dbus_fast.Message>`
300
+
301
+ :returns: A message in reply to the message sent. If the message does
302
+ not expect a reply based on the message flags or type, returns
303
+ ``None`` immediately.
304
+ :rtype: :class:`Message <dbus_fast.Message>`
305
+
306
+ :raises:
307
+ - :class:`DBusError <dbus_fast.DBusError>` - If the service threw \
308
+ an error for the method call or returned an invalid result.
309
+ - :class:`Exception` - If a connection error occurred.
310
+ """
311
+ if (
312
+ msg.flags & MessageFlag.NO_REPLY_EXPECTED
313
+ or msg.message_type is not MessageType.METHOD_CALL
314
+ ):
315
+ self.send(msg)
316
+ return None
317
+
318
+ if not msg.serial:
319
+ msg.serial = self.next_serial()
320
+
321
+ main = GLib.MainLoop()
322
+ handler_reply = None
323
+ connection_error = None
324
+
325
+ def reply_handler(reply, err):
326
+ nonlocal handler_reply
327
+ nonlocal connection_error
328
+
329
+ handler_reply = reply
330
+ connection_error = err
331
+
332
+ main.quit()
333
+
334
+ self._method_return_handlers[msg.serial] = reply_handler
335
+ self.send(msg)
336
+ main.run()
337
+
338
+ if connection_error:
339
+ raise connection_error
340
+
341
+ return handler_reply
342
+
343
+ def introspect_sync(self, bus_name: str, path: str) -> intr.Node:
344
+ """Get introspection data for the node at the given path from the given
345
+ bus name.
346
+
347
+ Calls the standard ``org.freedesktop.DBus.Introspectable.Introspect``
348
+ on the bus for the path.
349
+
350
+ :param bus_name: The name to introspect.
351
+ :type bus_name: str
352
+ :param path: The path to introspect.
353
+ :type path: str
354
+
355
+ :returns: The introspection data for the name at the path.
356
+ :rtype: :class:`Node <dbus_fast.introspection.Node>`
357
+
358
+ :raises:
359
+ - :class:`InvalidObjectPathError <dbus_fast.InvalidObjectPathError>` \
360
+ - If the given object path is not valid.
361
+ - :class:`InvalidBusNameError <dbus_fast.InvalidBusNameError>` - If \
362
+ the given bus name is not valid.
363
+ - :class:`DBusError <dbus_fast.DBusError>` - If the service threw \
364
+ an error for the method call or returned an invalid result.
365
+ - :class:`Exception` - If a connection error occurred.
366
+ """
367
+ main = GLib.MainLoop()
368
+ request_result = None
369
+ request_error = None
370
+
371
+ def reply_notify(result, err):
372
+ nonlocal request_result
373
+ nonlocal request_error
374
+
375
+ request_result = result
376
+ request_error = err
377
+
378
+ main.quit()
379
+
380
+ super().introspect(bus_name, path, reply_notify)
381
+ main.run()
382
+
383
+ if request_error:
384
+ raise request_error
385
+
386
+ return request_result
387
+
388
+ def request_name_sync(
389
+ self, name: str, flags: NameFlag = NameFlag.NONE
390
+ ) -> RequestNameReply:
391
+ """Request that this message bus owns the given name.
392
+
393
+ :param name: The name to request.
394
+ :type name: str
395
+ :param flags: Name flags that affect the behavior of the name request.
396
+ :type flags: :class:`NameFlag <dbus_fast.NameFlag>`
397
+
398
+ :returns: The reply to the name request.
399
+ :rtype: :class:`RequestNameReply <dbus_fast.RequestNameReply>`
400
+
401
+ :raises:
402
+ - :class:`InvalidBusNameError <dbus_fast.InvalidBusNameError>` - If \
403
+ the given bus name is not valid.
404
+ - :class:`DBusError <dbus_fast.DBusError>` - If the service threw \
405
+ an error for the method call or returned an invalid result.
406
+ - :class:`Exception` - If a connection error occurred.
407
+ """
408
+ main = GLib.MainLoop()
409
+ request_result = None
410
+ request_error = None
411
+
412
+ def reply_notify(result, err):
413
+ nonlocal request_result
414
+ nonlocal request_error
415
+
416
+ request_result = result
417
+ request_error = err
418
+
419
+ main.quit()
420
+
421
+ super().request_name(name, flags, reply_notify)
422
+ main.run()
423
+
424
+ if request_error:
425
+ raise request_error
426
+
427
+ return request_result
428
+
429
+ def release_name_sync(self, name: str) -> ReleaseNameReply:
430
+ """Request that this message bus release the given name.
431
+
432
+ :param name: The name to release.
433
+ :type name: str
434
+
435
+ :returns: The reply to the release request.
436
+ :rtype: :class:`ReleaseNameReply <dbus_fast.ReleaseNameReply>`
437
+
438
+ :raises:
439
+ - :class:`InvalidBusNameError <dbus_fast.InvalidBusNameError>` - If \
440
+ the given bus name is not valid.
441
+ - :class:`DBusError <dbus_fast.DBusError>` - If the service threw \
442
+ an error for the method call or returned an invalid result.
443
+ - :class:`Exception` - If a connection error occurred.
444
+ """
445
+ main = GLib.MainLoop()
446
+ release_result = None
447
+ release_error = None
448
+
449
+ def reply_notify(result, err):
450
+ nonlocal release_result
451
+ nonlocal release_error
452
+
453
+ release_result = result
454
+ release_error = err
455
+
456
+ main.quit()
457
+
458
+ super().release_name(name, reply_notify)
459
+ main.run()
460
+
461
+ if release_error:
462
+ raise release_error
463
+
464
+ return release_result
465
+
466
+ def send(self, msg: Message):
467
+ if not msg.serial:
468
+ msg.serial = self.next_serial()
469
+
470
+ self._buffered_messages.append(msg)
471
+
472
+ if self.unique_name:
473
+ self._schedule_write()
474
+
475
+ def get_proxy_object(
476
+ self, bus_name: str, path: str, introspection: intr.Node
477
+ ) -> ProxyObject:
478
+ return super().get_proxy_object(bus_name, path, introspection)
479
+
480
+ def _schedule_write(self):
481
+ if self.writable_source is None or self.writable_source.is_destroyed():
482
+ self.writable_source = _MessageWritableSource(self)
483
+ self.writable_source.attach(self._main_context)
484
+ self.writable_source.add_unix_fd(self._fd, GLib.IO_OUT)
485
+
486
+ def _authenticate(self, authenticate_notify):
487
+ self._stream.write(b"\0")
488
+ first_line = self._auth._authentication_start()
489
+ if first_line is not None:
490
+ if type(first_line) is not str:
491
+ raise AuthError("authenticator gave response not type str")
492
+ self._stream.write(f"{first_line}\r\n".encode())
493
+ self._stream.flush()
494
+
495
+ def line_notify(line):
496
+ try:
497
+ resp = self._auth._receive_line(line)
498
+ self._stream.write(Authenticator._format_line(resp))
499
+ self._stream.flush()
500
+ if resp == "BEGIN":
501
+ self._readline_source = None
502
+ authenticate_notify(None)
503
+ return True
504
+ except Exception as e:
505
+ authenticate_notify(e)
506
+ return True
507
+
508
+ readline_source = _AuthLineSource(self._stream)
509
+ readline_source.set_callback(line_notify)
510
+ readline_source.add_unix_fd(self._fd, GLib.IO_IN)
511
+ readline_source.attach(self._main_context)
512
+ # make sure it doesnt get cleaned up
513
+ self._readline_source = readline_source