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.
- flatbuffers/__init__.py +19 -0
- flatbuffers/_version.py +17 -0
- flatbuffers/builder.py +776 -0
- flatbuffers/compat.py +86 -0
- flatbuffers/encode.py +42 -0
- flatbuffers/flexbuffers.py +1527 -0
- flatbuffers/number_types.py +181 -0
- flatbuffers/packer.py +42 -0
- flatbuffers/reflection/AdvancedFeatures.py +10 -0
- flatbuffers/reflection/BaseType.py +24 -0
- flatbuffers/reflection/Enum.py +169 -0
- flatbuffers/reflection/EnumVal.py +96 -0
- flatbuffers/reflection/Field.py +208 -0
- flatbuffers/reflection/KeyValue.py +56 -0
- flatbuffers/reflection/Object.py +175 -0
- flatbuffers/reflection/RPCCall.py +131 -0
- flatbuffers/reflection/Schema.py +206 -0
- flatbuffers/reflection/SchemaFile.py +77 -0
- flatbuffers/reflection/Service.py +145 -0
- flatbuffers/reflection/Type.py +98 -0
- flatbuffers/reflection/__init__.py +0 -0
- flatbuffers/table.py +129 -0
- flatbuffers/util.py +43 -0
- zlmdb/__init__.py +312 -0
- zlmdb/_database.py +990 -0
- zlmdb/_errors.py +31 -0
- zlmdb/_meta.py +27 -0
- zlmdb/_pmap.py +1667 -0
- zlmdb/_schema.py +137 -0
- zlmdb/_transaction.py +181 -0
- zlmdb/_types.py +1596 -0
- zlmdb/_version.py +27 -0
- zlmdb/cli.py +41 -0
- zlmdb/flatbuffers/__init__.py +5 -0
- zlmdb/flatbuffers/reflection/AdvancedFeatures.py +10 -0
- zlmdb/flatbuffers/reflection/BaseType.py +25 -0
- zlmdb/flatbuffers/reflection/Enum.py +252 -0
- zlmdb/flatbuffers/reflection/EnumVal.py +144 -0
- zlmdb/flatbuffers/reflection/Field.py +325 -0
- zlmdb/flatbuffers/reflection/KeyValue.py +84 -0
- zlmdb/flatbuffers/reflection/Object.py +260 -0
- zlmdb/flatbuffers/reflection/RPCCall.py +195 -0
- zlmdb/flatbuffers/reflection/Schema.py +301 -0
- zlmdb/flatbuffers/reflection/SchemaFile.py +112 -0
- zlmdb/flatbuffers/reflection/Service.py +213 -0
- zlmdb/flatbuffers/reflection/Type.py +148 -0
- zlmdb/flatbuffers/reflection/__init__.py +0 -0
- zlmdb/flatbuffers/reflection.fbs +152 -0
- zlmdb/lmdb/__init__.py +37 -0
- zlmdb/lmdb/__main__.py +25 -0
- zlmdb/lmdb/_config.py +10 -0
- zlmdb/lmdb/_lmdb_cffi.cpython-313-x86_64-linux-gnu.so +0 -0
- zlmdb/lmdb/cffi.py +2606 -0
- zlmdb/lmdb/tool.py +670 -0
- zlmdb/tests/lmdb/__init__.py +0 -0
- zlmdb/tests/lmdb/address_book.py +287 -0
- zlmdb/tests/lmdb/crash_test.py +339 -0
- zlmdb/tests/lmdb/cursor_test.py +333 -0
- zlmdb/tests/lmdb/env_test.py +919 -0
- zlmdb/tests/lmdb/getmulti_test.py +92 -0
- zlmdb/tests/lmdb/iteration_test.py +258 -0
- zlmdb/tests/lmdb/package_test.py +70 -0
- zlmdb/tests/lmdb/test_lmdb.py +188 -0
- zlmdb/tests/lmdb/testlib.py +185 -0
- zlmdb/tests/lmdb/tool_test.py +60 -0
- zlmdb/tests/lmdb/txn_test.py +575 -0
- zlmdb/tests/orm/MNodeLog.py +853 -0
- zlmdb/tests/orm/__init__.py +0 -0
- zlmdb/tests/orm/_schema_fbs.py +215 -0
- zlmdb/tests/orm/_schema_mnode_log.py +1201 -0
- zlmdb/tests/orm/_schema_py2.py +250 -0
- zlmdb/tests/orm/_schema_py3.py +307 -0
- zlmdb/tests/orm/_test_flatbuffers.py +144 -0
- zlmdb/tests/orm/_test_serialization.py +144 -0
- zlmdb/tests/orm/test_basic.py +217 -0
- zlmdb/tests/orm/test_etcd.py +275 -0
- zlmdb/tests/orm/test_pmap_indexes.py +466 -0
- zlmdb/tests/orm/test_pmap_types.py +90 -0
- zlmdb/tests/orm/test_pmaps.py +295 -0
- zlmdb/tests/orm/test_select.py +619 -0
- zlmdb-25.10.1.dist-info/METADATA +264 -0
- zlmdb-25.10.1.dist-info/RECORD +87 -0
- zlmdb-25.10.1.dist-info/WHEEL +5 -0
- zlmdb-25.10.1.dist-info/entry_points.txt +2 -0
- zlmdb-25.10.1.dist-info/licenses/LICENSE +137 -0
- zlmdb-25.10.1.dist-info/licenses/NOTICE +41 -0
- zlmdb-25.10.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2013-2021 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
|
+
# test delete(dupdata)
|
|
24
|
+
|
|
25
|
+
from __future__ import absolute_import
|
|
26
|
+
from __future__ import with_statement
|
|
27
|
+
import sys
|
|
28
|
+
import unittest
|
|
29
|
+
|
|
30
|
+
import zlmdb.lmdb as lmdb
|
|
31
|
+
|
|
32
|
+
from . import testlib
|
|
33
|
+
from .testlib import B
|
|
34
|
+
from .testlib import BT
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ContextManagerTest(unittest.TestCase):
|
|
38
|
+
def tearDown(self):
|
|
39
|
+
testlib.cleanup()
|
|
40
|
+
|
|
41
|
+
def test_ok(self):
|
|
42
|
+
path, env = testlib.temp_env()
|
|
43
|
+
txn = env.begin(write=True)
|
|
44
|
+
with txn.cursor() as curs:
|
|
45
|
+
curs.put(B("foo"), B("123"))
|
|
46
|
+
self.assertRaises(Exception, lambda: curs.get(B("foo")))
|
|
47
|
+
|
|
48
|
+
def test_crash(self):
|
|
49
|
+
path, env = testlib.temp_env()
|
|
50
|
+
txn = env.begin(write=True)
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
with txn.cursor() as curs:
|
|
54
|
+
curs.put(123, 123)
|
|
55
|
+
except Exception:
|
|
56
|
+
pass
|
|
57
|
+
self.assertRaises(Exception, lambda: curs.get(B("foo")))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class CursorTestBase(unittest.TestCase):
|
|
61
|
+
def tearDown(self):
|
|
62
|
+
testlib.cleanup()
|
|
63
|
+
|
|
64
|
+
def setUp(self):
|
|
65
|
+
self.path, self.env = testlib.temp_env()
|
|
66
|
+
self.txn = self.env.begin(write=True)
|
|
67
|
+
self.c = self.txn.cursor()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class CursorTest(CursorTestBase):
|
|
71
|
+
def testKeyValueItemEmpty(self):
|
|
72
|
+
self.assertEqual(B(""), self.c.key())
|
|
73
|
+
self.assertEqual(B(""), self.c.value())
|
|
74
|
+
self.assertEqual(BT("", ""), self.c.item())
|
|
75
|
+
|
|
76
|
+
def testFirstLastEmpty(self):
|
|
77
|
+
self.assertEqual(False, self.c.first())
|
|
78
|
+
self.assertEqual(False, self.c.last())
|
|
79
|
+
|
|
80
|
+
def testFirstFilled(self):
|
|
81
|
+
testlib.putData(self.txn)
|
|
82
|
+
self.assertEqual(True, self.c.first())
|
|
83
|
+
self.assertEqual(testlib.ITEMS[0], self.c.item())
|
|
84
|
+
|
|
85
|
+
def testLastFilled(self):
|
|
86
|
+
testlib.putData(self.txn)
|
|
87
|
+
self.assertEqual(True, self.c.last())
|
|
88
|
+
self.assertEqual(testlib.ITEMS[-1], self.c.item())
|
|
89
|
+
|
|
90
|
+
def testSetKey(self):
|
|
91
|
+
self.assertRaises(Exception, (lambda: self.c.set_key(B(""))))
|
|
92
|
+
self.assertEqual(False, self.c.set_key(B("missing")))
|
|
93
|
+
testlib.putData(self.txn)
|
|
94
|
+
self.assertEqual(True, self.c.set_key(B("b")))
|
|
95
|
+
self.assertEqual(False, self.c.set_key(B("ba")))
|
|
96
|
+
|
|
97
|
+
def testSetRange(self):
|
|
98
|
+
self.assertEqual(False, self.c.set_range(B("x")))
|
|
99
|
+
testlib.putData(self.txn)
|
|
100
|
+
self.assertEqual(False, self.c.set_range(B("x")))
|
|
101
|
+
self.assertEqual(True, self.c.set_range(B("a")))
|
|
102
|
+
self.assertEqual(B("a"), self.c.key())
|
|
103
|
+
self.assertEqual(True, self.c.set_range(B("ba")))
|
|
104
|
+
self.assertEqual(B("baa"), self.c.key())
|
|
105
|
+
self.c.set_range(B(""))
|
|
106
|
+
self.assertEqual(B("a"), self.c.key())
|
|
107
|
+
|
|
108
|
+
def testDeleteEmpty(self):
|
|
109
|
+
self.assertEqual(False, self.c.delete())
|
|
110
|
+
|
|
111
|
+
def testDeleteFirst(self):
|
|
112
|
+
testlib.putData(self.txn)
|
|
113
|
+
self.assertEqual(False, self.c.delete())
|
|
114
|
+
self.c.first()
|
|
115
|
+
self.assertEqual(BT("a", ""), self.c.item())
|
|
116
|
+
self.assertEqual(True, self.c.delete())
|
|
117
|
+
self.assertEqual(BT("b", ""), self.c.item())
|
|
118
|
+
self.assertEqual(True, self.c.delete())
|
|
119
|
+
self.assertEqual(BT("baa", ""), self.c.item())
|
|
120
|
+
self.assertEqual(True, self.c.delete())
|
|
121
|
+
self.assertEqual(BT("d", ""), self.c.item())
|
|
122
|
+
self.assertEqual(True, self.c.delete())
|
|
123
|
+
self.assertEqual(BT("", ""), self.c.item())
|
|
124
|
+
self.assertEqual(False, self.c.delete())
|
|
125
|
+
self.assertEqual(BT("", ""), self.c.item())
|
|
126
|
+
|
|
127
|
+
def testDeleteLast(self):
|
|
128
|
+
testlib.putData(self.txn)
|
|
129
|
+
self.assertEqual(True, self.c.last())
|
|
130
|
+
self.assertEqual(BT("d", ""), self.c.item())
|
|
131
|
+
self.assertEqual(True, self.c.delete())
|
|
132
|
+
self.assertEqual(BT("", ""), self.c.item())
|
|
133
|
+
self.assertEqual(False, self.c.delete())
|
|
134
|
+
self.assertEqual(BT("", ""), self.c.item())
|
|
135
|
+
|
|
136
|
+
def testCount(self):
|
|
137
|
+
self.assertRaises(Exception, (lambda: self.c.count()))
|
|
138
|
+
testlib.putData(self.txn)
|
|
139
|
+
self.c.first()
|
|
140
|
+
# TODO: complete dup key support.
|
|
141
|
+
# self.assertEqual(1, self.c.count())
|
|
142
|
+
|
|
143
|
+
def testPut(self):
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class CursorTest2(unittest.TestCase):
|
|
148
|
+
def tearDown(self):
|
|
149
|
+
testlib.cleanup()
|
|
150
|
+
|
|
151
|
+
def setUp(self):
|
|
152
|
+
self.path, self.env = testlib.temp_env()
|
|
153
|
+
self.db = self.env.open_db(b"foo", dupsort=True)
|
|
154
|
+
self.txn = self.env.begin(write=True, db=self.db)
|
|
155
|
+
self.c = self.txn.cursor()
|
|
156
|
+
|
|
157
|
+
def testIterWithDeletes(self):
|
|
158
|
+
"""A problem identified in LMDB 0.9.27"""
|
|
159
|
+
self.c.put(b"\x00\x01", b"hehe", dupdata=True)
|
|
160
|
+
self.c.put(b"\x00\x02", b"haha", dupdata=True)
|
|
161
|
+
self.c.set_key(b"\x00\x02")
|
|
162
|
+
it = self.c.iternext()
|
|
163
|
+
self.assertEqual((b"\x00\x02", b"haha"), next(it))
|
|
164
|
+
self.txn.delete(b"\x00\x01", b"hehe", db=self.db)
|
|
165
|
+
self.assertRaises(StopIteration, next, it)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class PutmultiTest(CursorTestBase):
|
|
169
|
+
def test_empty_seq(self):
|
|
170
|
+
consumed, added = self.c.putmulti(())
|
|
171
|
+
assert consumed == added == 0
|
|
172
|
+
|
|
173
|
+
def test_2list(self):
|
|
174
|
+
l = [BT("a", ""), BT("a", "")]
|
|
175
|
+
consumed, added = self.c.putmulti(l)
|
|
176
|
+
assert consumed == added == 2
|
|
177
|
+
|
|
178
|
+
li = iter(l)
|
|
179
|
+
consumed, added = self.c.putmulti(li)
|
|
180
|
+
assert consumed == added == 2
|
|
181
|
+
|
|
182
|
+
def test_2list_preserve(self):
|
|
183
|
+
l = [BT("a", ""), BT("a", "")]
|
|
184
|
+
consumed, added = self.c.putmulti(l, overwrite=False)
|
|
185
|
+
assert consumed == 2
|
|
186
|
+
assert added == 1
|
|
187
|
+
|
|
188
|
+
assert self.c.set_key(B("a"))
|
|
189
|
+
assert self.c.delete()
|
|
190
|
+
|
|
191
|
+
li = iter(l)
|
|
192
|
+
consumed, added = self.c.putmulti(li, overwrite=False)
|
|
193
|
+
assert consumed == 2
|
|
194
|
+
assert added == 1
|
|
195
|
+
|
|
196
|
+
def test_bad_seq1(self):
|
|
197
|
+
self.assertRaises(Exception, lambda: self.c.putmulti(range(2)))
|
|
198
|
+
|
|
199
|
+
def test_dupsort(self):
|
|
200
|
+
_, env = testlib.temp_env()
|
|
201
|
+
db1 = env.open_db(B("db1"), dupsort=True)
|
|
202
|
+
txn = env.begin(write=True, db=db1)
|
|
203
|
+
with txn.cursor() as c:
|
|
204
|
+
tups = [BT("a", "value1"), BT("b", "value1"), BT("b", "value2")]
|
|
205
|
+
assert (3, 3) == c.putmulti(tups)
|
|
206
|
+
|
|
207
|
+
def test_dupsort_putmulti_append(self):
|
|
208
|
+
_, env = testlib.temp_env()
|
|
209
|
+
db1 = env.open_db(B("db1"), dupsort=True)
|
|
210
|
+
txn = env.begin(write=True, db=db1)
|
|
211
|
+
with txn.cursor() as c:
|
|
212
|
+
tups = [BT("a", "value1"), BT("b", "value1"), BT("b", "value2")]
|
|
213
|
+
assert (3, 3) == c.putmulti(tups, append=True)
|
|
214
|
+
|
|
215
|
+
def test_dupsort_put_append(self):
|
|
216
|
+
_, env = testlib.temp_env()
|
|
217
|
+
db1 = env.open_db(B("db1"), dupsort=True)
|
|
218
|
+
txn = env.begin(write=True, db=db1)
|
|
219
|
+
with txn.cursor() as c:
|
|
220
|
+
assert c.put(B("a"), B("value1"), append=True)
|
|
221
|
+
assert c.put(B("b"), B("value1"), append=True)
|
|
222
|
+
assert c.put(B("b"), B("value2"), append=True)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class ReplaceTest(CursorTestBase):
|
|
226
|
+
def test_replace(self):
|
|
227
|
+
assert None is self.c.replace(B("a"), B(""))
|
|
228
|
+
assert B("") == self.c.replace(B("a"), B("x"))
|
|
229
|
+
assert B("x") == self.c.replace(B("a"), B("y"))
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class ContextManagerTest2(CursorTestBase):
|
|
233
|
+
def test_enter(self):
|
|
234
|
+
with self.c as c:
|
|
235
|
+
assert c is self.c
|
|
236
|
+
c.put(B("a"), B("a"))
|
|
237
|
+
assert c.get(B("a")) == B("a")
|
|
238
|
+
self.assertRaises(Exception, lambda: c.get(B("a")))
|
|
239
|
+
|
|
240
|
+
def test_exit_success(self):
|
|
241
|
+
with self.txn.cursor() as c:
|
|
242
|
+
c.put(B("a"), B("a"))
|
|
243
|
+
self.assertRaises(Exception, lambda: c.get(B("a")))
|
|
244
|
+
|
|
245
|
+
def test_exit_failure(self):
|
|
246
|
+
try:
|
|
247
|
+
with self.txn.cursor() as c:
|
|
248
|
+
c.put(B("a"), B("a"))
|
|
249
|
+
raise ValueError
|
|
250
|
+
except ValueError:
|
|
251
|
+
pass
|
|
252
|
+
self.assertRaises(Exception, lambda: c.get(B("a")))
|
|
253
|
+
|
|
254
|
+
def test_close(self):
|
|
255
|
+
self.c.close()
|
|
256
|
+
self.assertRaises(Exception, lambda: c.get(B("a")))
|
|
257
|
+
|
|
258
|
+
def test_double_close(self):
|
|
259
|
+
self.c.close()
|
|
260
|
+
self.c.close()
|
|
261
|
+
self.assertRaises(Exception, lambda: self.c.put(B("a"), B("a")))
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
GiB = 1024 * 1024 * 1024
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class PreloadTest(CursorTestBase):
|
|
268
|
+
def setUp(self, redo=False):
|
|
269
|
+
env_args = {"writemap": True, "map_size": GiB}
|
|
270
|
+
if not redo:
|
|
271
|
+
self.path, self.env = testlib.temp_env(**env_args)
|
|
272
|
+
else:
|
|
273
|
+
self.path, self.env = testlib.temp_env(path=self.path, **env_args)
|
|
274
|
+
self.txn = self.env.begin(write=True)
|
|
275
|
+
self.c = self.txn.cursor()
|
|
276
|
+
|
|
277
|
+
@unittest.skipIf(not sys.platform.startswith("linux"), "test only works on Linux")
|
|
278
|
+
def test_preload(self):
|
|
279
|
+
"""
|
|
280
|
+
Test that reading just the key doesn't prefault the value contents, but
|
|
281
|
+
reading the data does.
|
|
282
|
+
"""
|
|
283
|
+
|
|
284
|
+
import resource
|
|
285
|
+
|
|
286
|
+
self.c.put(B("a"), B("a") * (256 * 1024 * 1024))
|
|
287
|
+
self.txn.commit()
|
|
288
|
+
self.env.close()
|
|
289
|
+
# Just reading the data is obviously going to fault the value in. The
|
|
290
|
+
# point is to fault it in while the GIL is unlocked. We use the buffers
|
|
291
|
+
# API so that we're not actually copying the data in. This doesn't
|
|
292
|
+
# actually show that we're prefaulting with the GIL unlocked, but it
|
|
293
|
+
# does prove we prefault at all, and in 2 correct places.
|
|
294
|
+
self.path, self.env = testlib.temp_env(path=self.path, writemap=True)
|
|
295
|
+
self.txn = self.env.begin(write=True, buffers=True)
|
|
296
|
+
self.c = self.txn.cursor()
|
|
297
|
+
minflts_before = resource.getrusage(resource.RUSAGE_SELF)[6]
|
|
298
|
+
self.c.set_key(B("a"))
|
|
299
|
+
assert bytes(self.c.key()) == B("a")
|
|
300
|
+
minflts_after_key = resource.getrusage(resource.RUSAGE_SELF)[6]
|
|
301
|
+
|
|
302
|
+
self.c.value()
|
|
303
|
+
minflts_after_value = resource.getrusage(resource.RUSAGE_SELF)[6]
|
|
304
|
+
|
|
305
|
+
epsilon = 60
|
|
306
|
+
|
|
307
|
+
# Setting the position doesn't prefault the data
|
|
308
|
+
assert minflts_after_key - minflts_before < epsilon
|
|
309
|
+
|
|
310
|
+
# Getting the value does prefault the data, even if we only get it by pointer
|
|
311
|
+
assert minflts_after_value - minflts_after_key > 1000
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class CursorReadOnlyTest(unittest.TestCase):
|
|
315
|
+
def tearDown(self):
|
|
316
|
+
testlib.cleanup()
|
|
317
|
+
|
|
318
|
+
def test_cursor_readonly(self):
|
|
319
|
+
"""
|
|
320
|
+
Tests whether you can open a cursor on a sub-db at all in a read-only environment.
|
|
321
|
+
"""
|
|
322
|
+
path, env = testlib.temp_env(max_dbs=10)
|
|
323
|
+
env.open_db(b"foo")
|
|
324
|
+
env.close()
|
|
325
|
+
with lmdb.open(path, max_dbs=10, readonly=True) as env:
|
|
326
|
+
db2 = env.open_db(b"foo")
|
|
327
|
+
with env.begin(db=db2) as txn:
|
|
328
|
+
with txn.cursor(db=db2):
|
|
329
|
+
pass
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
if __name__ == "__main__":
|
|
333
|
+
unittest.main()
|