zlmdb 25.10.1__cp313-cp313-manylinux_2_34_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 zlmdb might be problematic. Click here for more details.

Files changed (87) hide show
  1. flatbuffers/__init__.py +19 -0
  2. flatbuffers/_version.py +17 -0
  3. flatbuffers/builder.py +776 -0
  4. flatbuffers/compat.py +86 -0
  5. flatbuffers/encode.py +42 -0
  6. flatbuffers/flexbuffers.py +1527 -0
  7. flatbuffers/number_types.py +181 -0
  8. flatbuffers/packer.py +42 -0
  9. flatbuffers/reflection/AdvancedFeatures.py +10 -0
  10. flatbuffers/reflection/BaseType.py +24 -0
  11. flatbuffers/reflection/Enum.py +169 -0
  12. flatbuffers/reflection/EnumVal.py +96 -0
  13. flatbuffers/reflection/Field.py +208 -0
  14. flatbuffers/reflection/KeyValue.py +56 -0
  15. flatbuffers/reflection/Object.py +175 -0
  16. flatbuffers/reflection/RPCCall.py +131 -0
  17. flatbuffers/reflection/Schema.py +206 -0
  18. flatbuffers/reflection/SchemaFile.py +77 -0
  19. flatbuffers/reflection/Service.py +145 -0
  20. flatbuffers/reflection/Type.py +98 -0
  21. flatbuffers/reflection/__init__.py +0 -0
  22. flatbuffers/table.py +129 -0
  23. flatbuffers/util.py +43 -0
  24. zlmdb/__init__.py +312 -0
  25. zlmdb/_database.py +990 -0
  26. zlmdb/_errors.py +31 -0
  27. zlmdb/_meta.py +27 -0
  28. zlmdb/_pmap.py +1667 -0
  29. zlmdb/_schema.py +137 -0
  30. zlmdb/_transaction.py +181 -0
  31. zlmdb/_types.py +1596 -0
  32. zlmdb/_version.py +27 -0
  33. zlmdb/cli.py +41 -0
  34. zlmdb/flatbuffers/__init__.py +5 -0
  35. zlmdb/flatbuffers/reflection/AdvancedFeatures.py +10 -0
  36. zlmdb/flatbuffers/reflection/BaseType.py +25 -0
  37. zlmdb/flatbuffers/reflection/Enum.py +252 -0
  38. zlmdb/flatbuffers/reflection/EnumVal.py +144 -0
  39. zlmdb/flatbuffers/reflection/Field.py +325 -0
  40. zlmdb/flatbuffers/reflection/KeyValue.py +84 -0
  41. zlmdb/flatbuffers/reflection/Object.py +260 -0
  42. zlmdb/flatbuffers/reflection/RPCCall.py +195 -0
  43. zlmdb/flatbuffers/reflection/Schema.py +301 -0
  44. zlmdb/flatbuffers/reflection/SchemaFile.py +112 -0
  45. zlmdb/flatbuffers/reflection/Service.py +213 -0
  46. zlmdb/flatbuffers/reflection/Type.py +148 -0
  47. zlmdb/flatbuffers/reflection/__init__.py +0 -0
  48. zlmdb/flatbuffers/reflection.fbs +152 -0
  49. zlmdb/lmdb/__init__.py +37 -0
  50. zlmdb/lmdb/__main__.py +25 -0
  51. zlmdb/lmdb/_config.py +10 -0
  52. zlmdb/lmdb/_lmdb_cffi.cpython-313-x86_64-linux-gnu.so +0 -0
  53. zlmdb/lmdb/cffi.py +2606 -0
  54. zlmdb/lmdb/tool.py +670 -0
  55. zlmdb/tests/lmdb/__init__.py +0 -0
  56. zlmdb/tests/lmdb/address_book.py +287 -0
  57. zlmdb/tests/lmdb/crash_test.py +339 -0
  58. zlmdb/tests/lmdb/cursor_test.py +333 -0
  59. zlmdb/tests/lmdb/env_test.py +919 -0
  60. zlmdb/tests/lmdb/getmulti_test.py +92 -0
  61. zlmdb/tests/lmdb/iteration_test.py +258 -0
  62. zlmdb/tests/lmdb/package_test.py +70 -0
  63. zlmdb/tests/lmdb/test_lmdb.py +188 -0
  64. zlmdb/tests/lmdb/testlib.py +185 -0
  65. zlmdb/tests/lmdb/tool_test.py +60 -0
  66. zlmdb/tests/lmdb/txn_test.py +575 -0
  67. zlmdb/tests/orm/MNodeLog.py +853 -0
  68. zlmdb/tests/orm/__init__.py +0 -0
  69. zlmdb/tests/orm/_schema_fbs.py +215 -0
  70. zlmdb/tests/orm/_schema_mnode_log.py +1201 -0
  71. zlmdb/tests/orm/_schema_py2.py +250 -0
  72. zlmdb/tests/orm/_schema_py3.py +307 -0
  73. zlmdb/tests/orm/_test_flatbuffers.py +144 -0
  74. zlmdb/tests/orm/_test_serialization.py +144 -0
  75. zlmdb/tests/orm/test_basic.py +217 -0
  76. zlmdb/tests/orm/test_etcd.py +275 -0
  77. zlmdb/tests/orm/test_pmap_indexes.py +466 -0
  78. zlmdb/tests/orm/test_pmap_types.py +90 -0
  79. zlmdb/tests/orm/test_pmaps.py +295 -0
  80. zlmdb/tests/orm/test_select.py +619 -0
  81. zlmdb-25.10.1.dist-info/METADATA +264 -0
  82. zlmdb-25.10.1.dist-info/RECORD +87 -0
  83. zlmdb-25.10.1.dist-info/WHEEL +5 -0
  84. zlmdb-25.10.1.dist-info/entry_points.txt +2 -0
  85. zlmdb-25.10.1.dist-info/licenses/LICENSE +137 -0
  86. zlmdb-25.10.1.dist-info/licenses/NOTICE +41 -0
  87. zlmdb-25.10.1.dist-info/top_level.txt +2 -0
