dbus-fast 3.0.0__cp314-cp314-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-314-aarch64-linux-musl.so +0 -0
  6. dbus_fast/_private/address.pxd +15 -0
  7. dbus_fast/_private/address.py +119 -0
  8. dbus_fast/_private/constants.py +20 -0
  9. dbus_fast/_private/marshaller.cpython-314-aarch64-linux-musl.so +0 -0
  10. dbus_fast/_private/marshaller.pxd +110 -0
  11. dbus_fast/_private/marshaller.py +231 -0
  12. dbus_fast/_private/unmarshaller.cpython-314-aarch64-linux-musl.so +0 -0
  13. dbus_fast/_private/unmarshaller.pxd +261 -0
  14. dbus_fast/_private/unmarshaller.py +904 -0
  15. dbus_fast/_private/util.py +177 -0
  16. dbus_fast/aio/__init__.py +5 -0
  17. dbus_fast/aio/message_bus.py +569 -0
  18. dbus_fast/aio/message_reader.cpython-314-aarch64-linux-musl.so +0 -0
  19. dbus_fast/aio/message_reader.pxd +13 -0
  20. dbus_fast/aio/message_reader.py +51 -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-314-aarch64-linux-musl.so +0 -0
  30. dbus_fast/message.pxd +76 -0
  31. dbus_fast/message.py +389 -0
  32. dbus_fast/message_bus.cpython-314-aarch64-linux-musl.so +0 -0
  33. dbus_fast/message_bus.pxd +75 -0
  34. dbus_fast/message_bus.py +1332 -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-314-aarch64-linux-musl.so +0 -0
  39. dbus_fast/service.pxd +50 -0
  40. dbus_fast/service.py +701 -0
  41. dbus_fast/signature.cpython-314-aarch64-linux-musl.so +0 -0
  42. dbus_fast/signature.pxd +31 -0
  43. dbus_fast/signature.py +484 -0
  44. dbus_fast/unpack.cpython-314-aarch64-linux-musl.so +0 -0
  45. dbus_fast/unpack.pxd +13 -0
  46. dbus_fast/unpack.py +28 -0
  47. dbus_fast/validators.py +199 -0
  48. dbus_fast-3.0.0.dist-info/METADATA +262 -0
  49. dbus_fast-3.0.0.dist-info/RECORD +51 -0
  50. dbus_fast-3.0.0.dist-info/WHEEL +4 -0
  51. dbus_fast-3.0.0.dist-info/licenses/LICENSE +22 -0
