dbus-fast 2.45.0__cp39-cp39-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.
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-39-aarch64-linux-gnu.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-39-aarch64-linux-gnu.so +0 -0
  10. dbus_fast/_private/marshaller.pxd +110 -0
  11. dbus_fast/_private/marshaller.py +228 -0
  12. dbus_fast/_private/unmarshaller.cpython-39-aarch64-linux-gnu.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 +176 -0
  16. dbus_fast/aio/__init__.py +5 -0
  17. dbus_fast/aio/message_bus.py +578 -0
  18. dbus_fast/aio/message_reader.cpython-39-aarch64-linux-gnu.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 +126 -0
  23. dbus_fast/constants.py +152 -0
  24. dbus_fast/errors.py +84 -0
  25. dbus_fast/glib/__init__.py +3 -0
  26. dbus_fast/glib/message_bus.py +515 -0
  27. dbus_fast/glib/proxy_object.py +319 -0
  28. dbus_fast/introspection.py +683 -0
  29. dbus_fast/message.cpython-39-aarch64-linux-gnu.so +0 -0
  30. dbus_fast/message.pxd +76 -0
  31. dbus_fast/message.py +387 -0
  32. dbus_fast/message_bus.cpython-39-aarch64-linux-gnu.so +0 -0
  33. dbus_fast/message_bus.pxd +75 -0
  34. dbus_fast/message_bus.py +1310 -0
  35. dbus_fast/proxy_object.py +358 -0
  36. dbus_fast/py.typed +0 -0
  37. dbus_fast/send_reply.py +61 -0
  38. dbus_fast/service.cpython-39-aarch64-linux-gnu.so +0 -0
  39. dbus_fast/service.pxd +50 -0
  40. dbus_fast/service.py +682 -0
  41. dbus_fast/signature.cpython-39-aarch64-linux-gnu.so +0 -0
  42. dbus_fast/signature.pxd +31 -0
  43. dbus_fast/signature.py +481 -0
  44. dbus_fast/unpack.cpython-39-aarch64-linux-gnu.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.45.0.dist-info/METADATA +263 -0
  49. dbus_fast-2.45.0.dist-info/RECORD +51 -0
  50. dbus_fast-2.45.0.dist-info/WHEEL +4 -0
  51. dbus_fast-2.45.0.dist-info/licenses/LICENSE +22 -0