zlmdb/_types.py ADDED
@@ -0,0 +1,1596 @@
1
+ ###############################################################################
2
+ #
3
+ # The MIT License (MIT)
4
+ #
5
+ # Copyright (c) typedef int GmbH
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+ #
25
+ ###############################################################################
26
+
27
+ import struct
28
+ import random
29
+ import binascii
30
+ import pickle
31
+ import os
32
+ import uuid
33
+ import json
34
+
35
+ import cbor2
36
+ import flatbuffers
37
+ from txaio import time_ns
38
+
39
+ try:
40
+ import numpy as np
41
+ except ImportError:
42
+ HAS_NUMPY = False
43
+ else:
44
+ HAS_NUMPY = True
45
+
46
+ CHARSET = "345679ACEFGHJKLMNPQRSTUVWXY"
47
+ """
48
+ Charset from which to generate random key IDs.
49
+
50
+ .. note::
51
+
52
+ We take out the following 9 chars (leaving 27), because there is visual ambiguity: 0/O/D, 1/I, 8/B, 2/Z.
53
+ """
54
+
55
+ CHAR_GROUPS = 4
56
+ CHARS_PER_GROUP = 6
57
+ GROUP_SEP = "-"
58
+
59
+
60
+ def _random_string():
61
+ """
62
+ Generate a globally unique serial / product code of the form ``u'YRAC-EL4X-FQQE-AW4T-WNUV-VN6T'``.
63
+ The generated value is cryptographically strong and has (at least) 114 bits of entropy.
64
+
65
+ :return: new random string key
66
+ """
67
+ rng = random.SystemRandom()
68
+ token_value = "".join(
69
+ rng.choice(CHARSET) for _ in range(CHAR_GROUPS * CHARS_PER_GROUP)
70
+ )
71
+ if CHARS_PER_GROUP > 1:
72
+ return GROUP_SEP.join(map("".join, zip(*[iter(token_value)] * CHARS_PER_GROUP)))
73
+ else:
74
+ return token_value
75
+
76
+
77
+ def dt_to_bytes(dt):
78
+ """
79
+ Serialize a timestamp in big-endian byte order.
80
+
81
+ :param dt: Timestamp to serialize.
82
+ :return: Serialized bytes.
83
+ """
84
+ assert isinstance(dt, np.datetime64)
85
+
86
+ data = bytearray(dt.tobytes())
87
+ # FIXME: this must depend on host CPU arch
88
+ data.reverse()
89
+ return bytes(data)
90
+
91
+
92
+ def bytes_to_dt(data):
93
+ """
94
+ Deserialize a timestamp from big-endian byte order data.
95
+
96
+ :param data: Data to deserialize.
97
+ :return: Deserialized timestamp.
98
+ """
99
+ assert type(data) == bytes
100
+
101
+ data = bytearray(data)
102
+ # FIXME: this must depend on host CPU arch
103
+ data.reverse()
104
+ dt = np.frombuffer(bytes(data), dtype="datetime64[ns]")[0]
105
+ return dt
106
+
107
+
108
+ #
109
+ # Key Types
110
+ #
111
+
112
+
113
+ class _OidKeysMixin(object):
114
+ MAX_OID = 9007199254740992
115
+ """
116
+ Valid OID are from the integer range [0, MAX_OID].
117
+
118
+ The upper bound 2**53 is chosen since it is the maximum integer that can be
119
+ represented as a IEEE double such that all smaller integers are representable as well.
120
+
121
+ Hence, IDs can be safely used with languages that use IEEE double as their
122
+ main (or only) number type (JavaScript, Lua, etc).
123
+ """
124
+
125
+ @staticmethod
126
+ def new_key(secure=False):
127
+ if secure:
128
+ while True:
129
+ data = os.urandom(8)
130
+ key = struct.unpack(">Q", data)[0]
131
+ if key <= _OidKeysMixin.MAX_OID:
132
+ return key
133
+ else:
134
+ random.randint(0, _OidKeysMixin.MAX_OID)
135
+
136
+ def _serialize_key(self, key):
137
+ assert type(key) == int
138
+ assert key >= 0 and key <= _OidKeysMixin.MAX_OID
139
+ return struct.pack(">Q", key)
140
+
141
+ def _deserialize_key(self, data):
142
+ return struct.unpack(">Q", data)[0]
143
+
144
+
145
+ class _OidOidKeysMixin(object):
146
+ @staticmethod
147
+ def new_key(secure=False):
148
+ return _OidKeysMixin.new_key(secure=secure), _OidKeysMixin.new_key(
149
+ secure=secure
150
+ )
151
+
152
+ def _serialize_key(self, keys):
153
+ assert type(keys) == tuple
154
+ assert len(keys) == 2
155
+ key1, key2 = keys
156
+ assert type(key1) == int
157
+ assert key1 >= 0 and key1 <= _OidKeysMixin.MAX_OID
158
+ assert type(key2) == int
159
+ assert key2 >= 0 and key2 <= _OidKeysMixin.MAX_OID
160
+ return struct.pack(">QQ", key1, key2)
161
+
162
+ def _deserialize_key(self, data):
163
+ assert len(data) == 16
164
+ return struct.unpack(">QQ", data)
165
+
166
+
167
+ class _Oid3KeysMixin(object):
168
+ @staticmethod
169
+ def new_key(secure=False):
170
+ return (
171
+ _OidKeysMixin.new_key(secure=secure),
172
+ _OidKeysMixin.new_key(secure=secure),
173
+ _OidKeysMixin.new_key(secure=secure),
174
+ )
175
+
176
+ def _serialize_key(self, keys):
177
+ assert type(keys) == tuple
178
+ assert len(keys) == 3
179
+ key1, key2, key3 = keys
180
+ assert type(key1) == int
181
+ assert key1 >= 0 and key1 <= _OidKeysMixin.MAX_OID
182
+ assert type(key2) == int
183
+ assert key2 >= 0 and key2 <= _OidKeysMixin.MAX_OID
184
+ assert type(key3) == int
185
+ assert key3 >= 0 and key3 <= _OidKeysMixin.MAX_OID
186
+ return struct.pack(">QQQ", key1, key2, key3)
187
+
188
+ def _deserialize_key(self, data):
189
+ assert len(data) == 24
190
+ return struct.unpack(">QQQ", data)
191
+
192
+
193
+ class _OidTimestampKeysMixin(object):
194
+ @staticmethod
195
+ def new_key(secure=False):
196
+ return _OidKeysMixin.new_key(secure=secure), 0
197
+
198
+ def _serialize_key(self, keys):
199
+ assert type(keys) == tuple
200
+ assert len(keys) == 2
201
+ key1, key2 = keys
202
+ assert type(key1) == int
203
+ assert key1 >= 0 and key1 <= _OidKeysMixin.MAX_OID
204
+ assert isinstance(key2, np.datetime64)
205
+ return struct.pack(">Q", key1) + key2.tobytes()
206
+
207
+ def _deserialize_key(self, data):
208
+ assert len(data) == 16
209
+ key1, key2 = struct.unpack(">Q>Q", data)
210
+ key2 = np.datetime64(key2, "ns")
211
+ return key1, key2
212
+
213
+
214
+ class _OidTimestampStringKeysMixin(object):
215
+ @staticmethod
216
+ def new_key(secure=False):
217
+ return _OidKeysMixin.new_key(secure=secure), 0, ""
218
+
219
+ def _serialize_key(self, keys):
220
+ assert type(keys) == tuple
221
+ assert len(keys) == 3
222
+ key1, key2, key3 = keys
223
+ assert type(key1) == int
224
+ assert key1 >= 0 and key1 <= _OidKeysMixin.MAX_OID
225
+ assert isinstance(key2, np.datetime64)
226
+ assert type(key3) == str
227
+ return struct.pack(">Q", key1) + key2.tobytes() + key3.encode("utf8")
228
+
229
+ def _deserialize_key(self, data):
230
+ assert type(data) == bytes
231
+ assert len(data) > 16
232
+
233
+ oid, ts = struct.unpack(">Q>Q", data[:16])
234
+ ts = np.datetime64(ts, "ns")
235
+ s = data[16:]
236
+ return oid, ts, s
237
+
238
+
239
+ class _OidStringKeysMixin(object):
240
+ @staticmethod
241
+ def new_key(secure=False):
242
+ return _OidKeysMixin.new_key(secure=secure), ""
243
+
244
+ def _serialize_key(self, key1_key2):
245
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
246
+ key1, key2 = key1_key2
247
+
248
+ assert type(key1) == int
249
+ assert type(key2) == str
250
+
251
+ return struct.pack(">Q", key1) + key2.encode("utf8")
252
+
253
+ def _deserialize_key(self, data):
254
+ assert type(data) == bytes
255
+ assert len(data) > 8
256
+ oid = struct.unpack(">Q", data[:8])[0]
257
+ data = data[8:]
258
+ s = data.decode("utf8")
259
+ return oid, s
260
+
261
+
262
+ class _StringOidKeysMixin(object):
263
+ @staticmethod
264
+ def new_key(secure=False):
265
+ return _random_string(), _OidKeysMixin.new_key(secure=secure)
266
+
267
+ def _serialize_key(self, key1_key2):
268
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
269
+ key1, key2 = key1_key2
270
+
271
+ assert type(key1) == str
272
+ assert type(key2) == int
273
+
274
+ return key1.encode("utf8") + struct.pack(">Q", key2)
275
+
276
+ def _deserialize_key(self, data):
277
+ assert type(data) == bytes
278
+ assert len(data) > 8
279
+ oid = struct.unpack(">Q", data[-8:])[0]
280
+ data = data[0:8]
281
+ s = data.decode("utf8")
282
+ return s, oid
283
+
284
+
285
+ class _StringKeysMixin(object):
286
+ @staticmethod
287
+ def new_key():
288
+ return _random_string()
289
+
290
+ def _serialize_key(self, key):
291
+ assert type(key) == str
292
+
293
+ return key.encode("utf8")
294
+
295
+ def _deserialize_key(self, data):
296
+ assert type(data) == bytes
297
+
298
+ return data.decode("utf8")
299
+
300
+
301
+ class _StringStringKeysMixin(object):
302
+ @staticmethod
303
+ def new_key():
304
+ return _random_string(), _random_string()
305
+
306
+ def _serialize_key(self, key1_key2):
307
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
308
+ key1, key2 = key1_key2
309
+
310
+ assert type(key1) == str
311
+ assert type(key2) == str
312
+
313
+ return key1.encode("utf8") + b"\x00" + key2.encode("utf8")
314
+
315
+ def _deserialize_key(self, data):
316
+ assert type(data) == bytes
317
+ assert len(data) > 0
318
+ d = data.split(b"\x00")
319
+ assert len(d) == 2
320
+ return d[0], d[1]
321
+
322
+
323
+ class _StringStringStringKeysMixin(object):
324
+ @staticmethod
325
+ def new_key():
326
+ return _random_string(), _random_string(), _random_string()
327
+
328
+ def _serialize_key(self, key1_key2_key3):
329
+ assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
330
+ key1, key2, key3 = key1_key2_key3
331
+
332
+ assert type(key1) == str
333
+ assert type(key2) == str
334
+ assert type(key3) == str
335
+
336
+ return (
337
+ key1.encode("utf8")
338
+ + b"\x00"
339
+ + key2.encode("utf8")
340
+ + b"\x00"
341
+ + key3.encode("utf8")
342
+ )
343
+
344
+ def _deserialize_key(self, data):
345
+ assert type(data) == bytes
346
+ assert len(data) > 0
347
+ d = data.split(b"\x00")
348
+ assert len(d) == 3
349
+ return d[0], d[1], d[2]
350
+
351
+
352
+ class _UuidKeysMixin(object):
353
+ @staticmethod
354
+ def new_key():
355
+ # https: // docs.python.org / 3 / library / uuid.html # uuid.uuid4
356
+ # return uuid.UUID(bytes=os.urandom(16))
357
+ return uuid.uuid4()
358
+
359
+ def _serialize_key(self, key):
360
+ assert isinstance(key, uuid.UUID), 'key must be an UUID, but was "{}"'.format(
361
+ key
362
+ )
363
+
364
+ # The UUID as a 16-byte string (containing the six integer fields in big-endian byte order).
365
+ # https://docs.python.org/3/library/uuid.html#uuid.UUID.bytes
366
+ return key.bytes
367
+
368
+ def _deserialize_key(self, data):
369
+ assert type(data) == bytes
370
+
371
+ return uuid.UUID(bytes=data)
372
+
373
+
374
+ class _UuidUuidKeysMixin(object):
375
+ def _serialize_key(self, key1_key2):
376
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
377
+ key1, key2 = key1_key2
378
+
379
+ if key1 is None:
380
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
381
+ if key2 is None:
382
+ key2 = uuid.UUID(bytes=b"\x00" * 16)
383
+
384
+ assert isinstance(key1, uuid.UUID)
385
+ assert isinstance(key2, uuid.UUID)
386
+
387
+ return key1.bytes + key2.bytes
388
+
389
+ def _deserialize_key(self, data):
390
+ assert type(data) == bytes
391
+ assert len(data) == 32
392
+
393
+ data1, data2 = data[0:16], data[16:32]
394
+ return uuid.UUID(bytes=data1), uuid.UUID(bytes=data2)
395
+
396
+
397
+ class _UuidUuidUuidKeysMixin(object):
398
+ def _serialize_key(self, key1_key2_key3):
399
+ assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
400
+ key1, key2, key3 = key1_key2_key3
401
+
402
+ if key1 is None:
403
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
404
+ if key2 is None:
405
+ key2 = uuid.UUID(bytes=b"\x00" * 16)
406
+ if key3 is None:
407
+ key3 = uuid.UUID(bytes=b"\x00" * 16)
408
+
409
+ assert isinstance(key1, uuid.UUID)
410
+ assert isinstance(key2, uuid.UUID)
411
+ assert isinstance(key3, uuid.UUID)
412
+
413
+ return key1.bytes + key2.bytes + key3.bytes
414
+
415
+ def _deserialize_key(self, data):
416
+ assert type(data) == bytes
417
+ assert len(data) == 48
418
+
419
+ data1, data2, data3 = data[0:16], data[16:32], data[32:48]
420
+ return uuid.UUID(bytes=data1), uuid.UUID(bytes=data2), uuid.UUID(bytes=data3)
421
+
422
+
423
+ class _UuidUuidUuidUuidKeysMixin(object):
424
+ def _serialize_key(self, key1_key2_key3_key4):
425
+ assert type(key1_key2_key3_key4) == tuple and len(key1_key2_key3_key4) == 4
426
+ key1, key2, key3, key4 = key1_key2_key3_key4
427
+
428
+ if key1 is None:
429
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
430
+ if key2 is None:
431
+ key2 = uuid.UUID(bytes=b"\x00" * 16)
432
+ if key3 is None:
433
+ key3 = uuid.UUID(bytes=b"\x00" * 16)
434
+ if key4 is None:
435
+ key4 = uuid.UUID(bytes=b"\x00" * 16)
436
+
437
+ assert isinstance(key1, uuid.UUID)
438
+ assert isinstance(key2, uuid.UUID)
439
+ assert isinstance(key3, uuid.UUID)
440
+ assert isinstance(key4, uuid.UUID)
441
+
442
+ return key1.bytes + key2.bytes + key3.bytes + key4.bytes
443
+
444
+ def _deserialize_key(self, data):
445
+ assert type(data) == bytes
446
+ assert len(data) == 64
447
+
448
+ data1, data2, data3, data4 = data[0:16], data[16:32], data[32:48], data[48:64]
449
+ return (
450
+ uuid.UUID(bytes=data1),
451
+ uuid.UUID(bytes=data2),
452
+ uuid.UUID(bytes=data3),
453
+ uuid.UUID(bytes=data4),
454
+ )
455
+
456
+
457
+ class _Uint16UuidTimestampKeysMixin(object):
458
+ @staticmethod
459
+ def new_key():
460
+ return random.randint(0, 2**16), uuid.uuid4(), np.datetime64(time_ns(), "ns")
461
+
462
+ def _serialize_key(self, key1_key2_key3):
463
+ assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
464
+ key1, key2, key3 = key1_key2_key3
465
+
466
+ if key1 is None:
467
+ key1 = 0
468
+ if key2 is None:
469
+ key2 = uuid.UUID(bytes=b"\x00" * 16)
470
+ if key3 is None:
471
+ key3 = np.datetime64(0, "ns")
472
+
473
+ assert type(key1) == int and key1 >= 0 and key1 < 2**16
474
+ assert isinstance(key2, uuid.UUID)
475
+ assert isinstance(key3, np.datetime64)
476
+
477
+ return struct.pack("H", key1) + key2.bytes + dt_to_bytes(key3)
478
+
479
+ def _deserialize_key(self, data):
480
+ assert type(data) == bytes and len(data) == (2 + 16 + 8)
481
+
482
+ data1, data2, data3 = (
483
+ data[0:2],
484
+ data[2:18],
485
+ data[18:26],
486
+ )
487
+ return struct.unpack("H", data1), uuid.UUID(bytes=data2), bytes_to_dt(data3)
488
+
489
+
490
+ class _UuidBytes20Uint8KeysMixin(object):
491
+ @staticmethod
492
+ def new_key():
493
+ return uuid.uuid4(), os.urandom(20), random.randint(0, 255)
494
+
495
+ def _serialize_key(self, key1_key2_key3):
496
+ assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
497
+ key1, key2, key3 = key1_key2_key3
498
+
499
+ if key1 is None:
500
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
501
+ if key2 is None:
502
+ key2 = b"\x00" * 20
503
+ if key3 is None:
504
+ key3 = 0
505
+
506
+ assert isinstance(key1, uuid.UUID)
507
+ assert type(key2) == bytes and len(key2) == 20
508
+
509
+ # FIXME: workaround to process eg (3,)
510
+ if type(key3) == tuple and len(key3) == 1:
511
+ key3 = key3[0]
512
+ assert type(key3) == int and key3 >= 0 and key3 < 256
513
+
514
+ return key1.bytes + key2 + struct.pack("B", key3)
515
+
516
+ def _deserialize_key(self, data):
517
+ assert type(data) == bytes and len(data) == (16 + 20 + 1)
518
+
519
+ data1, data2, data3 = (
520
+ data[0:16],
521
+ data[16:36],
522
+ data[36:37],
523
+ )
524
+ return uuid.UUID(bytes=data1), data2, struct.unpack("B", data3)
525
+
526
+
527
+ class _UuidBytes20Uint8UuidKeysMixin(object):
528
+ @staticmethod
529
+ def new_key():
530
+ return uuid.uuid4(), os.urandom(20), random.randint(0, 255), uuid.uuid4()
531
+
532
+ def _serialize_key(self, key1_key2_key3_key4):
533
+ assert type(key1_key2_key3_key4) == tuple and len(key1_key2_key3_key4) == 4
534
+ key1, key2, key3, key4 = key1_key2_key3_key4
535
+
536
+ if key1 is None:
537
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
538
+ if key2 is None:
539
+ key2 = b"\x00" * 20
540
+ if key3 is None:
541
+ key3 = 0
542
+ if key4 is None:
543
+ key4 = uuid.UUID(bytes=b"\x00" * 16)
544
+
545
+ assert isinstance(key1, uuid.UUID)
546
+ assert type(key2) == bytes and len(key2) == 20
547
+ assert type(key3) == int and key3 >= 0 and key3 < 256
548
+ assert isinstance(key4, uuid.UUID)
549
+
550
+ return key1.bytes + key2 + struct.pack("B", key3) + key4.bytes
551
+
552
+ def _deserialize_key(self, data):
553
+ assert type(data) == bytes and len(data) == (16 + 20 + 1 + 16)
554
+
555
+ data1, data2, data3, data4 = data[0:16], data[16:36], data[36:37], data[37:53]
556
+ return (
557
+ uuid.UUID(bytes=data1),
558
+ data2,
559
+ struct.unpack("B", data3),
560
+ uuid.UUID(bytes=data4),
561
+ )
562
+
563
+
564
+ class _UuidBytes20Bytes20Uint8UuidKeysMixin(object):
565
+ @staticmethod
566
+ def new_key():
567
+ return (
568
+ uuid.uuid4(),
569
+ os.urandom(20),
570
+ os.urandom(20),
571
+ random.randint(0, 255),
572
+ uuid.uuid4(),
573
+ )
574
+
575
+ def _serialize_key(self, key1_key2_key3_key4_key5):
576
+ assert (
577
+ type(key1_key2_key3_key4_key5) == tuple
578
+ and len(key1_key2_key3_key4_key5) == 5
579
+ )
580
+ key1, key2, key3, key4, key5 = key1_key2_key3_key4_key5
581
+
582
+ if key1 is None:
583
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
584
+ if key2 is None:
585
+ key2 = b"\x00" * 20
586
+ if key3 is None:
587
+ key3 = b"\x00" * 20
588
+ if key4 is None:
589
+ key4 = 0
590
+ if key5 is None:
591
+ key5 = uuid.UUID(bytes=b"\x00" * 16)
592
+
593
+ assert isinstance(key1, uuid.UUID)
594
+ assert type(key2) == bytes and len(key2) == 20
595
+ assert type(key3) == bytes and len(key2) == 20
596
+ assert type(key4) == int and key4 >= 0 and key4 < 256
597
+ assert isinstance(key5, uuid.UUID)
598
+
599
+ return key1.bytes + key2 + key3 + struct.pack("B", key4) + key5.bytes
600
+
601
+ def _deserialize_key(self, data):
602
+ assert type(data) == bytes and len(data) == (16 + 20 + 20 + 1 + 16)
603
+
604
+ data1, data2, data3, data4, data5 = (
605
+ data[0:16],
606
+ data[16:36],
607
+ data[36:56],
608
+ data[56:57],
609
+ data[57:73],
610
+ )
611
+ return (
612
+ uuid.UUID(bytes=data1),
613
+ data2,
614
+ data3,
615
+ struct.unpack("B", data4),
616
+ uuid.UUID(bytes=data5),
617
+ )
618
+
619
+
620
+ class _TimestampKeysMixin(object):
621
+ @staticmethod
622
+ def new_key():
623
+ return np.datetime64(time_ns(), "ns")
624
+
625
+ def _serialize_key(self, key1):
626
+ assert isinstance(key1, np.datetime64)
627
+
628
+ return dt_to_bytes(key1)
629
+
630
+ def _deserialize_key(self, data):
631
+ assert type(data) == bytes
632
+ assert len(data) == 8
633
+
634
+ return bytes_to_dt(data[0:8])
635
+
636
+
637
+ class _TimestampUuidKeysMixin(object):
638
+ @staticmethod
639
+ def new_key():
640
+ return np.datetime64(time_ns(), "ns"), uuid.uuid4()
641
+
642
+ def _serialize_key(self, key1_key2):
643
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
644
+ key1, key2 = key1_key2
645
+
646
+ if key1 is None:
647
+ key1 = np.datetime64(0, "ns")
648
+ if key2 is None:
649
+ key2 = uuid.UUID(bytes=b"\x00" * 16)
650
+
651
+ assert isinstance(key1, np.datetime64)
652
+ assert isinstance(key2, uuid.UUID)
653
+
654
+ return dt_to_bytes(key1) + key2.bytes
655
+
656
+ def _deserialize_key(self, data):
657
+ assert type(data) == bytes
658
+ assert len(data) == 24
659
+
660
+ data1, data2 = data[0:8], data[8:24]
661
+
662
+ key1 = bytes_to_dt(data1)
663
+ key2 = uuid.UUID(bytes=data2)
664
+ return key1, key2
665
+
666
+
667
+ class _UuidTimestampUuidKeysMixin(object):
668
+ @staticmethod
669
+ def new_key():
670
+ return uuid.uuid4(), np.datetime64(time_ns(), "ns"), uuid.uuid4()
671
+
672
+ def _serialize_key(self, key1_key2_key3):
673
+ assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
674
+ key1, key2, key3 = key1_key2_key3
675
+
676
+ if key1 is None:
677
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
678
+ if key2 is None:
679
+ key2 = np.datetime64(0, "ns")
680
+ if key3 is None:
681
+ key3 = uuid.UUID(bytes=b"\x00" * 16)
682
+
683
+ assert isinstance(key1, uuid.UUID)
684
+ assert isinstance(key2, np.datetime64)
685
+ assert isinstance(key3, uuid.UUID)
686
+
687
+ return key1.bytes + dt_to_bytes(key2) + key3.bytes
688
+
689
+ def _deserialize_key(self, data):
690
+ assert type(data) == bytes
691
+ assert len(data) == 32
692
+
693
+ data1, data2, data3 = data[0:16], data[16:24], data[24:32]
694
+
695
+ key1 = uuid.UUID(bytes=data1)
696
+ key2 = bytes_to_dt(data2)
697
+ key3 = uuid.UUID(bytes=data3)
698
+ return key1, key2, key3
699
+
700
+
701
+ class _TimestampUuidStringKeysMixin(object):
702
+ @staticmethod
703
+ def new_key():
704
+ return np.datetime64(time_ns(), "ns"), uuid.uuid4(), ""
705
+
706
+ def _serialize_key(self, key1_key2_key3):
707
+ assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
708
+ key1, key2, key3 = key1_key2_key3
709
+
710
+ if key1 is None:
711
+ key1 = np.datetime64(0, "ns")
712
+ if key2 is None:
713
+ key2 = uuid.UUID(bytes=b"\x00" * 16)
714
+ if key3 is None:
715
+ key3 = ""
716
+
717
+ assert isinstance(key1, np.datetime64)
718
+ assert isinstance(key2, uuid.UUID)
719
+ assert type(key3) == str
720
+
721
+ return dt_to_bytes(key1) + key2.bytes + key3.encode("utf8")
722
+
723
+ def _deserialize_key(self, data):
724
+ assert type(data) == bytes
725
+ assert len(data) >= 24
726
+
727
+ data1, data2, data3 = data[0:8], data[8:24], data[24:]
728
+
729
+ key1 = bytes_to_dt(data1)
730
+ key2 = uuid.UUID(bytes=data2)
731
+ key3 = data3.decode("utf8") if data3 else ""
732
+ return key1, key2, key3
733
+
734
+
735
+ class _TimestampBytes32KeysMixin(object):
736
+ @staticmethod
737
+ def new_key():
738
+ return np.datetime64(time_ns(), "ns"), os.urandom(32)
739
+
740
+ def _serialize_key(self, key1_key2):
741
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
742
+ key1, key2 = key1_key2
743
+
744
+ if key1 is None:
745
+ key1 = np.datetime64(0, "ns")
746
+ if key2 is None:
747
+ key2 = b"\x00" * 32
748
+
749
+ assert isinstance(key1, np.datetime64)
750
+ assert isinstance(key2, bytes)
751
+ assert isinstance(key2, bytes) and len(key2) == 32
752
+
753
+ return dt_to_bytes(key1) + key2
754
+
755
+ def _deserialize_key(self, data):
756
+ assert type(data) == bytes, "data must be binary, but got {}".format(type(data))
757
+ assert len(data) == 40, "data must have len 40, but got {}".format(len(data))
758
+
759
+ data1, data2 = data[0:8], data[8:40]
760
+
761
+ key1 = bytes_to_dt(data1)
762
+ key2 = data2
763
+ return key1, key2
764
+
765
+
766
+ class _TimestampStringKeysMixin(object):
767
+ @staticmethod
768
+ def new_key():
769
+ return np.datetime64(time_ns(), "ns"), _StringKeysMixin.new_key()
770
+
771
+ def _serialize_key(self, key1_key2):
772
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
773
+ key1, key2 = key1_key2
774
+
775
+ if key1 is None:
776
+ key1 = np.datetime64(0, "ns")
777
+ if key2 is None:
778
+ key2 = ""
779
+
780
+ assert isinstance(key1, np.datetime64)
781
+ assert type(key2) == str
782
+
783
+ return dt_to_bytes(key1) + key2.encode("utf8")
784
+
785
+ def _deserialize_key(self, data):
786
+ assert type(data) == bytes
787
+ assert len(data) > 8
788
+
789
+ data1, data2 = data[0:8], data[8:]
790
+ key1 = bytes_to_dt(data1)
791
+ key2 = data2.decode("utf8")
792
+ return key1, key2
793
+
794
+
795
+ class _StringTimestampKeysMixin(object):
796
+ @staticmethod
797
+ def new_key():
798
+ return _StringKeysMixin.new_key(), np.datetime64(time_ns(), "ns")
799
+
800
+ def _serialize_key(self, key1_key2):
801
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
802
+ key1, key2 = key1_key2
803
+
804
+ if key1 is None:
805
+ key1 = ""
806
+ if key2 is None:
807
+ key2 = np.datetime64(0, "ns")
808
+
809
+ assert type(key1) == str
810
+ assert isinstance(key2, np.datetime64)
811
+
812
+ return key1.encode("utf8") + dt_to_bytes(key2)
813
+
814
+ def _deserialize_key(self, data):
815
+ assert type(data) == bytes
816
+ assert len(data) > 8
817
+
818
+ slen = len(data) - 8
819
+ data1, data2 = data[0:slen], data[slen:]
820
+ key1 = data1.decode("utf8")
821
+ key2 = bytes_to_dt(data2)
822
+ return key1, key2
823
+
824
+
825
+ class _UuidTimestampKeysMixin(object):
826
+ @staticmethod
827
+ def new_key():
828
+ return uuid.uuid4(), np.datetime64(time_ns(), "ns")
829
+
830
+ def _serialize_key(self, key1_key2):
831
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
832
+ key1, key2 = key1_key2
833
+
834
+ if key1 is None:
835
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
836
+ if key2 is None:
837
+ key2 = np.datetime64(0, "ns")
838
+
839
+ assert isinstance(key1, uuid.UUID)
840
+ assert isinstance(key2, np.datetime64)
841
+
842
+ return key1.bytes + dt_to_bytes(key2)
843
+
844
+ def _deserialize_key(self, data):
845
+ assert type(data) == bytes
846
+ assert len(data) == 24
847
+
848
+ data1, data2 = data[0:16], data[16:24]
849
+ key1 = uuid.UUID(bytes=data1)
850
+ key2 = bytes_to_dt(data2)
851
+ return key1, key2
852
+
853
+
854
+ class _Uint64TimestampKeysMixin(object):
855
+ @staticmethod
856
+ def new_key():
857
+ return random.randint(1, 2**64 - 1), np.datetime64(time_ns(), "ns")
858
+
859
+ def _serialize_key(self, key1_key2):
860
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
861
+ key1, key2 = key1_key2
862
+
863
+ if key1 is None:
864
+ key1 = 0
865
+ if key2 is None:
866
+ key2 = np.datetime64(0, "ns")
867
+
868
+ assert type(key1) == int, "key1 must be int, but was {}".format(type(key1))
869
+ assert isinstance(key2, np.datetime64), (
870
+ "key2 must be np.datetime64, but was {}".format(type(key2))
871
+ )
872
+
873
+ return struct.pack(">Q", key1) + dt_to_bytes(key2)
874
+
875
+ def _deserialize_key(self, data):
876
+ assert type(data) == bytes
877
+ assert len(data) == 16
878
+
879
+ data1, data2 = data[0:8], data[8:16]
880
+ key1 = struct.unpack(">Q", data1)[0]
881
+ key2 = bytes_to_dt(data2)
882
+ return key1, key2
883
+
884
+
885
+ class _UuidStringKeysMixin(object):
886
+ def _serialize_key(self, key1_key2):
887
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
888
+ key1, key2 = key1_key2
889
+
890
+ if key1 is None:
891
+ key1 = uuid.UUID(bytes=b"\x00" * 16)
892
+ if key2 is None:
893
+ key2 = ""
894
+
895
+ assert isinstance(key1, uuid.UUID), (
896
+ "key1 must be of type UUID, but was {}".format(type(key1))
897
+ )
898
+ assert type(key2) == str, "key2 must be of type string, but was {}".format(
899
+ type(key2)
900
+ )
901
+
902
+ # The UUID as a 16-byte string (containing the six integer fields in big-endian byte order).
903
+ # https://docs.python.org/3/library/uuid.html#uuid.UUID.bytes
904
+ return key1.bytes + key2.encode("utf8")
905
+
906
+ def _deserialize_key(self, data):
907
+ assert type(data) == bytes
908
+ assert len(data) >= 16
909
+ data1 = data[:16]
910
+ if len(data) > 16:
911
+ data2 = data[16:]
912
+ else:
913
+ data2 = b""
914
+ return uuid.UUID(bytes=data1), data2.decode("utf8")
915
+
916
+
917
+ class _SlotUuidKeysMixin(object):
918
+ def _serialize_key(self, key1_key2):
919
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
920
+ key1, key2 = key1_key2
921
+
922
+ assert type(key1) == int
923
+ assert key1 >= 0 and key1 < 2**16
924
+ assert isinstance(key2, uuid.UUID)
925
+
926
+ return struct.pack(">H", key1) + key2.bytes
927
+
928
+ def _deserialize_key(self, data):
929
+ assert type(data) == bytes
930
+ assert len(data) == (2 + 16)
931
+ data1, data2 = data[:2], data[2:]
932
+
933
+ return struct.unpack(">H", data1)[0], uuid.UUID(bytes=data2)
934
+
935
+
936
+ class _Bytes32KeysMixin(object):
937
+ @staticmethod
938
+ def new_key():
939
+ return os.urandom(32)
940
+
941
+ def _serialize_key(self, key):
942
+ assert type(key) == bytes, 'key must be bytes[32], was "{}"'.format(key)
943
+ assert len(key) == 32
944
+
945
+ return key
946
+
947
+ def _deserialize_key(self, data):
948
+ assert type(data) == bytes, 'data must be bytes[32], was "{}"'.format(data)
949
+ assert len(data) == 32
950
+
951
+ return data
952
+
953
+
954
+ class _Bytes32Bytes32KeysMixin(object):
955
+ def _serialize_key(self, key1_key2):
956
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
957
+ key1, key2 = key1_key2
958
+
959
+ assert type(key1) == bytes
960
+ assert len(key1) == 32
961
+
962
+ assert type(key2) == bytes
963
+ assert len(key2) == 32
964
+
965
+ return key1 + key2
966
+
967
+ def _deserialize_key(self, data):
968
+ assert type(data) == bytes
969
+ assert len(data) == 64
970
+
971
+ data1, data2 = data[0:32], data[32:64]
972
+ return data1, data2
973
+
974
+
975
+ class _Bytes32UuidKeysMixin(object):
976
+ def _serialize_key(self, key1_key2):
977
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
978
+ key1, key2 = key1_key2
979
+
980
+ assert type(key1) == bytes
981
+ assert len(key1) == 32
982
+
983
+ assert isinstance(key2, uuid.UUID)
984
+
985
+ return key1 + key2.bytes
986
+
987
+ def _deserialize_key(self, data):
988
+ assert type(data) == bytes
989
+ assert len(data) == 48
990
+
991
+ data1, data2 = data[0:32], data[32:48]
992
+ return data1, uuid.UUID(bytes=data2)
993
+
994
+
995
+ class _UuidBytes32KeysMixin(object):
996
+ def _serialize_key(self, key1_key2):
997
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
998
+ key1, key2 = key1_key2
999
+
1000
+ assert isinstance(key1, uuid.UUID)
1001
+
1002
+ assert type(key2) == bytes
1003
+ assert len(key2) == 32
1004
+
1005
+ return key2.bytes + key1
1006
+
1007
+ def _deserialize_key(self, data):
1008
+ assert type(data) == bytes
1009
+ assert len(data) == 48
1010
+
1011
+ data1, data2 = data[0:16], data[16:48]
1012
+ return uuid.UUID(bytes=data1), data2
1013
+
1014
+
1015
+ class _Bytes32StringKeysMixin(object):
1016
+ def _serialize_key(self, key1_key2):
1017
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
1018
+ key1, key2 = key1_key2
1019
+
1020
+ assert type(key1) == bytes
1021
+ assert len(key1) == 32
1022
+
1023
+ assert type(key2) == str
1024
+ assert len(key2) > 0
1025
+
1026
+ return key1 + key2.encode("utf8")
1027
+
1028
+ def _deserialize_key(self, data):
1029
+ assert type(data) == bytes
1030
+ assert len(data) > 32
1031
+
1032
+ data1, data2 = data[:32], data[32:]
1033
+ return data1, data2.decode("utf8")
1034
+
1035
+
1036
+ class _UuidUuidStringKeysMixin(object):
1037
+ def _serialize_key(self, key1_key2_key3):
1038
+ assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
1039
+ key1, key2, key3 = key1_key2_key3
1040
+
1041
+ assert isinstance(key1, uuid.UUID)
1042
+ assert isinstance(key2, uuid.UUID)
1043
+ assert type(key3) == str
1044
+
1045
+ return key1.bytes + key2.bytes + key3.encode("utf8")
1046
+
1047
+ def _deserialize_key(self, data):
1048
+ assert type(data) == bytes
1049
+ assert len(data) > 32
1050
+
1051
+ data1, data2, data3 = data[:16], data[16:32], data[32:]
1052
+ return uuid.UUID(bytes=data1), uuid.UUID(bytes=data2), data3.decode("utf8")
1053
+
1054
+
1055
+ class _UuidUuidUuidStringKeysMixin(object):
1056
+ def _serialize_key(self, key1_key2_key3_key4):
1057
+ assert type(key1_key2_key3_key4) == tuple and len(key1_key2_key3_key4) == 4
1058
+ key1, key2, key3, key4 = key1_key2_key3_key4
1059
+
1060
+ assert isinstance(key1, uuid.UUID), "key1 must be a UUID, was {}: {}".format(
1061
+ type(key1), key1
1062
+ )
1063
+ assert isinstance(key2, uuid.UUID), "key2 must be a UUID, was {}: {}".format(
1064
+ type(key2), key2
1065
+ )
1066
+ assert isinstance(key3, uuid.UUID), "key3 must be a UUID, was {}: {}".format(
1067
+ type(key3), key3
1068
+ )
1069
+ assert type(key4) == str, "key4 must be a str, was {}: {}".format(
1070
+ type(key4), key4
1071
+ )
1072
+
1073
+ return key1.bytes + key2.bytes + key3.bytes + key4.encode("utf8")
1074
+
1075
+ def _deserialize_key(self, data):
1076
+ assert type(data) == bytes
1077
+ assert len(data) >= 48
1078
+
1079
+ data1, data2, data3, data4 = data[:16], data[16:32], data[32:48], data[48:]
1080
+ return (
1081
+ uuid.UUID(bytes=data1),
1082
+ uuid.UUID(bytes=data2),
1083
+ uuid.UUID(bytes=data3),
1084
+ data4.decode("utf8"),
1085
+ )
1086
+
1087
+
1088
+ class _Bytes20KeysMixin(object):
1089
+ @staticmethod
1090
+ def new_key():
1091
+ return os.urandom(20)
1092
+
1093
+ def _serialize_key(self, key):
1094
+ assert type(key) == bytes and len(key) == 20, (
1095
+ 'key must be bytes[20], was "{}"'.format(key)
1096
+ )
1097
+
1098
+ return key
1099
+
1100
+ def _deserialize_key(self, data):
1101
+ assert type(data) == bytes and len(data) == 20, (
1102
+ 'data must be bytes[20], was "{}"'.format(data)
1103
+ )
1104
+
1105
+ return data
1106
+
1107
+
1108
+ class _Bytes16KeysMixin(object):
1109
+ @staticmethod
1110
+ def new_key():
1111
+ return os.urandom(16)
1112
+
1113
+ def _serialize_key(self, key):
1114
+ assert type(key) == bytes and len(key) == 16, (
1115
+ 'key must be bytes[16], was "{}"'.format(key)
1116
+ )
1117
+
1118
+ return key
1119
+
1120
+ def _deserialize_key(self, data):
1121
+ assert type(data) == bytes and len(data) == 16, (
1122
+ 'data must be bytes[16], was "{}"'.format(data)
1123
+ )
1124
+
1125
+ return data
1126
+
1127
+
1128
+ class _Bytes20Bytes20KeysMixin(object):
1129
+ @staticmethod
1130
+ def new_key():
1131
+ return os.urandom(20), os.urandom(20)
1132
+
1133
+ def _serialize_key(self, key1_key2):
1134
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
1135
+ key1, key2 = key1_key2
1136
+
1137
+ assert type(key1) == bytes
1138
+ assert len(key1) == 20
1139
+
1140
+ assert type(key2) == bytes
1141
+ assert len(key2) == 20
1142
+
1143
+ return key1 + key2
1144
+
1145
+ def _deserialize_key(self, data):
1146
+ assert type(data) == bytes
1147
+ assert len(data) == 40
1148
+
1149
+ data1, data2 = data[0:20], data[20:40]
1150
+ return data1, data2
1151
+
1152
+
1153
+ class _Bytes20StringKeysMixin(object):
1154
+ @staticmethod
1155
+ def new_key():
1156
+ return os.urandom(20), binascii.b2a_base64(os.urandom(8)).decode().strip()
1157
+
1158
+ def _serialize_key(self, key1_key2):
1159
+ assert type(key1_key2) == tuple and len(key1_key2) == 2
1160
+ key1, key2 = key1_key2
1161
+
1162
+ assert type(key1) == bytes
1163
+ assert len(key1) == 20
1164
+
1165
+ assert type(key2) == str
1166
+ assert len(key2) > 0
1167
+
1168
+ return key1 + key2.encode("utf8")
1169
+
1170
+ def _deserialize_key(self, data):
1171
+ assert type(data) == bytes
1172
+ assert len(data) > 20
1173
+ data1, data2 = data[:20], data[20:]
1174
+
1175
+ return data1, data2.decode("utf8")
1176
+
1177
+
1178
+ class _Bytes20TimestampKeysMixin(object):
1179
+ @staticmethod
1180
+ def new_key():
1181
+ return os.urandom(20), np.datetime64(time_ns(), "ns")
1182
+
1183
+ def _serialize_key(self, keys):
1184
+ assert type(keys) == tuple, (
1185
+ 'keys in {}._serialize_key must be a tuple, was: "{}"'.format(
1186
+ self.__class__.__name__, keys
1187
+ )
1188
+ )
1189
+ assert len(keys) == 2
1190
+ key1, key2 = keys
1191
+
1192
+ if not key1:
1193
+ key1 = b"\x00" * 20
1194
+
1195
+ assert key1 is None or (type(key1) == bytes and len(key1) == 20)
1196
+ assert isinstance(key2, np.datetime64)
1197
+
1198
+ return key1 + dt_to_bytes(key2)
1199
+
1200
+ def _deserialize_key(self, data):
1201
+ assert data is None or (type(data) == bytes and len(data) == 28)
1202
+
1203
+ if data:
1204
+ key1 = data[:20]
1205
+ key2 = bytes_to_dt(data[20:])
1206
+ else:
1207
+ key1 = b"\x00" * 20
1208
+ key2 = np.datetime64(0, "ns")
1209
+
1210
+ return key1, key2
1211
+
1212
+
1213
+ class _Bytes16TimestampKeysMixin(object):
1214
+ @staticmethod
1215
+ def new_key():
1216
+ return os.urandom(20), np.datetime64(time_ns(), "ns")
1217
+
1218
+ def _serialize_key(self, keys):
1219
+ assert type(keys) == tuple, (
1220
+ 'keys in {}._serialize_key must be a tuple, was: "{}"'.format(
1221
+ self.__class__.__name__, keys
1222
+ )
1223
+ )
1224
+ assert len(keys) == 2
1225
+ key1, key2 = keys
1226
+
1227
+ if not key1:
1228
+ key1 = b"\x00" * 16
1229
+
1230
+ assert key1 is None or (type(key1) == bytes and len(key1) == 16)
1231
+ assert isinstance(key2, np.datetime64)
1232
+
1233
+ return key1 + dt_to_bytes(key2)
1234
+
1235
+ def _deserialize_key(self, data):
1236
+ assert data is None or (type(data) == bytes and len(data) == 24)
1237
+
1238
+ if data:
1239
+ key1 = data[:16]
1240
+ key2 = bytes_to_dt(data[16:])
1241
+ else:
1242
+ key1 = b"\x00" * 16
1243
+ key2 = np.datetime64(0, "ns")
1244
+
1245
+ return key1, key2
1246
+
1247
+
1248
+ class _Bytes16TimestampUuidKeysMixin(object):
1249
+ @staticmethod
1250
+ def new_key():
1251
+ return os.urandom(20), np.datetime64(time_ns(), "ns"), uuid.uuid4()
1252
+
1253
+ def _serialize_key(self, keys):
1254
+ assert type(keys) == tuple, (
1255
+ 'keys in {}._serialize_key must be a tuple, was: "{}"'.format(
1256
+ self.__class__.__name__, keys
1257
+ )
1258
+ )
1259
+ assert len(keys) == 3
1260
+ key1, key2, key3 = keys
1261
+
1262
+ if not key1:
1263
+ key1 = b"\x00" * 16
1264
+
1265
+ assert key1 is None or (type(key1) == bytes and len(key1) == 16)
1266
+ assert isinstance(key2, np.datetime64)
1267
+ assert isinstance(key3, uuid.UUID)
1268
+
1269
+ return key1 + dt_to_bytes(key2) + key3.bytes
1270
+
1271
+ def _deserialize_key(self, data):
1272
+ assert data is None or (type(data) == bytes and len(data) == 40)
1273
+
1274
+ if data:
1275
+ key1 = data[:16]
1276
+ key2 = bytes_to_dt(data[16:24])
1277
+ key3 = uuid.UUID(bytes=data[24:])
1278
+ else:
1279
+ key1 = b"\x00" * 16
1280
+ key2 = np.datetime64(0, "ns")
1281
+ key3 = uuid.UUID(bytes=b"\x00" * 16)
1282
+
1283
+ return key1, key2, key3
1284
+
1285
+
1286
+ #
1287
+ # Value Types
1288
+ #
1289
+
1290
+
1291
+ class _StringValuesMixin(object):
1292
+ def _serialize_value(self, value):
1293
+ assert value is None or type(value) == str
1294
+
1295
+ if value is not None:
1296
+ return value.encode("utf8")
1297
+ else:
1298
+ return b""
1299
+
1300
+ def _deserialize_value(self, data):
1301
+ if data:
1302
+ return data.decode("utf8")
1303
+ else:
1304
+ return None
1305
+
1306
+
1307
+ class _StringSetValuesMixin(object):
1308
+ def _serialize_value(self, value_set):
1309
+ assert type(value_set) == set
1310
+ for v in value_set:
1311
+ assert v is None or type(v) == str
1312
+
1313
+ return b"\0".join(
1314
+ [(value.encode("utf8") if value else b"") for value in value_set]
1315
+ )
1316
+
1317
+ def _deserialize_value(self, data):
1318
+ assert type(data) == bytes
1319
+ return set([(d.decode("utf8") if d else None) for d in data.split("\0")])
1320
+
1321
+
1322
+ class _OidValuesMixin(object):
1323
+ def _serialize_value(self, value):
1324
+ assert type(value) == int
1325
+ assert value >= 0 and value <= _OidKeysMixin.MAX_OID
1326
+
1327
+ return struct.pack(">Q", value)
1328
+
1329
+ def _deserialize_value(self, data):
1330
+ return struct.unpack(">Q", data)[0]
1331
+
1332
+
1333
+ class _OidSetValuesMixin(object):
1334
+ def _serialize_value(self, value_set):
1335
+ assert type(value_set) == set
1336
+ for value in value_set:
1337
+ assert value >= 0 and value <= _OidKeysMixin.MAX_OID
1338
+ return b"".join([struct.pack(">Q", value) for value in value_set])
1339
+
1340
+ def _deserialize_value(self, data):
1341
+ VLEN = 8
1342
+ assert len(data) % VLEN == 0
1343
+ cnt = len(data) // VLEN
1344
+ return set(
1345
+ [struct.unpack(">Q", data[i : i + VLEN])[0] for i in range(0, cnt, VLEN)]
1346
+ )
1347
+
1348
+
1349
+ class _UuidValuesMixin(object):
1350
+ def _serialize_value(self, value):
1351
+ assert value is None or isinstance(value, uuid.UUID), (
1352
+ 'not a UUID - value "{}"'.format(value)
1353
+ )
1354
+
1355
+ # The UUID as a 16-byte string (containing the six integer fields in big-endian byte order).
1356
+ # https://docs.python.org/3/library/uuid.html#uuid.UUID.bytes
1357
+ if value:
1358
+ return value.bytes
1359
+ else:
1360
+ return b"\x00" * 16
1361
+
1362
+ def _deserialize_value(self, data):
1363
+ assert data is None or type(data) == bytes
1364
+
1365
+ if data:
1366
+ return uuid.UUID(bytes=data)
1367
+ else:
1368
+ return uuid.UUID(bytes=b"\x00" * 16)
1369
+
1370
+
1371
+ class _TimestampValuesMixin(object):
1372
+ def _serialize_value(self, value):
1373
+ assert value is None or isinstance(value, np.datetime64)
1374
+
1375
+ if value:
1376
+ return dt_to_bytes(value)
1377
+ else:
1378
+ return b"\x00" * 8
1379
+
1380
+ def _deserialize_value(self, data):
1381
+ assert data is None or type(data) == bytes and len(data) == 8
1382
+
1383
+ if data:
1384
+ return bytes_to_dt(data)
1385
+ else:
1386
+ return None
1387
+
1388
+
1389
+ class _Bytes32ValuesMixin(object):
1390
+ def _serialize_value(self, value):
1391
+ assert value is None or (type(value) == bytes and len(value) == 32)
1392
+ if value:
1393
+ return value
1394
+ else:
1395
+ return b"\x00" * 32
1396
+
1397
+ def _deserialize_value(self, data):
1398
+ assert data is None or (type(data) == bytes and len(data) == 32)
1399
+ if data:
1400
+ return data
1401
+ else:
1402
+ return None
1403
+
1404
+
1405
+ class _Bytes20ValuesMixin(object):
1406
+ def _serialize_value(self, value):
1407
+ assert value is None or (type(value) == bytes and len(value) == 20)
1408
+ if value:
1409
+ return value
1410
+ else:
1411
+ return b"\x00" * 20
1412
+
1413
+ def _deserialize_value(self, data):
1414
+ assert data is None or (type(data) == bytes and len(data) == 20)
1415
+ if data:
1416
+ return data
1417
+ else:
1418
+ return None
1419
+
1420
+
1421
+ class _Bytes20TimestampValuesMixin(object):
1422
+ def _serialize_value(self, values):
1423
+ assert type(values) == tuple
1424
+ assert len(values) == 2
1425
+ value1, value2 = values
1426
+
1427
+ if not value1:
1428
+ value1 = b"\x00" * 20
1429
+
1430
+ assert value1 is None or (type(value1) == bytes and len(value1) == 20)
1431
+ assert isinstance(value2, np.datetime64)
1432
+
1433
+ return value1 + dt_to_bytes(value2)
1434
+
1435
+ def _deserialize_value(self, data):
1436
+ assert data is None or (type(data) == bytes and len(data) == 28)
1437
+
1438
+ if data:
1439
+ value1 = data[:20]
1440
+ value2 = bytes_to_dt(data[20:])
1441
+ else:
1442
+ value1 = b"\x00" * 20
1443
+ value2 = np.datetime64(0, "ns")
1444
+
1445
+ return value1, value2
1446
+
1447
+
1448
+ class _Bytes16ValuesMixin(object):
1449
+ def _serialize_value(self, value):
1450
+ assert value is None or (type(value) == bytes and len(value) == 16)
1451
+ if value:
1452
+ return value
1453
+ else:
1454
+ return b"\x00" * 16
1455
+
1456
+ def _deserialize_value(self, data):
1457
+ assert data is None or (type(data) == bytes and len(data) == 16)
1458
+ if data:
1459
+ return data
1460
+ else:
1461
+ return None
1462
+
1463
+
1464
+ class _UuidSetValuesMixin(object):
1465
+ def _serialize_value(self, value_set):
1466
+ assert type(value_set) == set
1467
+ return b"".join([value.bytes for value in value_set])
1468
+
1469
+ def _deserialize_value(self, data):
1470
+ VLEN = 16
1471
+ assert len(data) % VLEN == 0
1472
+ cnt = len(data) // VLEN
1473
+ return set([uuid.UUID(bytes=data[i : i + VLEN]) for i in range(0, cnt, VLEN)])
1474
+
1475
+
1476
+ class _JsonValuesMixin(object):
1477
+ def __init__(self, marshal=None, unmarshal=None):
1478
+ self._marshal = None
1479
+ if marshal:
1480
+ self._marshal = marshal
1481
+ else:
1482
+ if hasattr(self, "_zlmdb_marshal"):
1483
+ self._marshal = self._zlmdb_marshal
1484
+ assert self._marshal
1485
+
1486
+ self._unmarshal = None
1487
+ if unmarshal:
1488
+ self._unmarshal = unmarshal
1489
+ else:
1490
+ if hasattr(self, "_zlmdb_unmarshal"):
1491
+ self._unmarshal = self._zlmdb_unmarshal
1492
+ assert self._unmarshal
1493
+
1494
+ def _serialize_value(self, value):
1495
+ return json.dumps(
1496
+ self._marshal(value),
1497
+ separators=(",", ":"),
1498
+ ensure_ascii=False,
1499
+ sort_keys=False,
1500
+ ).encode("utf8")
1501
+
1502
+ def _deserialize_value(self, data):
1503
+ return self._unmarshal(json.loads(data.decode("utf8")))
1504
+
1505
+
1506
+ class _CborValuesMixin(object):
1507
+ def __init__(self, marshal=None, unmarshal=None):
1508
+ self._marshal = None
1509
+ if marshal:
1510
+ self._marshal = marshal
1511
+ else:
1512
+ if hasattr(self, "_zlmdb_marshal"):
1513
+ self._marshal = self._zlmdb_marshal
1514
+ assert self._marshal
1515
+
1516
+ self._unmarshal = None
1517
+ if unmarshal:
1518
+ self._unmarshal = unmarshal
1519
+ else:
1520
+ if hasattr(self, "_zlmdb_unmarshal"):
1521
+ self._unmarshal = self._zlmdb_unmarshal
1522
+ assert self._unmarshal
1523
+
1524
+ def _serialize_value(self, value):
1525
+ return cbor2.dumps(self._marshal(value))
1526
+
1527
+ def _deserialize_value(self, data):
1528
+ return self._unmarshal(cbor2.loads(data))
1529
+
1530
+
1531
+ class _PickleValuesMixin(object):
1532
+ # PROTOCOL = _NATIVE_PICKLE_PROTOCOL
1533
+ PROTOCOL = 2
1534
+
1535
+ def _serialize_value(self, value):
1536
+ return pickle.dumps(value, protocol=self.PROTOCOL)
1537
+
1538
+ def _deserialize_value(self, data):
1539
+ return pickle.loads(data)
1540
+
1541
+
1542
+ class _FlatBuffersValuesMixin(object):
1543
+ def __init__(self, build, cast):
1544
+ self._build = build or self._zlmdb_build
1545
+ self._cast = cast or self._zlmdb_cast
1546
+
1547
+ def _serialize_value(self, value):
1548
+ builder = flatbuffers.Builder(0)
1549
+ obj = self._build(value, builder)
1550
+ builder.Finish(obj)
1551
+ buf = builder.Output()
1552
+ return bytes(buf)
1553
+
1554
+ def _deserialize_value(self, data):
1555
+ return self._cast(data)
1556
+
1557
+
1558
+ class _Pickle5ValuesMixin(object):
1559
+ """
1560
+ Arbitrary Python object values, serialized using Pickle protocol version 5.
1561
+ Protocol version 5 was added in Python 3.8. It adds support for out-of-band
1562
+ data and speedup for in-band data.
1563
+
1564
+ .. seealso::
1565
+
1566
+ * https://docs.python.org/3/library/pickle.html#data-stream-format
1567
+ * https://www.python.org/dev/peps/pep-0574/
1568
+ """
1569
+
1570
+ PROTOCOL = 5
1571
+
1572
+ def _serialize_value(self, value):
1573
+ obj_buffers = []
1574
+ obj_data = pickle.dumps(
1575
+ value, protocol=self.PROTOCOL, buffer_callback=obj_buffers.append
1576
+ )
1577
+ data = []
1578
+ data.append(struct.pack(">I", len(obj_data)))
1579
+ data.append(obj_data)
1580
+ for d in obj_buffers:
1581
+ data.append(struct.pack(">I", len(d.raw())))
1582
+ data.append(d)
1583
+ return b"".join(data)
1584
+
1585
+ def _deserialize_value(self, data):
1586
+ data = memoryview(data)
1587
+ obj_buffers = []
1588
+ obj_len = struct.unpack(">I", data[0:4])[0]
1589
+ obj_data = data[4 : obj_len + 4]
1590
+ i = obj_len + 4
1591
+ while i < len(data):
1592
+ buffer_len = struct.unpack(">I", data[i : i + 4])[0]
1593
+ buffer_data = data[i + 4 : i + 4 + buffer_len]
1594
+ obj_buffers.append(buffer_data)
1595
+ i += 4 + buffer_len
1596
+ return pickle.loads(obj_data, buffers=obj_buffers)