dbus_fast/__init__.py ADDED
@@ -0,0 +1,82 @@
1
+ from . import introspection, message_bus, proxy_object, service
2
+ from .constants import (
3
+ ArgDirection,
4
+ BusType,
5
+ ErrorType,
6
+ MessageFlag,
7
+ MessageType,
8
+ NameFlag,
9
+ PropertyAccess,
10
+ ReleaseNameReply,
11
+ RequestNameReply,
12
+ )
13
+ from .errors import (
14
+ AuthError,
15
+ DBusError,
16
+ InterfaceNotFoundError,
17
+ InvalidAddressError,
18
+ InvalidBusNameError,
19
+ InvalidInterfaceNameError,
20
+ InvalidIntrospectionError,
21
+ InvalidMemberNameError,
22
+ InvalidMessageError,
23
+ InvalidObjectPathError,
24
+ InvalidSignatureError,
25
+ SignalDisabledError,
26
+ SignatureBodyMismatchError,
27
+ )
28
+ from .message import Message
29
+ from .signature import SignatureTree, SignatureType, Variant
30
+ from .unpack import unpack_variants
31
+ from .validators import (
32
+ assert_bus_name_valid,
33
+ assert_interface_name_valid,
34
+ assert_member_name_valid,
35
+ assert_object_path_valid,
36
+ is_bus_name_valid,
37
+ is_interface_name_valid,
38
+ is_member_name_valid,
39
+ is_object_path_valid,
40
+ )
41
+
42
+ __all__ = [
43
+ "ArgDirection",
44
+ "AuthError",
45
+ "BusType",
46
+ "DBusError",
47
+ "ErrorType",
48
+ "InterfaceNotFoundError",
49
+ "InvalidAddressError",
50
+ "InvalidBusNameError",
51
+ "InvalidInterfaceNameError",
52
+ "InvalidIntrospectionError",
53
+ "InvalidMemberNameError",
54
+ "InvalidMessageError",
55
+ "InvalidObjectPathError",
56
+ "InvalidSignatureError",
57
+ "Message",
58
+ "MessageFlag",
59
+ "MessageType",
60
+ "NameFlag",
61
+ "PropertyAccess",
62
+ "ReleaseNameReply",
63
+ "RequestNameReply",
64
+ "SignalDisabledError",
65
+ "SignatureBodyMismatchError",
66
+ "SignatureTree",
67
+ "SignatureType",
68
+ "Variant",
69
+ "assert_bus_name_valid",
70
+ "assert_interface_name_valid",
71
+ "assert_member_name_valid",
72
+ "assert_object_path_valid",
73
+ "introspection",
74
+ "is_bus_name_valid",
75
+ "is_interface_name_valid",
76
+ "is_member_name_valid",
77
+ "is_object_path_valid",
78
+ "message_bus",
79
+ "proxy_object",
80
+ "service",
81
+ "unpack_variants",
82
+ ]
@@ -0,0 +1,10 @@
1
+ __title__ = "dbus_fast"
2
+ __description__ = (
3
+ "A performant zero-dependency DBus library for Python with asyncio support"
4
+ )
5
+ __url__ = "https://github.com/bluetooth-devices/dbus-fast"
6
+ __version__ = "3.0.0"
7
+ __author__ = "Bluetooth Devices authors, Tony Crisci"
8
+ __author_email__ = "bluetooth@koston.org"
9
+ __license__ = "MIT"
10
+ __copyright__ = "Copyright 2022 Bluetooth Devices authors, 2019 Tony Crisci"
@@ -0,0 +1 @@
1
+ from __future__ import annotations
@@ -0,0 +1,14 @@
1
+ """Stub for when Cython is not available."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ class FakeCython:
7
+ """Stub for when Cython is not available."""
8
+
9
+ @property
10
+ def compiled(self) -> bool:
11
+ return False
12
+
13
+
14
+ FAKE_CYTHON = FakeCython()
@@ -0,0 +1,15 @@
1
+ """cdefs for address.py"""
2
+
3
+ import cython
4
+
5
+
6
+ cdef object unquote
7
+
8
+ @cython.locals(kv=cython.str, opt_string=cython.str, address=cython.str)
9
+ cpdef parse_address(cython.str address_str)
10
+
11
+ cpdef get_bus_address(object bus_type)
12
+
13
+ cpdef get_session_bus_address()
14
+
15
+ cpdef get_system_bus_address()
@@ -0,0 +1,119 @@
1
+ # cython: freethreading_compatible = True
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+ from urllib.parse import unquote
8
+
9
+ from ..constants import BusType
10
+ from ..errors import InvalidAddressError
11
+
12
+ invalid_address_chars_re = re.compile(r"[^-0-9A-Za-z_/.%]")
13
+
14
+ str_ = str
15
+
16
+
17
+ def parse_address(address_str: str_) -> list[tuple[str, dict[str, str]]]:
18
+ """Parse a dbus address string into a list of addresses."""
19
+ addresses: list[tuple[str, dict[str, str]]] = []
20
+
21
+ for address in address_str.split(";"):
22
+ if not address:
23
+ continue
24
+ if address.find(":") == -1:
25
+ raise InvalidAddressError("address did not contain a transport")
26
+
27
+ transport, opt_string = address.split(":", 1)
28
+ options: dict[str, str] = {}
29
+
30
+ for kv in opt_string.split(","):
31
+ if not kv:
32
+ continue
33
+ if kv.find("=") == -1:
34
+ raise InvalidAddressError("address option did not contain a value")
35
+ k, v = kv.split("=", 1)
36
+ if invalid_address_chars_re.search(v):
37
+ raise InvalidAddressError("address contains invalid characters")
38
+ # XXX the actual unquote rules are simpler than this
39
+ options[k] = unquote(v)
40
+
41
+ addresses.append((transport, options))
42
+
43
+ if not addresses:
44
+ raise InvalidAddressError(
45
+ f'address string contained no addresses: "{address_str}"'
46
+ )
47
+
48
+ return addresses
49
+
50
+
51
+ def get_system_bus_address() -> str:
52
+ """Get the system bus address from the environment or return the default."""
53
+ return (
54
+ os.environ.get("DBUS_SYSTEM_BUS_ADDRESS")
55
+ or "unix:path=/var/run/dbus/system_bus_socket"
56
+ )
57
+
58
+
59
+ display_re = re.compile(r".*:([0-9]+)\.?.*")
60
+ remove_quotes_re = re.compile(r"""^['"]?(.*?)['"]?$""")
61
+
62
+
63
+ def get_session_bus_address() -> str:
64
+ """Get the session bus address from the environment or return the default."""
65
+ dbus_session_bus_address = os.environ.get("DBUS_SESSION_BUS_ADDRESS")
66
+ if dbus_session_bus_address:
67
+ return dbus_session_bus_address
68
+
69
+ home = os.environ["HOME"]
70
+ if "DISPLAY" not in os.environ:
71
+ raise InvalidAddressError(
72
+ "DBUS_SESSION_BUS_ADDRESS not set and could not get DISPLAY environment variable to get bus address"
73
+ )
74
+
75
+ display = os.environ["DISPLAY"]
76
+ try:
77
+ display = display_re.search(display).group(1)
78
+ except Exception as ex:
79
+ raise InvalidAddressError(
80
+ f"DBUS_SESSION_BUS_ADDRESS not set and could not parse DISPLAY environment variable to get bus address: {display}"
81
+ ) from ex
82
+
83
+ # XXX: this will block but they're very small files and fs operations
84
+ # should be fairly reliable. fix this by passing in an async func to read
85
+ # the file for each io backend.
86
+ machine_id = None
87
+ with open("/var/lib/dbus/machine-id") as f:
88
+ machine_id = f.read().rstrip()
89
+
90
+ dbus_info_file_name = f"{home}/.dbus/session-bus/{machine_id}-{display}"
91
+ dbus_info: str | None = None
92
+ try:
93
+ with open(dbus_info_file_name) as f:
94
+ dbus_info = f.read().rstrip()
95
+ except Exception as ex:
96
+ raise InvalidAddressError(
97
+ f"could not open dbus info file: {dbus_info_file_name}"
98
+ ) from ex
99
+
100
+ for line in dbus_info.split("\n"):
101
+ if line.strip().startswith("DBUS_SESSION_BUS_ADDRESS="):
102
+ _, addr = line.split("=", 1)
103
+ if not addr:
104
+ raise InvalidAddressError(
105
+ f"DBUS_SESSION_BUS_ADDRESS variable not set correctly in dbus info file: {dbus_info_file_name}"
106
+ )
107
+ addr = remove_quotes_re.search(addr).group(1)
108
+ return addr
109
+
110
+ raise InvalidAddressError("could not find dbus session bus address")
111
+
112
+
113
+ def get_bus_address(bus_type: BusType) -> str:
114
+ """Get the address of the bus specified by the bus type."""
115
+ if bus_type == BusType.SESSION:
116
+ return get_session_bus_address()
117
+ if bus_type == BusType.SYSTEM:
118
+ return get_system_bus_address()
119
+ raise Exception(f"got unknown bus type: {bus_type}")
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+
3
+ from enum import Enum
4
+
5
+ PROTOCOL_VERSION = 1
6
+
7
+ LITTLE_ENDIAN = ord("l")
8
+ BIG_ENDIAN = ord("B")
9
+
10
+
11
+ class HeaderField(Enum):
12
+ PATH = 1
13
+ INTERFACE = 2
14
+ MEMBER = 3
15
+ ERROR_NAME = 4
16
+ REPLY_SERIAL = 5
17
+ DESTINATION = 6
18
+ SENDER = 7
19
+ SIGNATURE = 8
20
+ UNIX_FDS = 9
@@ -0,0 +1,110 @@
1
+ """cdefs for marshaller.py"""
2
+
3
+ import cython
4
+
5
+ from ..signature cimport SignatureTree, SignatureType, Variant
6
+
7
+
8
+ cdef object PACK_UINT32
9
+
10
+ cdef bytes PACKED_UINT32_ZERO
11
+ cdef bytes PACKED_BOOL_TRUE
12
+ cdef bytes PACKED_BOOL_FALSE
13
+
14
+ cdef get_signature_tree
15
+
16
+ cdef class Marshaller:
17
+
18
+ cdef SignatureTree signature_tree
19
+ cdef bytearray _buf
20
+ cdef cython.list body
21
+
22
+ cdef _buffer(self)
23
+
24
+ cpdef align(self, unsigned int n)
25
+
26
+ @cython.locals(
27
+ offset=cython.ulong,
28
+ )
29
+ cdef unsigned int _align(self, unsigned int n)
30
+
31
+ cpdef write_boolean(self, bint boolean, SignatureType type_)
32
+
33
+ @cython.locals(
34
+ written=cython.uint,
35
+ )
36
+ cdef unsigned int _write_boolean(self, bint boolean)
37
+
38
+ cpdef write_string(self, object value, SignatureType type_)
39
+
40
+ @cython.locals(
41
+ buf=cython.bytearray,
42
+ value_len=cython.uint,
43
+ signature_len=cython.uint,
44
+ written=cython.uint,
45
+ )
46
+ cdef unsigned int _write_string(self, object value)
47
+
48
+ @cython.locals(
49
+ signature_len=cython.uint,
50
+ )
51
+ cdef unsigned int _write_signature(self, bytes signature_bytes)
52
+
53
+ cpdef write_array(self, object array, SignatureType type_)
54
+
55
+ @cython.locals(
56
+ array_len=cython.uint,
57
+ buf=cython.bytearray,
58
+ written=cython.uint,
59
+ token=cython.str,
60
+ child_type=SignatureType,
61
+ array_len_packed=cython.bytes,
62
+ size=cython.uint,
63
+ writer=cython.object,
64
+ packer=cython.object,
65
+ i=cython.uint,
66
+ )
67
+ cdef unsigned int _write_array(self, object array, SignatureType type_)
68
+
69
+ cpdef write_struct(self, object array, SignatureType type_)
70
+
71
+ @cython.locals(
72
+ written=cython.uint,
73
+ i=cython.uint,
74
+ )
75
+ cdef unsigned int _write_struct(self, object array, SignatureType type_)
76
+
77
+ cpdef write_variant(self, Variant variant, SignatureType type_)
78
+
79
+ @cython.locals(
80
+ written=cython.uint,
81
+ signature=cython.str,
82
+ signature_bytes=cython.bytes,
83
+ )
84
+ cdef unsigned int _write_variant(self, Variant variant, SignatureType type_)
85
+
86
+ @cython.locals(
87
+ written=cython.uint,
88
+ size=cython.uint,
89
+ )
90
+ cdef unsigned int _write_single(self, SignatureType type_, object body)
91
+
92
+ @cython.locals(
93
+ written=cython.uint,
94
+ t=cython.str,
95
+ )
96
+ cpdef write_dict_entry(self, cython.list dict_entry, SignatureType type_)
97
+
98
+ cpdef marshall(self)
99
+
100
+ cdef _marshall(self)
101
+
102
+ @cython.locals(
103
+ offset=cython.ulong,
104
+ t=cython.str,
105
+ size=cython.uint,
106
+ writer=cython.object,
107
+ packer=cython.object,
108
+ type_=SignatureType,
109
+ )
110
+ cdef _construct_buffer(self)
@@ -0,0 +1,231 @@
1
+ # cython: freethreading_compatible = True
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from struct import Struct, error
7
+ from typing import Any
8
+
9
+ from ..signature import SignatureType, Variant, get_signature_tree
10
+
11
+ PACK_LITTLE_ENDIAN = "<"
12
+
13
+ PACK_UINT32 = Struct(f"{PACK_LITTLE_ENDIAN}I").pack
14
+ PACKED_UINT32_ZERO = PACK_UINT32(0)
15
+ PACKED_BOOL_FALSE = PACK_UINT32(0)
16
+ PACKED_BOOL_TRUE = PACK_UINT32(1)
17
+
18
+ _int = int
19
+ _bytes = bytes
20
+ _str = str
21
+
22
+
23
+ class Marshaller:
24
+ """Marshall data for Dbus."""
25
+
26
+ __slots__ = ("_buf", "body", "signature_tree")
27
+
28
+ def __init__(self, signature: str, body: list[Any]) -> None:
29
+ """Marshaller constructor."""
30
+ self.signature_tree = get_signature_tree(signature)
31
+ self._buf = bytearray()
32
+ self.body = body
33
+
34
+ @property
35
+ def buffer(self) -> bytearray:
36
+ return self._buf
37
+
38
+ def _buffer(self) -> bytearray:
39
+ return self._buf
40
+
41
+ def align(self, n: _int) -> int:
42
+ return self._align(n)
43
+
44
+ def _align(self, n: _int) -> _int:
45
+ offset = n - len(self._buf) % n
46
+ if offset == 0 or offset == n:
47
+ return 0
48
+ for _ in range(offset):
49
+ self._buf.append(0)
50
+ return offset
51
+
52
+ def write_boolean(self, boolean: bool, type_: SignatureType) -> int:
53
+ return self._write_boolean(boolean)
54
+
55
+ def _write_boolean(self, boolean: bool) -> int:
56
+ written = self._align(4)
57
+ self._buf += PACKED_BOOL_TRUE if boolean else PACKED_BOOL_FALSE
58
+ return written + 4
59
+
60
+ def write_signature(self, signature: str, type_: SignatureType) -> int:
61
+ return self._write_signature(signature.encode())
62
+
63
+ def _write_signature(self, signature_bytes: _bytes) -> int:
64
+ signature_len = len(signature_bytes)
65
+ buf = self._buf
66
+ buf.append(signature_len)
67
+ buf += signature_bytes
68
+ buf.append(0)
69
+ return signature_len + 2
70
+
71
+ def write_string(self, value: _str, type_: SignatureType) -> int:
72
+ return self._write_string(value)
73
+
74
+ def _write_string(self, value: _str) -> int:
75
+ value_bytes = value.encode()
76
+ value_len = len(value_bytes)
77
+ written = self._align(4) + 4
78
+ buf = self._buf
79
+ buf += PACK_UINT32(value_len)
80
+ buf += value_bytes
81
+ written += value_len
82
+ buf.append(0)
83
+ written += 1
84
+ return written
85
+
86
+ def write_variant(self, variant: Variant, type_: SignatureType) -> int:
87
+ return self._write_variant(variant, type_)
88
+
89
+ def _write_variant(self, variant: Variant, type_: SignatureType) -> int:
90
+ signature = variant.signature
91
+ signature_bytes = signature.encode()
92
+ written = self._write_signature(signature_bytes)
93
+ written += self._write_single(variant.type, variant.value)
94
+ return written
95
+
96
+ def write_array(
97
+ self, array: bytes | list[Any] | dict[Any, Any], type_: SignatureType
98
+ ) -> int:
99
+ return self._write_array(array, type_)
100
+
101
+ def _write_array(
102
+ self, array: bytes | list[Any] | dict[Any, Any], type_: SignatureType
103
+ ) -> int:
104
+ # TODO max array size is 64MiB (67108864 bytes)
105
+ written = self._align(4)
106
+ # length placeholder
107
+ buf: bytearray = self._buf
108
+ offset = len(buf)
109
+ written += self._align(4) + 4
110
+ buf += PACKED_UINT32_ZERO
111
+ child_type = type_.children[0]
112
+ token = child_type.token
113
+
114
+ if token in "xtd{(":
115
+ # the first alignment is not included in array size
116
+ written += self._align(8)
117
+
118
+ array_len = 0
119
+ if token == "{":
120
+ for key, value in array.items(): # type: ignore[union-attr]
121
+ array_len += self.write_dict_entry([key, value], child_type)
122
+ elif token == "y":
123
+ array_len = len(array)
124
+ buf += array # type: ignore[arg-type]
125
+ elif token == "(":
126
+ for value in array:
127
+ array_len += self._write_struct(value, child_type)
128
+ else:
129
+ writer, packer, size = self._writers[token]
130
+ if not writer:
131
+ for value in array:
132
+ array_len += self._align(size) + size
133
+ buf += packer(value) # type: ignore[misc]
134
+ else:
135
+ for value in array:
136
+ array_len += writer(self, value, child_type)
137
+
138
+ array_len_packed = PACK_UINT32(array_len)
139
+ for i in range(offset, offset + 4):
140
+ buf[i] = array_len_packed[i - offset]
141
+
142
+ return written + array_len
143
+
144
+ def write_struct(self, array: tuple[Any] | list[Any], type_: SignatureType) -> int:
145
+ return self._write_struct(array, type_)
146
+
147
+ def _write_struct(self, array: tuple[Any] | list[Any], type_: SignatureType) -> int:
148
+ written = self._align(8)
149
+ for i, value in enumerate(array):
150
+ written += self._write_single(type_.children[i], value)
151
+ return written
152
+
153
+ def write_dict_entry(self, dict_entry: list[Any], type_: SignatureType) -> int:
154
+ written = self._align(8)
155
+ written += self._write_single(type_.children[0], dict_entry[0])
156
+ written += self._write_single(type_.children[1], dict_entry[1])
157
+ return written
158
+
159
+ def _write_single(self, type_: SignatureType, body: Any) -> int:
160
+ t = type_.token
161
+ if t == "y":
162
+ self._buf.append(body)
163
+ return 1
164
+ if t == "u":
165
+ written = self._align(4)
166
+ self._buf += PACK_UINT32(body)
167
+ return written + 4
168
+ if t == "a":
169
+ return self._write_array(body, type_)
170
+ if t == "s" or t == "o":
171
+ return self._write_string(body)
172
+ if t == "v":
173
+ return self._write_variant(body, type_)
174
+ if t == "b":
175
+ return self._write_boolean(body)
176
+ writer, packer, size = self._writers[t]
177
+ if not writer:
178
+ written = self._align(size)
179
+ self._buf += packer(body) # type: ignore[misc]
180
+ return written + size
181
+ return writer(self, body, type_)
182
+
183
+ def marshall(self) -> bytearray:
184
+ """Marshalls the body into a byte array"""
185
+ return self._marshall()
186
+
187
+ def _marshall(self) -> bytearray:
188
+ """Marshalls the body into a byte array"""
189
+ try:
190
+ return self._construct_buffer()
191
+ except KeyError as ex:
192
+ raise NotImplementedError(
193
+ f'type is not implemented yet: "{ex.args}"'
194
+ ) from ex
195
+ except error:
196
+ self.signature_tree.verify(self.body)
197
+ raise RuntimeError("should not reach here")
198
+
199
+ def _construct_buffer(self) -> bytearray:
200
+ self._buf.clear()
201
+ body = self.body
202
+ for i, type_ in enumerate(self.signature_tree.types):
203
+ self._write_single(type_, body[i])
204
+ return self._buf
205
+
206
+ _writers: dict[
207
+ str,
208
+ tuple[
209
+ Callable[[Any, Any, SignatureType], int] | None,
210
+ Callable[[Any], bytes] | None,
211
+ int,
212
+ ],
213
+ ] = {
214
+ "y": (None, Struct(f"{PACK_LITTLE_ENDIAN}B").pack, 1),
215
+ "b": (write_boolean, None, 0),
216
+ "n": (None, Struct(f"{PACK_LITTLE_ENDIAN}h").pack, 2),
217
+ "q": (None, Struct(f"{PACK_LITTLE_ENDIAN}H").pack, 2),
218
+ "i": (None, Struct(f"{PACK_LITTLE_ENDIAN}i").pack, 4),
219
+ "u": (None, PACK_UINT32, 4),
220
+ "x": (None, Struct(f"{PACK_LITTLE_ENDIAN}q").pack, 8),
221
+ "t": (None, Struct(f"{PACK_LITTLE_ENDIAN}Q").pack, 8),
222
+ "d": (None, Struct(f"{PACK_LITTLE_ENDIAN}d").pack, 8),
223
+ "h": (None, Struct(f"{PACK_LITTLE_ENDIAN}I").pack, 4),
224
+ "o": (write_string, None, 0),
225
+ "s": (write_string, None, 0),
226
+ "g": (write_signature, None, 0),
227
+ "a": (write_array, None, 0),
228
+ "(": (write_struct, None, 0),
229
+ "{": (write_dict_entry, None, 0),
230
+ "v": (write_variant, None, 0),
231
+ }