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.

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-313-x86_64-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-313-x86_64-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-313-x86_64-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-313-x86_64-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-313-x86_64-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-313-x86_64-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-313-x86_64-linux-gnu.so +0 -0
  39. dbus_fast/service.pxd +50 -0
  40. dbus_fast/service.py +682 -0
  41. dbus_fast/signature.cpython-313-x86_64-linux-gnu.so +0 -0
  42. dbus_fast/signature.pxd +31 -0
  43. dbus_fast/signature.py +481 -0
  44. dbus_fast/unpack.cpython-313-x86_64-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.44.6.dist-info/METADATA +263 -0
  49. dbus_fast-2.44.6.dist-info/RECORD +51 -0
  50. dbus_fast-2.44.6.dist-info/WHEEL +4 -0
  51. dbus_fast-2.44.6.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__ = "2.44.6"
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,117 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import re
5
+ from urllib.parse import unquote
6
+
7
+ from ..constants import BusType
8
+ from ..errors import InvalidAddressError
9
+
10
+ invalid_address_chars_re = re.compile(r"[^-0-9A-Za-z_/.%]")
11
+
12
+ str_ = str
13
+
14
+
15
+ def parse_address(address_str: str_) -> list[tuple[str, dict[str, str]]]:
16
+ """Parse a dbus address string into a list of addresses."""
17
+ addresses: list[tuple[str, dict[str, str]]] = []
18
+
19
+ for address in address_str.split(";"):
20
+ if not address:
21
+ continue
22
+ if address.find(":") == -1:
23
+ raise InvalidAddressError("address did not contain a transport")
24
+
25
+ transport, opt_string = address.split(":", 1)
26
+ options: dict[str, str] = {}
27
+
28
+ for kv in opt_string.split(","):
29
+ if not kv:
30
+ continue
31
+ if kv.find("=") == -1:
32
+ raise InvalidAddressError("address option did not contain a value")
33
+ k, v = kv.split("=", 1)
34
+ if invalid_address_chars_re.search(v):
35
+ raise InvalidAddressError("address contains invalid characters")
36
+ # XXX the actual unquote rules are simpler than this
37
+ options[k] = unquote(v)
38
+
39
+ addresses.append((transport, options))
40
+
41
+ if not addresses:
42
+ raise InvalidAddressError(
43
+ f'address string contained no addresses: "{address_str}"'
44
+ )
45
+
46
+ return addresses
47
+
48
+
49
+ def get_system_bus_address() -> str:
50
+ """Get the system bus address from the environment or return the default."""
51
+ return (
52
+ os.environ.get("DBUS_SYSTEM_BUS_ADDRESS")
53
+ or "unix:path=/var/run/dbus/system_bus_socket"
54
+ )
55
+
56
+
57
+ display_re = re.compile(r".*:([0-9]+)\.?.*")
58
+ remove_quotes_re = re.compile(r"""^['"]?(.*?)['"]?$""")
59
+
60
+
61
+ def get_session_bus_address() -> str:
62
+ """Get the session bus address from the environment or return the default."""
63
+ dbus_session_bus_address = os.environ.get("DBUS_SESSION_BUS_ADDRESS")
64
+ if dbus_session_bus_address:
65
+ return dbus_session_bus_address
66
+
67
+ home = os.environ["HOME"]
68
+ if "DISPLAY" not in os.environ:
69
+ raise InvalidAddressError(
70
+ "DBUS_SESSION_BUS_ADDRESS not set and could not get DISPLAY environment variable to get bus address"
71
+ )
72
+
73
+ display = os.environ["DISPLAY"]
74
+ try:
75
+ display = display_re.search(display).group(1)
76
+ except Exception as ex:
77
+ raise InvalidAddressError(
78
+ f"DBUS_SESSION_BUS_ADDRESS not set and could not parse DISPLAY environment variable to get bus address: {display}"
79
+ ) from ex
80
+
81
+ # XXX: this will block but they're very small files and fs operations
82
+ # should be fairly reliable. fix this by passing in an async func to read
83
+ # the file for each io backend.
84
+ machine_id = None
85
+ with open("/var/lib/dbus/machine-id") as f:
86
+ machine_id = f.read().rstrip()
87
+
88
+ dbus_info_file_name = f"{home}/.dbus/session-bus/{machine_id}-{display}"
89
+ dbus_info: str | None = None
90
+ try:
91
+ with open(dbus_info_file_name) as f:
92
+ dbus_info = f.read().rstrip()
93
+ except Exception as ex:
94
+ raise InvalidAddressError(
95
+ f"could not open dbus info file: {dbus_info_file_name}"
96
+ ) from ex
97
+
98
+ for line in dbus_info.split("\n"):
99
+ if line.strip().startswith("DBUS_SESSION_BUS_ADDRESS="):
100
+ _, addr = line.split("=", 1)
101
+ if not addr:
102
+ raise InvalidAddressError(
103
+ f"DBUS_SESSION_BUS_ADDRESS variable not set correctly in dbus info file: {dbus_info_file_name}"
104
+ )
105
+ addr = remove_quotes_re.search(addr).group(1)
106
+ return addr
107
+
108
+ raise InvalidAddressError("could not find dbus session bus address")
109
+
110
+
111
+ def get_bus_address(bus_type: BusType) -> str:
112
+ """Get the address of the bus specified by the bus type."""
113
+ if bus_type == BusType.SESSION:
114
+ return get_session_bus_address()
115
+ if bus_type == BusType.SYSTEM:
116
+ return get_system_bus_address()
117
+ 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, object boolean, SignatureType type_)
32
+
33
+ @cython.locals(
34
+ written=cython.uint,
35
+ )
36
+ cdef unsigned int _write_boolean(self, object 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,228 @@
1
+ from __future__ import annotations
2
+
3
+ from struct import Struct, error
4
+ from typing import Any, Callable
5
+
6
+ from ..signature import SignatureType, Variant, get_signature_tree
7
+
8
+ PACK_LITTLE_ENDIAN = "<"
9
+
10
+ PACK_UINT32 = Struct(f"{PACK_LITTLE_ENDIAN}I").pack
11
+ PACKED_UINT32_ZERO = PACK_UINT32(0)
12
+ PACKED_BOOL_FALSE = PACK_UINT32(0)
13
+ PACKED_BOOL_TRUE = PACK_UINT32(1)
14
+
15
+ _int = int
16
+ _bytes = bytes
17
+ _str = str
18
+
19
+
20
+ class Marshaller:
21
+ """Marshall data for Dbus."""
22
+
23
+ __slots__ = ("_buf", "body", "signature_tree")
24
+
25
+ def __init__(self, signature: str, body: list[Any]) -> None:
26
+ """Marshaller constructor."""
27
+ self.signature_tree = get_signature_tree(signature)
28
+ self._buf = bytearray()
29
+ self.body = body
30
+
31
+ @property
32
+ def buffer(self) -> bytearray:
33
+ return self._buf
34
+
35
+ def _buffer(self) -> bytearray:
36
+ return self._buf
37
+
38
+ def align(self, n: _int) -> int:
39
+ return self._align(n)
40
+
41
+ def _align(self, n: _int) -> _int:
42
+ offset = n - len(self._buf) % n
43
+ if offset == 0 or offset == n:
44
+ return 0
45
+ for _ in range(offset):
46
+ self._buf.append(0)
47
+ return offset
48
+
49
+ def write_boolean(self, boolean: bool, type_: SignatureType) -> int:
50
+ return self._write_boolean(boolean)
51
+
52
+ def _write_boolean(self, boolean: bool) -> int:
53
+ written = self._align(4)
54
+ self._buf += PACKED_BOOL_TRUE if boolean else PACKED_BOOL_FALSE
55
+ return written + 4
56
+
57
+ def write_signature(self, signature: str, type_: SignatureType) -> int:
58
+ return self._write_signature(signature.encode())
59
+
60
+ def _write_signature(self, signature_bytes: _bytes) -> int:
61
+ signature_len = len(signature_bytes)
62
+ buf = self._buf
63
+ buf.append(signature_len)
64
+ buf += signature_bytes
65
+ buf.append(0)
66
+ return signature_len + 2
67
+
68
+ def write_string(self, value: _str, type_: SignatureType) -> int:
69
+ return self._write_string(value)
70
+
71
+ def _write_string(self, value: _str) -> int:
72
+ value_bytes = value.encode()
73
+ value_len = len(value_bytes)
74
+ written = self._align(4) + 4
75
+ buf = self._buf
76
+ buf += PACK_UINT32(value_len)
77
+ buf += value_bytes
78
+ written += value_len
79
+ buf.append(0)
80
+ written += 1
81
+ return written
82
+
83
+ def write_variant(self, variant: Variant, type_: SignatureType) -> int:
84
+ return self._write_variant(variant, type_)
85
+
86
+ def _write_variant(self, variant: Variant, type_: SignatureType) -> int:
87
+ signature = variant.signature
88
+ signature_bytes = signature.encode()
89
+ written = self._write_signature(signature_bytes)
90
+ written += self._write_single(variant.type, variant.value)
91
+ return written
92
+
93
+ def write_array(
94
+ self, array: bytes | list[Any] | dict[Any, Any], type_: SignatureType
95
+ ) -> int:
96
+ return self._write_array(array, type_)
97
+
98
+ def _write_array(
99
+ self, array: bytes | list[Any] | dict[Any, Any], type_: SignatureType
100
+ ) -> int:
101
+ # TODO max array size is 64MiB (67108864 bytes)
102
+ written = self._align(4)
103
+ # length placeholder
104
+ buf: bytearray = self._buf
105
+ offset = len(buf)
106
+ written += self._align(4) + 4
107
+ buf += PACKED_UINT32_ZERO
108
+ child_type = type_.children[0]
109
+ token = child_type.token
110
+
111
+ if token in "xtd{(":
112
+ # the first alignment is not included in array size
113
+ written += self._align(8)
114
+
115
+ array_len = 0
116
+ if token == "{":
117
+ for key, value in array.items(): # type: ignore[union-attr]
118
+ array_len += self.write_dict_entry([key, value], child_type)
119
+ elif token == "y":
120
+ array_len = len(array)
121
+ buf += array # type: ignore[arg-type]
122
+ elif token == "(":
123
+ for value in array:
124
+ array_len += self._write_struct(value, child_type)
125
+ else:
126
+ writer, packer, size = self._writers[token]
127
+ if not writer:
128
+ for value in array:
129
+ array_len += self._align(size) + size
130
+ buf += packer(value) # type: ignore[misc]
131
+ else:
132
+ for value in array:
133
+ array_len += writer(self, value, child_type)
134
+
135
+ array_len_packed = PACK_UINT32(array_len)
136
+ for i in range(offset, offset + 4):
137
+ buf[i] = array_len_packed[i - offset]
138
+
139
+ return written + array_len
140
+
141
+ def write_struct(self, array: tuple[Any] | list[Any], type_: SignatureType) -> int:
142
+ return self._write_struct(array, type_)
143
+
144
+ def _write_struct(self, array: tuple[Any] | list[Any], type_: SignatureType) -> int:
145
+ written = self._align(8)
146
+ for i, value in enumerate(array):
147
+ written += self._write_single(type_.children[i], value)
148
+ return written
149
+
150
+ def write_dict_entry(self, dict_entry: list[Any], type_: SignatureType) -> int:
151
+ written = self._align(8)
152
+ written += self._write_single(type_.children[0], dict_entry[0])
153
+ written += self._write_single(type_.children[1], dict_entry[1])
154
+ return written
155
+
156
+ def _write_single(self, type_: SignatureType, body: Any) -> int:
157
+ t = type_.token
158
+ if t == "y":
159
+ self._buf.append(body)
160
+ return 1
161
+ if t == "u":
162
+ written = self._align(4)
163
+ self._buf += PACK_UINT32(body)
164
+ return written + 4
165
+ if t == "a":
166
+ return self._write_array(body, type_)
167
+ if t == "s" or t == "o":
168
+ return self._write_string(body)
169
+ if t == "v":
170
+ return self._write_variant(body, type_)
171
+ if t == "b":
172
+ return self._write_boolean(body)
173
+ writer, packer, size = self._writers[t]
174
+ if not writer:
175
+ written = self._align(size)
176
+ self._buf += packer(body) # type: ignore[misc]
177
+ return written + size
178
+ return writer(self, body, type_)
179
+
180
+ def marshall(self) -> bytearray:
181
+ """Marshalls the body into a byte array"""
182
+ return self._marshall()
183
+
184
+ def _marshall(self) -> bytearray:
185
+ """Marshalls the body into a byte array"""
186
+ try:
187
+ return self._construct_buffer()
188
+ except KeyError as ex:
189
+ raise NotImplementedError(
190
+ f'type is not implemented yet: "{ex.args}"'
191
+ ) from ex
192
+ except error:
193
+ self.signature_tree.verify(self.body)
194
+ raise RuntimeError("should not reach here")
195
+
196
+ def _construct_buffer(self) -> bytearray:
197
+ self._buf.clear()
198
+ body = self.body
199
+ for i, type_ in enumerate(self.signature_tree.types):
200
+ self._write_single(type_, body[i])
201
+ return self._buf
202
+
203
+ _writers: dict[
204
+ str,
205
+ tuple[
206
+ Callable[[Any, Any, SignatureType], int] | None,
207
+ Callable[[Any], bytes] | None,
208
+ int,
209
+ ],
210
+ ] = {
211
+ "y": (None, Struct(f"{PACK_LITTLE_ENDIAN}B").pack, 1),
212
+ "b": (write_boolean, None, 0),
213
+ "n": (None, Struct(f"{PACK_LITTLE_ENDIAN}h").pack, 2),
214
+ "q": (None, Struct(f"{PACK_LITTLE_ENDIAN}H").pack, 2),
215
+ "i": (None, Struct(f"{PACK_LITTLE_ENDIAN}i").pack, 4),
216
+ "u": (None, PACK_UINT32, 4),
217
+ "x": (None, Struct(f"{PACK_LITTLE_ENDIAN}q").pack, 8),
218
+ "t": (None, Struct(f"{PACK_LITTLE_ENDIAN}Q").pack, 8),
219
+ "d": (None, Struct(f"{PACK_LITTLE_ENDIAN}d").pack, 8),
220
+ "h": (None, Struct(f"{PACK_LITTLE_ENDIAN}I").pack, 4),
221
+ "o": (write_string, None, 0),
222
+ "s": (write_string, None, 0),
223
+ "g": (write_signature, None, 0),
224
+ "a": (write_array, None, 0),
225
+ "(": (write_struct, None, 0),
226
+ "{": (write_dict_entry, None, 0),
227
+ "v": (write_variant, None, 0),
228
+ }