@@ -0,0 +1,515 @@
1
+ import io
2
+ import logging
3
+ import traceback
4
+ from typing import Callable, Optional
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: Optional[str] = None,
165
+ bus_type: BusType = BusType.SESSION,
166
+ auth: Optional[Authenticator] = 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: Optional[
192
+ Callable[["MessageBus", Optional[Exception]], None]
193
+ ] = None,
194
+ ):
195
+ """Connect this message bus to the DBus daemon.
196
+
197
+ This method or the synchronous version must be called before the
198
+ message bus can be used.
199
+
200
+ :param connect_notify: A callback that will be called with this message
201
+ bus. May return an :class:`Exception` on connection errors or
202
+ :class:`AuthError <dbus_fast.AuthError>` on authorization errors.
203
+ :type callback: :class:`Callable`
204
+ """
205
+
206
+ def authenticate_notify(exc):
207
+ if exc is not None:
208
+ if connect_notify is not None:
209
+ connect_notify(None, exc)
210
+ return
211
+ self.message_source = _MessageSource(self)
212
+ self.message_source.set_callback(self._on_message)
213
+ self.message_source.attach(self._main_context)
214
+
215
+ self.writable_source = None
216
+
217
+ self.message_source.add_unix_fd(self._fd, GLib.IO_IN)
218
+
219
+ def on_hello(reply, err):
220
+ if err:
221
+ if connect_notify:
222
+ connect_notify(reply, err)
223
+ return
224
+
225
+ self.unique_name = reply.body[0]
226
+
227
+ for m in self._buffered_messages:
228
+ self.send(m)
229
+
230
+ if connect_notify:
231
+ connect_notify(self, err)
232
+
233
+ hello_msg = Message(
234
+ destination="org.freedesktop.DBus",
235
+ path="/org/freedesktop/DBus",
236
+ interface="org.freedesktop.DBus",
237
+ member="Hello",
238
+ serial=self.next_serial(),
239
+ )
240
+
241
+ self._method_return_handlers[hello_msg.serial] = on_hello
242
+ self._stream.write(hello_msg._marshall(False))
243
+ self._stream.flush()
244
+
245
+ self._authenticate(authenticate_notify)
246
+
247
+ def connect_sync(self) -> "MessageBus":
248
+ """Connect this message bus to the DBus daemon.
249
+
250
+ This method or the asynchronous version must be called before the
251
+ message bus can be used.
252
+
253
+ :returns: This message bus for convenience.
254
+ :rtype: :class:`MessageBus <dbus_fast.glib.MessageBus>`
255
+
256
+ :raises:
257
+ - :class:`AuthError <dbus_fast.AuthError>` - If authorization to \
258
+ the DBus daemon failed.
259
+ - :class:`Exception` - If there was a connection error.
260
+ """
261
+ main = GLib.MainLoop()
262
+ connection_error = None
263
+
264
+ def connect_notify(bus, err):
265
+ nonlocal connection_error
266
+ connection_error = err
267
+ main.quit()
268
+
269
+ self.connect(connect_notify)
270
+ main.run()
271
+
272
+ if connection_error:
273
+ raise connection_error
274
+
275
+ return self
276
+
277
+ def call(
278
+ self,
279
+ msg: Message,
280
+ reply_notify: Optional[
281
+ Callable[[Optional[Message], Optional[Exception]], None]
282
+ ] = None,
283
+ ):
284
+ """Send a method call and asynchronously wait for a reply from the DBus
285
+ daemon.
286
+
287
+ :param msg: The method call message to send.
288
+ :type msg: :class:`Message <dbus_fast.Message>`
289
+ :param reply_notify: A callback that will be called with the reply to
290
+ this message. May return an :class:`Exception` on connection errors.
291
+ :type reply_notify: Callable
292
+ """
293
+ BaseMessageBus._check_callback_type(reply_notify)
294
+ self._call(msg, reply_notify)
295
+
296
+ def call_sync(self, msg: Message) -> Optional[Message]:
297
+ """Send a method call and synchronously wait for a reply from the DBus
298
+ daemon.
299
+
300
+ :param msg: The method call message to send.
301
+ :type msg: :class:`Message <dbus_fast.Message>`
302
+
303
+ :returns: A message in reply to the message sent. If the message does
304
+ not expect a reply based on the message flags or type, returns
305
+ ``None`` immediately.
306
+ :rtype: :class:`Message <dbus_fast.Message>`
307
+
308
+ :raises:
309
+ - :class:`DBusError <dbus_fast.DBusError>` - If the service threw \
310
+ an error for the method call or returned an invalid result.
311
+ - :class:`Exception` - If a connection error occurred.
312
+ """
313
+ if (
314
+ msg.flags & MessageFlag.NO_REPLY_EXPECTED
315
+ or msg.message_type is not MessageType.METHOD_CALL
316
+ ):
317
+ self.send(msg)
318
+ return None
319
+
320
+ if not msg.serial:
321
+ msg.serial = self.next_serial()
322
+
323
+ main = GLib.MainLoop()
324
+ handler_reply = None
325
+ connection_error = None
326
+
327
+ def reply_handler(reply, err):
328
+ nonlocal handler_reply
329
+ nonlocal connection_error
330
+
331
+ handler_reply = reply
332
+ connection_error = err
333
+
334
+ main.quit()
335
+
336
+ self._method_return_handlers[msg.serial] = reply_handler
337
+ self.send(msg)
338
+ main.run()
339
+
340
+ if connection_error:
341
+ raise connection_error
342
+
343
+ return handler_reply
344
+
345
+ def introspect_sync(self, bus_name: str, path: str) -> intr.Node:
346
+ """Get introspection data for the node at the given path from the given
347
+ bus name.
348
+
349
+ Calls the standard ``org.freedesktop.DBus.Introspectable.Introspect``
350
+ on the bus for the path.
351
+
352
+ :param bus_name: The name to introspect.
353
+ :type bus_name: str
354
+ :param path: The path to introspect.
355
+ :type path: str
356
+
357
+ :returns: The introspection data for the name at the path.
358
+ :rtype: :class:`Node <dbus_fast.introspection.Node>`
359
+
360
+ :raises:
361
+ - :class:`InvalidObjectPathError <dbus_fast.InvalidObjectPathError>` \
362
+ - If the given object path is not valid.
363
+ - :class:`InvalidBusNameError <dbus_fast.InvalidBusNameError>` - If \
364
+ the given bus name is not valid.
365
+ - :class:`DBusError <dbus_fast.DBusError>` - If the service threw \
366
+ an error for the method call or returned an invalid result.
367
+ - :class:`Exception` - If a connection error occurred.
368
+ """
369
+ main = GLib.MainLoop()
370
+ request_result = None
371
+ request_error = None
372
+
373
+ def reply_notify(result, err):
374
+ nonlocal request_result
375
+ nonlocal request_error
376
+
377
+ request_result = result
378
+ request_error = err
379
+
380
+ main.quit()
381
+
382
+ super().introspect(bus_name, path, reply_notify)
383
+ main.run()
384
+
385
+ if request_error:
386
+ raise request_error
387
+
388
+ return request_result
389
+
390
+ def request_name_sync(
391
+ self, name: str, flags: NameFlag = NameFlag.NONE
392
+ ) -> RequestNameReply:
393
+ """Request that this message bus owns the given name.
394
+
395
+ :param name: The name to request.
396
+ :type name: str
397
+ :param flags: Name flags that affect the behavior of the name request.
398
+ :type flags: :class:`NameFlag <dbus_fast.NameFlag>`
399
+
400
+ :returns: The reply to the name request.
401
+ :rtype: :class:`RequestNameReply <dbus_fast.RequestNameReply>`
402
+
403
+ :raises:
404
+ - :class:`InvalidBusNameError <dbus_fast.InvalidBusNameError>` - If \
405
+ the given bus name is not valid.
406
+ - :class:`DBusError <dbus_fast.DBusError>` - If the service threw \
407
+ an error for the method call or returned an invalid result.
408
+ - :class:`Exception` - If a connection error occurred.
409
+ """
410
+ main = GLib.MainLoop()
411
+ request_result = None
412
+ request_error = None
413
+
414
+ def reply_notify(result, err):
415
+ nonlocal request_result
416
+ nonlocal request_error
417
+
418
+ request_result = result
419
+ request_error = err
420
+
421
+ main.quit()
422
+
423
+ super().request_name(name, flags, reply_notify)
424
+ main.run()
425
+
426
+ if request_error:
427
+ raise request_error
428
+
429
+ return request_result
430
+
431
+ def release_name_sync(self, name: str) -> ReleaseNameReply:
432
+ """Request that this message bus release the given name.
433
+
434
+ :param name: The name to release.
435
+ :type name: str
436
+
437
+ :returns: The reply to the release request.
438
+ :rtype: :class:`ReleaseNameReply <dbus_fast.ReleaseNameReply>`
439
+
440
+ :raises:
441
+ - :class:`InvalidBusNameError <dbus_fast.InvalidBusNameError>` - If \
442
+ the given bus name is not valid.
443
+ - :class:`DBusError <dbus_fast.DBusError>` - If the service threw \
444
+ an error for the method call or returned an invalid result.
445
+ - :class:`Exception` - If a connection error occurred.
446
+ """
447
+ main = GLib.MainLoop()
448
+ release_result = None
449
+ release_error = None
450
+
451
+ def reply_notify(result, err):
452
+ nonlocal release_result
453
+ nonlocal release_error
454
+
455
+ release_result = result
456
+ release_error = err
457
+
458
+ main.quit()
459
+
460
+ super().release_name(name, reply_notify)
461
+ main.run()
462
+
463
+ if release_error:
464
+ raise release_error
465
+
466
+ return release_result
467
+
468
+ def send(self, msg: Message):
469
+ if not msg.serial:
470
+ msg.serial = self.next_serial()
471
+
472
+ self._buffered_messages.append(msg)
473
+
474
+ if self.unique_name:
475
+ self._schedule_write()
476
+
477
+ def get_proxy_object(
478
+ self, bus_name: str, path: str, introspection: intr.Node
479
+ ) -> ProxyObject:
480
+ return super().get_proxy_object(bus_name, path, introspection)
481
+
482
+ def _schedule_write(self):
483
+ if self.writable_source is None or self.writable_source.is_destroyed():
484
+ self.writable_source = _MessageWritableSource(self)
485
+ self.writable_source.attach(self._main_context)
486
+ self.writable_source.add_unix_fd(self._fd, GLib.IO_OUT)
487
+
488
+ def _authenticate(self, authenticate_notify):
489
+ self._stream.write(b"\0")
490
+ first_line = self._auth._authentication_start()
491
+ if first_line is not None:
492
+ if type(first_line) is not str:
493
+ raise AuthError("authenticator gave response not type str")
494
+ self._stream.write(f"{first_line}\r\n".encode())
495
+ self._stream.flush()
496
+
497
+ def line_notify(line):
498
+ try:
499
+ resp = self._auth._receive_line(line)
500
+ self._stream.write(Authenticator._format_line(resp))
501
+ self._stream.flush()
502
+ if resp == "BEGIN":
503
+ self._readline_source = None
504
+ authenticate_notify(None)
505
+ return True
506
+ except Exception as e:
507
+ authenticate_notify(e)
508
+ return True
509
+
510
+ readline_source = _AuthLineSource(self._stream)
511
+ readline_source.set_callback(line_notify)
512
+ readline_source.add_unix_fd(self._fd, GLib.IO_IN)
513
+ readline_source.attach(self._main_context)
514
+ # make sure it doesnt get cleaned up
515
+ self._readline_source = readline_source