zlmdb 25.10.1__cp313-cp313-macosx_15_0_arm64.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-darwin.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
@@ -0,0 +1,575 @@
1
+ #
2
+ # Copyright 2013-2025 The py-lmdb authors, all rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted only as authorized by the OpenLDAP
6
+ # Public License.
7
+ #
8
+ # A copy of this license is available in the file LICENSE in the
9
+ # top-level directory of the distribution or, alternatively, at
10
+ # <http://www.OpenLDAP.org/license.html>.
11
+ #
12
+ # OpenLDAP is a registered trademark of the OpenLDAP Foundation.
13
+ #
14
+ # Individual files and/or contributed packages may be copyright by
15
+ # other parties and/or subject to additional restrictions.
16
+ #
17
+ # This work also contains materials derived from public sources.
18
+ #
19
+ # Additional information about OpenLDAP can be obtained at
20
+ # <http://www.openldap.org/>.
21
+ #
22
+
23
+ import os
24
+ import sys
25
+ import struct
26
+ import unittest
27
+ import weakref
28
+
29
+ from . import testlib
30
+ from .testlib import B
31
+ from .testlib import INT_TYPES
32
+ from .testlib import BytesType
33
+
34
+ import zlmdb.lmdb as lmdb
35
+
36
+
37
+ UINT_0001 = struct.pack("I", 1)
38
+ UINT_0002 = struct.pack("I", 2)
39
+ ULONG_0001 = struct.pack("L", 1) # L != size_t
40
+ ULONG_0002 = struct.pack("L", 2) # L != size_t
41
+
42
+
43
+ class InitTest(testlib.LmdbTest):
44
+ def tearDown(self):
45
+ testlib.cleanup()
46
+
47
+ def test_closed(self):
48
+ _, env = testlib.temp_env()
49
+ env.close()
50
+ self.assertRaises(Exception, lambda: lmdb.Transaction(env))
51
+
52
+ def test_readonly(self):
53
+ _, env = testlib.temp_env()
54
+ txn = lmdb.Transaction(env)
55
+ # Read txn can't write.
56
+ self.assertRaises(lmdb.ReadonlyError, lambda: txn.put(B("a"), B("")))
57
+ txn.abort()
58
+
59
+ def test_begin_write(self):
60
+ _, env = testlib.temp_env()
61
+ txn = lmdb.Transaction(env, write=True)
62
+ # Write txn can write.
63
+ assert txn.put(B("a"), B(""))
64
+ txn.commit()
65
+
66
+ def test_bind_db(self):
67
+ _, env = testlib.temp_env()
68
+ main = env.open_db(None)
69
+ sub = env.open_db(B("db1"))
70
+
71
+ txn = lmdb.Transaction(env, write=True, db=sub)
72
+ assert txn.put(B("b"), B("")) # -> sub
73
+ assert txn.put(B("a"), B(""), db=main) # -> main
74
+ txn.commit()
75
+
76
+ txn = lmdb.Transaction(env)
77
+ assert txn.get(B("a")) == B("")
78
+ assert txn.get(B("b")) is None
79
+ assert txn.get(B("a"), db=sub) is None
80
+ assert txn.get(B("b"), db=sub) == B("")
81
+ txn.abort()
82
+
83
+ def test_bind_db_methods(self):
84
+ _, env = testlib.temp_env()
85
+ maindb = env.open_db(None)
86
+ db1 = env.open_db(B("d1"))
87
+ txn = lmdb.Transaction(env, write=True, db=db1)
88
+ assert txn.put(B("a"), B("d1"))
89
+ assert txn.get(B("a"), db=db1) == B("d1")
90
+ assert txn.get(B("a"), db=maindb) is None
91
+ assert txn.replace(B("a"), B("d11")) == B("d1")
92
+ assert txn.pop(B("a")) == B("d11")
93
+ assert txn.put(B("a"), B("main"), db=maindb, overwrite=False)
94
+ assert not txn.delete(B("a"))
95
+ txn.abort()
96
+
97
+ def test_parent_readonly(self):
98
+ _, env = testlib.temp_env()
99
+ parent = lmdb.Transaction(env)
100
+ # Nonsensical.
101
+ self.assertRaises(
102
+ lmdb.InvalidParameterError, lambda: lmdb.Transaction(env, parent=parent)
103
+ )
104
+
105
+ def test_parent(self):
106
+ _, env = testlib.temp_env()
107
+ parent = lmdb.Transaction(env, write=True)
108
+ parent.put(B("a"), B("a"))
109
+
110
+ child = lmdb.Transaction(env, write=True, parent=parent)
111
+ assert child.get(B("a")) == B("a")
112
+ assert child.put(B("a"), B("b"))
113
+ child.abort()
114
+
115
+ # put() should have rolled back
116
+ assert parent.get(B("a")) == B("a")
117
+
118
+ child = lmdb.Transaction(env, write=True, parent=parent)
119
+ assert child.put(B("a"), B("b"))
120
+ child.commit()
121
+
122
+ # put() should be visible
123
+ assert parent.get(B("a")) == B("b")
124
+
125
+ def test_buffers(self):
126
+ _, env = testlib.temp_env()
127
+ txn = lmdb.Transaction(env, write=True, buffers=True)
128
+ assert txn.put(B("a"), B("a"))
129
+ b = txn.get(B("a"))
130
+ assert b is not None
131
+ assert len(b) == 1
132
+ assert not isinstance(b, type(B("")))
133
+ txn.commit()
134
+
135
+ txn = lmdb.Transaction(env, buffers=False)
136
+ b = txn.get(B("a"))
137
+ assert b is not None
138
+ assert len(b) == 1
139
+ assert isinstance(b, type(B("")))
140
+ txn.abort()
141
+
142
+ @unittest.skipIf(sys.platform.startswith("win"), "No fork on Windows")
143
+ def test_cached_txn_across_fork(self):
144
+ _, env = testlib.temp_env()
145
+ txn = env.begin(write=False)
146
+ del txn
147
+
148
+ if os.fork() != 0:
149
+ # I am the parent
150
+ os.wait() # Wait for child to finish
151
+ txn = env.begin(write=False) # Used to raise MDB_BAD_RSLOT (#346)
152
+
153
+ @unittest.skipIf(sys.platform.startswith("win"), "No fork on Windows")
154
+ def test_child_deleting_transaction(self):
155
+ _, env = testlib.temp_env()
156
+ with env.begin(write=True) as txn:
157
+ txn.put(b"a", b"foo")
158
+ txn = env.begin()
159
+
160
+ r = env.readers()
161
+ assert r != "(no active readers)\n"
162
+
163
+ pid = os.fork()
164
+ if pid == 0:
165
+ del txn # I am the child
166
+ os._exit(0)
167
+
168
+ os.waitpid(pid, 0)
169
+ # Make sure my child didn't mess with my environment
170
+ r2 = env.readers()
171
+ assert r2 == r, "%r != %r" % (r2, r)
172
+ assert txn.get(b"a") == b"foo"
173
+ del txn
174
+
175
+
176
+ class ContextManagerTest(unittest.TestCase):
177
+ def tearDown(self):
178
+ testlib.cleanup()
179
+
180
+ def test_ok(self):
181
+ path, env = testlib.temp_env()
182
+ txn = env.begin(write=True)
183
+ with txn as txn_:
184
+ assert txn is txn_
185
+ txn.put(B("foo"), B("123"))
186
+
187
+ self.assertRaises(Exception, lambda: txn.get(B("foo")))
188
+ with env.begin() as txn:
189
+ assert txn.get(B("foo")) == B("123")
190
+
191
+ def test_crash(self):
192
+ path, env = testlib.temp_env()
193
+ txn = env.begin(write=True)
194
+
195
+ try:
196
+ with txn as txn_:
197
+ txn.put(B("foo"), B("123"))
198
+ txn.put(123, 123)
199
+ except:
200
+ pass
201
+
202
+ self.assertRaises(Exception, lambda: txn.get(B("foo")))
203
+ with env.begin() as txn:
204
+ assert txn.get(B("foo")) is None
205
+
206
+
207
+ class IdTest(unittest.TestCase):
208
+ def tearDown(self):
209
+ testlib.cleanup()
210
+
211
+ def test_readonly_new(self):
212
+ _, env = testlib.temp_env()
213
+ with env.begin() as txn:
214
+ assert txn.id() == 0
215
+
216
+ def test_write_new(self):
217
+ _, env = testlib.temp_env()
218
+ with env.begin(write=True) as txn:
219
+ assert txn.id() == 1
220
+
221
+ def test_readonly_after_write(self):
222
+ _, env = testlib.temp_env()
223
+ with env.begin(write=True) as txn:
224
+ txn.put(B("a"), B("a"))
225
+ with env.begin() as txn:
226
+ assert txn.id() == 1
227
+
228
+ def test_invalid_txn(self):
229
+ _, env = testlib.temp_env()
230
+ txn = env.begin()
231
+ txn.abort()
232
+ self.assertRaises(Exception, lambda: txn.id())
233
+
234
+
235
+ class StatTest(unittest.TestCase):
236
+ def tearDown(self):
237
+ testlib.cleanup()
238
+
239
+ def test_stat(self):
240
+ _, env = testlib.temp_env()
241
+ db1 = env.open_db(B("db1"))
242
+ db2 = env.open_db(B("db2"))
243
+
244
+ txn = lmdb.Transaction(env)
245
+ for db in db1, db2:
246
+ stat = txn.stat(db)
247
+ for k in "psize", "depth", "branch_pages", "overflow_pages", "entries":
248
+ assert isinstance(stat[k], INT_TYPES), k
249
+ assert stat[k] >= 0
250
+ assert stat["entries"] == 0
251
+
252
+ txn = lmdb.Transaction(env, write=True)
253
+ txn.put(B("a"), B("b"), db=db1)
254
+ txn.commit()
255
+
256
+ txn = lmdb.Transaction(env)
257
+ stat = txn.stat(db1)
258
+ assert stat["entries"] == 1
259
+
260
+ stat = txn.stat(db2)
261
+ assert stat["entries"] == 0
262
+
263
+ txn.abort()
264
+ self.assertRaises(Exception, lambda: env.stat(db1))
265
+ env.close()
266
+ self.assertRaises(Exception, lambda: env.stat(db1))
267
+
268
+
269
+ class DropTest(unittest.TestCase):
270
+ def tearDown(self):
271
+ testlib.cleanup()
272
+
273
+ def test_empty(self):
274
+ _, env = testlib.temp_env()
275
+ db1 = env.open_db(B("db1"))
276
+ txn = env.begin(write=True)
277
+ txn.put(B("a"), B("a"), db=db1)
278
+ assert txn.get(B("a"), db=db1) == B("a")
279
+ txn.drop(db1, False)
280
+ assert txn.get(B("a")) is None
281
+ txn.drop(db1, False) # should succeed.
282
+ assert txn.get(B("a")) is None
283
+
284
+ def test_delete(self):
285
+ _, env = testlib.temp_env()
286
+ db1 = env.open_db(B("db1"))
287
+ txn = env.begin(write=True)
288
+ txn.put(B("a"), B("a"), db=db1)
289
+ txn.drop(db1)
290
+ self.assertRaises(lmdb.InvalidParameterError, lambda: txn.get(B("a"), db=db1))
291
+ self.assertRaises(lmdb.InvalidParameterError, lambda: txn.drop(db1))
292
+
293
+ def test_double_delete(self):
294
+ _, env = testlib.temp_env()
295
+
296
+ db1 = env.open_db(B("db1"))
297
+ txn = env.begin(write=True, db=db1)
298
+ txn.put(B("a"), B("a"), db=db1)
299
+ txn.drop(db1)
300
+ self.assertRaises(lmdb.InvalidParameterError, lambda: txn.get(B("a"), db=db1))
301
+ self.assertRaises(lmdb.InvalidParameterError, lambda: txn.drop(db1))
302
+ txn.commit()
303
+
304
+ db1 = env.open_db(B("db1"))
305
+ txn = env.begin(write=True, db=db1)
306
+ txn.put(B("a"), B("a"), db=db1)
307
+ txn.drop(db1)
308
+ self.assertRaises(lmdb.InvalidParameterError, lambda: txn.get(B("a"), db=db1))
309
+ self.assertRaises(lmdb.InvalidParameterError, lambda: txn.drop(db1))
310
+ txn.commit()
311
+
312
+
313
+ class CommitTest(unittest.TestCase):
314
+ def tearDown(self):
315
+ testlib.cleanup()
316
+
317
+ def test_bad_txn(self):
318
+ _, env = testlib.temp_env()
319
+ txn = env.begin()
320
+ txn.abort()
321
+ self.assertRaises(Exception, lambda: txn.commit())
322
+
323
+ def test_bad_env(self):
324
+ _, env = testlib.temp_env()
325
+ txn = env.begin()
326
+ env.close()
327
+ self.assertRaises(Exception, lambda: txn.commit())
328
+
329
+ def test_commit_ro(self):
330
+ _, env = testlib.temp_env()
331
+ txn = env.begin()
332
+ txn.commit()
333
+ self.assertRaises(Exception, lambda: txn.commit())
334
+
335
+ def test_commit_rw(self):
336
+ _, env = testlib.temp_env()
337
+ txn = env.begin(write=True)
338
+ assert txn.put(B("a"), B("a"))
339
+ txn.commit()
340
+ self.assertRaises(Exception, lambda: txn.commit())
341
+ txn = env.begin()
342
+ assert txn.get(B("a")) == B("a")
343
+ txn.abort()
344
+
345
+
346
+ class AbortTest(unittest.TestCase):
347
+ def tearDown(self):
348
+ testlib.cleanup()
349
+
350
+ def test_abort_ro(self):
351
+ _, env = testlib.temp_env()
352
+ txn = env.begin()
353
+ assert txn.get(B("a")) is None
354
+ txn.abort()
355
+ self.assertRaises(Exception, lambda: txn.get(B("a")))
356
+ env.close()
357
+ self.assertRaises(Exception, lambda: txn.get(B("a")))
358
+
359
+ def test_abort_rw(self):
360
+ _, env = testlib.temp_env()
361
+ txn = env.begin(write=True)
362
+ assert txn.put(B("a"), B("a"))
363
+ txn.abort()
364
+ txn = env.begin()
365
+ assert txn.get(B("a")) is None
366
+
367
+
368
+ class GetTest(unittest.TestCase):
369
+ def tearDown(self):
370
+ testlib.cleanup()
371
+
372
+ def test_bad_txn(self):
373
+ _, env = testlib.temp_env()
374
+ txn = env.begin()
375
+ txn.abort()
376
+ self.assertRaises(Exception, lambda: txn.get(B("a")))
377
+
378
+ def test_bad_env(self):
379
+ _, env = testlib.temp_env()
380
+ txn = env.begin()
381
+ env.close()
382
+ self.assertRaises(Exception, lambda: txn.get(B("a")))
383
+
384
+ def test_missing(self):
385
+ _, env = testlib.temp_env()
386
+ txn = env.begin()
387
+ assert txn.get(B("a")) is None
388
+ assert txn.get(B("a"), default="default") == "default"
389
+
390
+ def test_empty_key(self):
391
+ _, env = testlib.temp_env()
392
+ txn = env.begin()
393
+ self.assertRaises(lmdb.BadValsizeError, lambda: txn.get(B("")))
394
+
395
+ def test_db(self):
396
+ _, env = testlib.temp_env()
397
+ maindb = env.open_db(None)
398
+ db1 = env.open_db(B("db1"))
399
+
400
+ txn = env.begin()
401
+ assert txn.get(B("a"), db=db1) is None
402
+ txn.abort()
403
+
404
+ txn = env.begin(write=True)
405
+ txn.put(B("a"), B("a"), db=db1)
406
+ txn.commit()
407
+
408
+ txn = env.begin()
409
+ assert txn.get(B("a")) is None
410
+ txn.abort()
411
+
412
+ txn = env.begin(db=db1)
413
+ assert txn.get(B("a")) == B("a")
414
+ assert txn.get(B("a"), db=maindb) is None
415
+
416
+ def test_buffers_no(self):
417
+ _, env = testlib.temp_env()
418
+ txn = env.begin(write=True)
419
+ assert txn.put(B("a"), B("a"))
420
+ assert type(txn.get(B("a"))) is BytesType
421
+
422
+ def test_buffers_yes(self):
423
+ _, env = testlib.temp_env()
424
+ txn = env.begin(write=True, buffers=True)
425
+ assert txn.put(B("a"), B("a"))
426
+ assert type(txn.get(B("a"))) is not BytesType
427
+
428
+ def test_dupsort(self):
429
+ _, env = testlib.temp_env()
430
+ db1 = env.open_db(B("db1"), dupsort=True)
431
+ txn = env.begin(write=True, db=db1)
432
+ assert txn.put(B("a"), B("a"))
433
+ assert txn.put(B("a"), B("b"))
434
+ assert txn.get(B("a")) == B("a")
435
+
436
+ def test_integerkey(self):
437
+ _, env = testlib.temp_env()
438
+ db1 = env.open_db(B("db1"), integerkey=True)
439
+ txn = env.begin(write=True, db=db1)
440
+ assert txn.put(UINT_0001, B("a"))
441
+ assert txn.put(UINT_0002, B("b"))
442
+ assert txn.get(UINT_0001) == B("a")
443
+ assert txn.get(UINT_0002) == B("b")
444
+
445
+ def test_integerdup(self):
446
+ _, env = testlib.temp_env()
447
+ db1 = env.open_db(B("db1"), dupsort=True, integerdup=True)
448
+ txn = env.begin(write=True, db=db1)
449
+ assert txn.put(UINT_0001, UINT_0002)
450
+ assert txn.put(UINT_0001, UINT_0001)
451
+ assert txn.get(UINT_0001) == UINT_0001
452
+
453
+ def test_dupfixed(self):
454
+ _, env = testlib.temp_env()
455
+ db1 = env.open_db(B("db1"), dupsort=True, dupfixed=True)
456
+ txn = env.begin(write=True, db=db1)
457
+ assert txn.put(B("a"), B("a"))
458
+ assert txn.put(B("a"), B("b"))
459
+ assert txn.get(B("a")) == B("a")
460
+
461
+
462
+ class PutTest(unittest.TestCase):
463
+ def tearDown(self):
464
+ testlib.cleanup()
465
+
466
+ def test_bad_txn(self):
467
+ _, env = testlib.temp_env()
468
+ txn = env.begin(write=True)
469
+ txn.abort()
470
+ self.assertRaises(Exception, lambda: txn.put(B("a"), B("a")))
471
+
472
+ def test_bad_env(self):
473
+ _, env = testlib.temp_env()
474
+ txn = env.begin(write=True)
475
+ env.close()
476
+ self.assertRaises(Exception, lambda: txn.put(B("a"), B("a")))
477
+
478
+ def test_ro_txn(self):
479
+ _, env = testlib.temp_env()
480
+ txn = env.begin()
481
+ self.assertRaises(lmdb.ReadonlyError, lambda: txn.put(B("a"), B("a")))
482
+
483
+ def test_empty_key_value(self):
484
+ _, env = testlib.temp_env()
485
+ txn = env.begin(write=True)
486
+ self.assertRaises(lmdb.BadValsizeError, lambda: txn.put(B(""), B("a")))
487
+
488
+ def test_dupsort(self):
489
+ _, env = testlib.temp_env()
490
+
491
+ def test_dupdata_no_dupsort(self):
492
+ _, env = testlib.temp_env()
493
+ txn = env.begin(write=True)
494
+ assert txn.put(B("a"), B("a"), dupdata=True)
495
+ assert txn.put(B("a"), B("b"), dupdata=True)
496
+ txn.get(B("a"))
497
+
498
+
499
+ class ReplaceTest(unittest.TestCase):
500
+ def tearDown(self):
501
+ testlib.cleanup()
502
+
503
+ def test_bad_txn(self):
504
+ _, env = testlib.temp_env()
505
+ txn = env.begin(write=True)
506
+ txn.abort()
507
+ self.assertRaises(Exception, lambda: txn.replace(B("a"), B("a")))
508
+
509
+ def test_bad_env(self):
510
+ _, env = testlib.temp_env()
511
+ txn = env.begin(write=True)
512
+ env.close()
513
+ self.assertRaises(Exception, lambda: txn.replace(B("a"), B("a")))
514
+
515
+ def test_ro_txn(self):
516
+ _, env = testlib.temp_env()
517
+ txn = env.begin()
518
+ self.assertRaises(lmdb.ReadonlyError, lambda: txn.replace(B("a"), B("a")))
519
+
520
+ def test_empty_key_value(self):
521
+ _, env = testlib.temp_env()
522
+ txn = env.begin(write=True)
523
+ self.assertRaises(lmdb.BadValsizeError, lambda: txn.replace(B(""), B("a")))
524
+
525
+ def test_dupsort_noexist(self):
526
+ _, env = testlib.temp_env()
527
+ db = env.open_db(B("db1"), dupsort=True)
528
+ txn = env.begin(write=True, db=db)
529
+ assert None is txn.replace(B("a"), B("x"))
530
+ assert B("x") == txn.replace(B("a"), B("y"))
531
+ assert B("y") == txn.replace(B("a"), B("z"))
532
+ cur = txn.cursor()
533
+ assert cur.set_key(B("a"))
534
+ assert [B("z")] == list(cur.iternext_dup())
535
+
536
+ def test_dupsort_del_none(self):
537
+ _, env = testlib.temp_env()
538
+ db = env.open_db(B("db1"), dupsort=True)
539
+ with env.begin(write=True, db=db) as txn:
540
+ assert txn.put(B("a"), B("a"))
541
+ assert txn.put(B("a"), B("b"))
542
+ cur = txn.cursor()
543
+ assert cur.set_key(B("a"))
544
+ assert [B("a"), B("b")] == list(cur.iternext_dup())
545
+ assert txn.delete(B("a"), None)
546
+
547
+ def test_dupdata_no_dupsort(self):
548
+ _, env = testlib.temp_env()
549
+ txn = env.begin(write=True)
550
+ assert txn.put(B("a"), B("a"), dupdata=True)
551
+ assert txn.put(B("a"), B("b"), dupdata=True)
552
+ txn.get(B("a"))
553
+
554
+
555
+ class LeakTest(unittest.TestCase):
556
+ def tearDown(self):
557
+ testlib.cleanup()
558
+
559
+ def test_open_close(self):
560
+ temp_dir = testlib.temp_dir()
561
+ env = lmdb.open(temp_dir)
562
+ with env.begin() as txn:
563
+ pass
564
+ env.close()
565
+ r1 = weakref.ref(env)
566
+ r2 = weakref.ref(txn)
567
+ env = None
568
+ txn = None
569
+ testlib.debug_collect()
570
+ assert r1() is None
571
+ assert r2() is None
572
+
573
+
574
+ if __name__ == "__main__":
575
+ unittest.main()