zlmdb 25.10.1__cp311-cp311-macosx_10_9_universal2.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-311-darwin.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,92 @@
|
|
|
1
|
+
from __future__ import absolute_import
|
|
2
|
+
from __future__ import with_statement
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
from . import testlib
|
|
6
|
+
import struct
|
|
7
|
+
from .testlib import KEYSFIXED, ITEMS_MULTI_FIXEDKEY
|
|
8
|
+
from .testlib import putBigDataMultiFixed
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GetMultiTestBase(unittest.TestCase):
|
|
12
|
+
def tearDown(self):
|
|
13
|
+
testlib.cleanup()
|
|
14
|
+
|
|
15
|
+
def setUp(self, dupsort=None, dupfixed=None):
|
|
16
|
+
self.db_key = "testdb".encode("utf-8")
|
|
17
|
+
self.path, self.env = testlib.temp_env(max_dbs=1)
|
|
18
|
+
self.txn = self.env.begin(write=True)
|
|
19
|
+
self.db = self.env.open_db(
|
|
20
|
+
key=self.db_key, txn=self.txn, dupsort=dupsort, dupfixed=dupfixed
|
|
21
|
+
)
|
|
22
|
+
putBigDataMultiFixed(self.txn, db=self.db)
|
|
23
|
+
self.c = self.txn.cursor(db=self.db)
|
|
24
|
+
|
|
25
|
+
def matchList(self, ls_a, ls_b):
|
|
26
|
+
return (not (ls_a or ls_b)) or (
|
|
27
|
+
ls_a and ls_b and all(map(lambda x, y: x == y, ls_a, ls_b))
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class GetMultiTestNoDupsortNoDupfixed(GetMultiTestBase):
|
|
32
|
+
ITEMS2_MULTI_NODUP = ITEMS_MULTI_FIXEDKEY[1::2]
|
|
33
|
+
|
|
34
|
+
def setUp(self, dupsort=False, dupfixed=False):
|
|
35
|
+
super(GetMultiTestNoDupsortNoDupfixed, self).setUp(
|
|
36
|
+
dupsort=dupsort, dupfixed=dupfixed
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def testGetMulti(self):
|
|
40
|
+
test_list = self.c.getmulti(KEYSFIXED)
|
|
41
|
+
self.assertEqual(self.matchList(test_list, self.ITEMS2_MULTI_NODUP), True)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class GetMultiTestDupsortNoDupfixed(GetMultiTestBase):
|
|
45
|
+
def setUp(self, dupsort=True, dupfixed=False):
|
|
46
|
+
super(GetMultiTestDupsortNoDupfixed, self).setUp(
|
|
47
|
+
dupsort=dupsort, dupfixed=dupfixed
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def testGetMulti(self):
|
|
51
|
+
test_list = self.c.getmulti(KEYSFIXED, dupdata=True)
|
|
52
|
+
self.assertEqual(self.matchList(test_list, ITEMS_MULTI_FIXEDKEY), True)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class GetMultiTestDupsortDupfixed(GetMultiTestBase):
|
|
56
|
+
def setUp(self, dupsort=True, dupfixed=True):
|
|
57
|
+
super(GetMultiTestDupsortDupfixed, self).setUp(
|
|
58
|
+
dupsort=dupsort, dupfixed=dupfixed
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def testGetMulti(self):
|
|
62
|
+
test_list = self.c.getmulti(KEYSFIXED, dupdata=True, dupfixed_bytes=1)
|
|
63
|
+
self.assertEqual(self.matchList(test_list, ITEMS_MULTI_FIXEDKEY), True)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class GetMultiTestDupsortDupfixedKeyfixed(GetMultiTestBase):
|
|
67
|
+
def setUp(self, dupsort=True, dupfixed=True):
|
|
68
|
+
super(GetMultiTestDupsortDupfixedKeyfixed, self).setUp(
|
|
69
|
+
dupsort=dupsort, dupfixed=dupfixed
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def testGetMulti(self):
|
|
73
|
+
val_bytes = 1
|
|
74
|
+
arr = bytearray(
|
|
75
|
+
self.c.getmulti(
|
|
76
|
+
KEYSFIXED, dupdata=True, dupfixed_bytes=val_bytes, keyfixed=True
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
asserts = []
|
|
80
|
+
for i, kv in enumerate(ITEMS_MULTI_FIXEDKEY):
|
|
81
|
+
key, val = kv
|
|
82
|
+
asserts.extend(
|
|
83
|
+
(
|
|
84
|
+
struct.pack("b", arr[i * 2]) == key,
|
|
85
|
+
struct.pack("b", arr[i * 2 + 1]) == val,
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
self.assertEqual(all(asserts), True)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
unittest.main()
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2013 The py-lmdb authors, all rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
|
6
|
+
# modification, are permitted only as authorized by the OpenLDAP
|
|
7
|
+
# Public License.
|
|
8
|
+
#
|
|
9
|
+
# A copy of this license is available in the file LICENSE in the
|
|
10
|
+
# top-level directory of the distribution or, alternatively, at
|
|
11
|
+
# <http://www.OpenLDAP.org/license.html>.
|
|
12
|
+
#
|
|
13
|
+
# OpenLDAP is a registered trademark of the OpenLDAP Foundation.
|
|
14
|
+
#
|
|
15
|
+
# Individual files and/or contributed packages may be copyright by
|
|
16
|
+
# other parties and/or subject to additional restrictions.
|
|
17
|
+
#
|
|
18
|
+
# This work also contains materials derived from public sources.
|
|
19
|
+
#
|
|
20
|
+
# Additional information about OpenLDAP can be obtained at
|
|
21
|
+
# <http://www.openldap.org/>.
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
# test delete(dupdata)
|
|
25
|
+
|
|
26
|
+
from __future__ import absolute_import
|
|
27
|
+
from __future__ import with_statement
|
|
28
|
+
import unittest
|
|
29
|
+
|
|
30
|
+
from . import testlib
|
|
31
|
+
from .testlib import B
|
|
32
|
+
from .testlib import BT
|
|
33
|
+
from .testlib import KEYS, ITEMS, KEYS2, ITEMS2
|
|
34
|
+
from .testlib import putData, putBigData
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class IterationTestBase(unittest.TestCase):
|
|
38
|
+
def tearDown(self):
|
|
39
|
+
testlib.cleanup()
|
|
40
|
+
|
|
41
|
+
def setUp(self):
|
|
42
|
+
self.path, self.env = testlib.temp_env() # creates 10 databases
|
|
43
|
+
self.txn = self.env.begin(write=True)
|
|
44
|
+
putData(self.txn)
|
|
45
|
+
self.c = self.txn.cursor()
|
|
46
|
+
self.empty_entry = (B(""), B(""))
|
|
47
|
+
|
|
48
|
+
def matchList(self, ls_a, ls_b):
|
|
49
|
+
return all(map(lambda x, y: x == y, ls_a, ls_b))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class IterationTestBase2(unittest.TestCase):
|
|
53
|
+
"""This puts more data than its predecessor"""
|
|
54
|
+
|
|
55
|
+
def tearDown(self):
|
|
56
|
+
testlib.cleanup()
|
|
57
|
+
|
|
58
|
+
def setUp(self):
|
|
59
|
+
self.path, self.env = testlib.temp_env() # creates 10 databases
|
|
60
|
+
self.txn = self.env.begin(write=True)
|
|
61
|
+
putBigData(self.txn) # HERE!
|
|
62
|
+
self.c = self.txn.cursor()
|
|
63
|
+
self.empty_entry = ("", "")
|
|
64
|
+
|
|
65
|
+
def matchList(self, ls_a, ls_b):
|
|
66
|
+
return all(map(lambda x, y: x == y, ls_a, ls_b))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class IterationTest(IterationTestBase):
|
|
70
|
+
def testFromStart(self):
|
|
71
|
+
# From start
|
|
72
|
+
self.c.first()
|
|
73
|
+
self.assertEqual(self.c.key(), KEYS[0]) # start of db
|
|
74
|
+
test_list = [i for i in iter(self.c)]
|
|
75
|
+
self.assertEqual(self.matchList(test_list, ITEMS), True)
|
|
76
|
+
self.assertEqual(self.c.item(), self.empty_entry) # end of db
|
|
77
|
+
|
|
78
|
+
def testFromStartWithIternext(self):
|
|
79
|
+
# From start with iternext
|
|
80
|
+
self.c.first()
|
|
81
|
+
self.assertEqual(self.c.key(), KEYS[0]) # start of db
|
|
82
|
+
test_list = [i for i in self.c.iternext()]
|
|
83
|
+
# remaining elements in db
|
|
84
|
+
self.assertEqual(self.matchList(test_list, ITEMS), True)
|
|
85
|
+
self.assertEqual(self.c.item(), self.empty_entry) # end of db
|
|
86
|
+
|
|
87
|
+
def testFromStartWithNext(self):
|
|
88
|
+
# From start with next
|
|
89
|
+
self.c.first()
|
|
90
|
+
self.assertEqual(self.c.key(), KEYS[0]) # start of db
|
|
91
|
+
test_list = []
|
|
92
|
+
while 1:
|
|
93
|
+
test_list.append(self.c.item())
|
|
94
|
+
if not self.c.next():
|
|
95
|
+
break
|
|
96
|
+
self.assertEqual(self.matchList(test_list, ITEMS), True)
|
|
97
|
+
|
|
98
|
+
def testFromExistentKeySetKey(self):
|
|
99
|
+
self.c.first()
|
|
100
|
+
self.c.set_key(KEYS[1])
|
|
101
|
+
self.assertEqual(self.c.key(), KEYS[1])
|
|
102
|
+
test_list = [i for i in self.c.iternext()]
|
|
103
|
+
self.assertEqual(self.matchList(test_list, ITEMS[1:]), True)
|
|
104
|
+
|
|
105
|
+
def testFromExistentKeySetRange(self):
|
|
106
|
+
self.c.first()
|
|
107
|
+
self.c.set_range(KEYS[1])
|
|
108
|
+
self.assertEqual(self.c.key(), KEYS[1])
|
|
109
|
+
test_list = [i for i in self.c.iternext()]
|
|
110
|
+
self.assertEqual(self.matchList(test_list, ITEMS[1:]), True)
|
|
111
|
+
|
|
112
|
+
def testFromNonExistentKeySetRange(self):
|
|
113
|
+
self.c.first()
|
|
114
|
+
self.c.set_range(B("c"))
|
|
115
|
+
self.assertEqual(self.c.key(), B("d"))
|
|
116
|
+
test_list = [i for i in self.c.iternext()]
|
|
117
|
+
test_items = [i for i in ITEMS if i[0] > B("c")]
|
|
118
|
+
self.assertEqual(self.matchList(test_list, test_items), True)
|
|
119
|
+
|
|
120
|
+
def testFromLastKey(self):
|
|
121
|
+
self.c.last()
|
|
122
|
+
self.assertEqual(self.c.key(), KEYS[-1])
|
|
123
|
+
test_list = [i for i in self.c.iternext()]
|
|
124
|
+
self.assertEqual(self.matchList(test_list, ITEMS[-1:]), True)
|
|
125
|
+
|
|
126
|
+
def testFromNonExistentKeyPastEnd(self):
|
|
127
|
+
self.c.last()
|
|
128
|
+
self.assertEqual(self.c.key(), KEYS[-1])
|
|
129
|
+
# next() fails, leaving iterator in an unpositioned state.
|
|
130
|
+
self.c.next()
|
|
131
|
+
self.assertEqual(self.c.item(), self.empty_entry)
|
|
132
|
+
# iternext() from an unpositioned state proceeds from start of DB.
|
|
133
|
+
test_list = list(self.c.iternext())
|
|
134
|
+
self.assertEqual(test_list, ITEMS)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class ReverseIterationTest(IterationTestBase):
|
|
138
|
+
def testFromStartRev(self):
|
|
139
|
+
# From start
|
|
140
|
+
self.c.first()
|
|
141
|
+
self.assertEqual(self.c.key(), KEYS[0]) # start of db
|
|
142
|
+
test_list = [i for i in self.c.iterprev()]
|
|
143
|
+
self.assertEqual(self.matchList(test_list, ITEMS[:1][::-1]), True)
|
|
144
|
+
self.assertEqual(self.c.item(), self.empty_entry) # very start of db
|
|
145
|
+
|
|
146
|
+
def testFromExistentKeySetKeyRev(self):
|
|
147
|
+
self.c.first()
|
|
148
|
+
self.c.set_key(KEYS[2])
|
|
149
|
+
self.assertEqual(self.c.key(), KEYS[2])
|
|
150
|
+
test_list = [i for i in self.c.iterprev()]
|
|
151
|
+
self.assertEqual(self.matchList(test_list, ITEMS[:3][::-1]), True)
|
|
152
|
+
|
|
153
|
+
def testFromExistentKeySetRangeRev(self):
|
|
154
|
+
self.c.first()
|
|
155
|
+
self.c.set_range(KEYS[2])
|
|
156
|
+
self.assertEqual(self.c.key(), KEYS[2])
|
|
157
|
+
test_list = [i for i in self.c.iterprev()]
|
|
158
|
+
self.assertEqual(self.matchList(test_list, ITEMS[:3][::-1]), True)
|
|
159
|
+
|
|
160
|
+
def testFromNonExistentKeySetRangeRev(self):
|
|
161
|
+
self.c.first()
|
|
162
|
+
self.c.set_range(B("c"))
|
|
163
|
+
self.assertEqual(self.c.key(), B("d"))
|
|
164
|
+
test_list = [i for i in self.c.iterprev()]
|
|
165
|
+
test_items = [i for i in ITEMS if i[0] <= B("d")]
|
|
166
|
+
test_items = test_items[::-1]
|
|
167
|
+
self.assertEqual(self.matchList(test_list, test_items), True)
|
|
168
|
+
|
|
169
|
+
def testFromLastKeyRev(self):
|
|
170
|
+
self.c.last()
|
|
171
|
+
self.assertEqual(self.c.key(), KEYS[-1])
|
|
172
|
+
test_list = [i for i in self.c.iterprev()]
|
|
173
|
+
self.assertEqual(self.matchList(test_list, ITEMS[::-1]), True)
|
|
174
|
+
|
|
175
|
+
def testFromLastKeyWithPrevRev(self):
|
|
176
|
+
self.c.last()
|
|
177
|
+
self.assertEqual(self.c.key(), KEYS[-1]) # end of db
|
|
178
|
+
test_list = []
|
|
179
|
+
while 1:
|
|
180
|
+
test_list.append(self.c.item())
|
|
181
|
+
if not self.c.prev():
|
|
182
|
+
break
|
|
183
|
+
self.assertEqual(self.matchList(test_list, ITEMS[::-1]), True)
|
|
184
|
+
|
|
185
|
+
def testFromNonExistentKeyPastEndRev(self):
|
|
186
|
+
self.c.first()
|
|
187
|
+
self.assertEqual(self.c.key(), KEYS[0])
|
|
188
|
+
# prev() fails, leaving iterator in an unpositioned state.
|
|
189
|
+
self.c.prev()
|
|
190
|
+
self.assertEqual(self.c.item(), self.empty_entry)
|
|
191
|
+
# iterprev() from an unpositioned state proceeds from end of DB.
|
|
192
|
+
test_list = list(self.c.iterprev())
|
|
193
|
+
self.assertEqual(test_list, ITEMS[::-1])
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class IterationTestWithDupsBase(unittest.TestCase):
|
|
197
|
+
def tearDown(self):
|
|
198
|
+
testlib.cleanup()
|
|
199
|
+
|
|
200
|
+
def setUp(self):
|
|
201
|
+
self.path, self.env = testlib.temp_env()
|
|
202
|
+
db = self.env.open_db(B("db1"), dupsort=True)
|
|
203
|
+
self.txn = self.env.begin(db, write=True)
|
|
204
|
+
for _ in range(2):
|
|
205
|
+
putData(self.txn)
|
|
206
|
+
self.c = self.txn.cursor()
|
|
207
|
+
self.empty_entry = ("", "")
|
|
208
|
+
|
|
209
|
+
def matchList(self, ls_a, ls_b):
|
|
210
|
+
return all(map(lambda x, y: x == y, ls_a, ls_b))
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class IterationTestWithDups(IterationTestWithDupsBase):
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class SeekIterationTest(IterationTestBase2):
|
|
218
|
+
def testForwardIterationSeek(self):
|
|
219
|
+
self.c.first()
|
|
220
|
+
test_list = []
|
|
221
|
+
for i in self.c.iternext():
|
|
222
|
+
test_list.append(i)
|
|
223
|
+
# skips d and e
|
|
224
|
+
if self.c.key() == B("baa"):
|
|
225
|
+
self.c.set_key(B("e"))
|
|
226
|
+
test_item = [i for i in ITEMS2 if i[0] not in (B("d"), B("e"))]
|
|
227
|
+
self.assertEqual(test_list, test_item)
|
|
228
|
+
|
|
229
|
+
def testPutDuringIteration(self):
|
|
230
|
+
self.c.first()
|
|
231
|
+
test_list = []
|
|
232
|
+
c = self.txn.cursor()
|
|
233
|
+
for i in c.iternext():
|
|
234
|
+
test_list.append(i)
|
|
235
|
+
# adds 'i' upon seeing 'e'
|
|
236
|
+
if c.key() == B("e"):
|
|
237
|
+
self.c.put(B("i"), B(""))
|
|
238
|
+
test_item = ITEMS2 + [(B("i"), B(""))]
|
|
239
|
+
self.assertEqual(test_list, test_item)
|
|
240
|
+
|
|
241
|
+
def testDeleteDuringIteration(self):
|
|
242
|
+
self.c.first()
|
|
243
|
+
test_list = []
|
|
244
|
+
for i in self.c.iternext():
|
|
245
|
+
# deletes 'e' upon seeing it
|
|
246
|
+
if self.c.key() == B("e"):
|
|
247
|
+
# Causes 'e' to be deleted, and advances cursor to next
|
|
248
|
+
# element.
|
|
249
|
+
self.c.delete()
|
|
250
|
+
i = self.c.item()
|
|
251
|
+
test_list.append(i)
|
|
252
|
+
|
|
253
|
+
test_item = [i for i in ITEMS2 if i[0] != B("e")]
|
|
254
|
+
self.assertEqual(test_list, test_item)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
if __name__ == "__main__":
|
|
258
|
+
unittest.main()
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2013 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
|
+
from __future__ import absolute_import
|
|
24
|
+
import unittest
|
|
25
|
+
|
|
26
|
+
import zlmdb.lmdb as lmdb
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PackageExportsTest(unittest.TestCase):
|
|
30
|
+
"""
|
|
31
|
+
Ensure the list of exported names matches a predefined list. Designed to
|
|
32
|
+
ensure future interface changes to cffi.py and cpython.c don't break
|
|
33
|
+
consistency of "from lmdb import *".
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def test_exports(self):
|
|
37
|
+
assert sorted(lmdb.__all__) == [
|
|
38
|
+
"BadDbiError",
|
|
39
|
+
"BadRslotError",
|
|
40
|
+
"BadTxnError",
|
|
41
|
+
"BadValsizeError",
|
|
42
|
+
"CorruptedError",
|
|
43
|
+
"Cursor",
|
|
44
|
+
"CursorFullError",
|
|
45
|
+
"DbsFullError",
|
|
46
|
+
"DiskError",
|
|
47
|
+
"Environment",
|
|
48
|
+
"Error",
|
|
49
|
+
"IncompatibleError",
|
|
50
|
+
"InvalidError",
|
|
51
|
+
"InvalidParameterError",
|
|
52
|
+
"KeyExistsError",
|
|
53
|
+
"LockError",
|
|
54
|
+
"MapFullError",
|
|
55
|
+
"MapResizedError",
|
|
56
|
+
"MemoryError",
|
|
57
|
+
"NotFoundError",
|
|
58
|
+
"PageFullError",
|
|
59
|
+
"PageNotFoundError",
|
|
60
|
+
"PanicError",
|
|
61
|
+
"ReadersFullError",
|
|
62
|
+
"ReadonlyError",
|
|
63
|
+
"TlsFullError",
|
|
64
|
+
"Transaction",
|
|
65
|
+
"TxnFullError",
|
|
66
|
+
"VersionMismatchError",
|
|
67
|
+
"_Database",
|
|
68
|
+
"enable_drop_gil",
|
|
69
|
+
"version",
|
|
70
|
+
]
|
|
@@ -0,0 +1,188 @@
|
|
|
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 random
|
|
28
|
+
import os
|
|
29
|
+
import zlmdb.lmdb as lmdb
|
|
30
|
+
import struct
|
|
31
|
+
import platform
|
|
32
|
+
|
|
33
|
+
import pytest
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
from tempfile import TemporaryDirectory
|
|
37
|
+
except ImportError:
|
|
38
|
+
from backports.tempfile import TemporaryDirectory # type:ignore
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_lmdb_create():
|
|
42
|
+
"""
|
|
43
|
+
Test creation of LMDB database.
|
|
44
|
+
"""
|
|
45
|
+
with TemporaryDirectory() as dbpath:
|
|
46
|
+
env = lmdb.open(dbpath)
|
|
47
|
+
|
|
48
|
+
with env.begin() as txn:
|
|
49
|
+
assert txn.id() == 0
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_lmdb_insert_empty_key_raises():
|
|
53
|
+
"""
|
|
54
|
+
Test that LMDB raises on inserting record with empty (bytes) key.
|
|
55
|
+
"""
|
|
56
|
+
with TemporaryDirectory() as dbpath:
|
|
57
|
+
env = lmdb.open(dbpath)
|
|
58
|
+
|
|
59
|
+
with env.begin(write=True) as txn:
|
|
60
|
+
key = b""
|
|
61
|
+
value = random.randint(0, 2**32 - 1)
|
|
62
|
+
data = struct.pack("<L", value)
|
|
63
|
+
with pytest.raises(lmdb.BadValsizeError):
|
|
64
|
+
txn.put(key, data)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@pytest.mark.skipif(
|
|
68
|
+
platform.python_implementation() == "PyPy",
|
|
69
|
+
reason="behavioral difference on pypy (does not raise, but runs into traceback)",
|
|
70
|
+
)
|
|
71
|
+
def test_lmdb_insert_null_key_raises():
|
|
72
|
+
"""
|
|
73
|
+
Test that LMDB raises on inserting record with NULL key.
|
|
74
|
+
"""
|
|
75
|
+
with TemporaryDirectory() as dbpath:
|
|
76
|
+
env = lmdb.open(dbpath)
|
|
77
|
+
|
|
78
|
+
with env.begin(write=True) as txn:
|
|
79
|
+
key = None
|
|
80
|
+
value = random.randint(0, 2**32 - 1)
|
|
81
|
+
data = struct.pack("<L", value)
|
|
82
|
+
with pytest.raises(lmdb.BadValsizeError):
|
|
83
|
+
txn.put(key, data)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_lmdb_insert_empty_value_ok():
|
|
87
|
+
"""
|
|
88
|
+
Test that LMDB allows to insert record with empty (bytes) value.
|
|
89
|
+
"""
|
|
90
|
+
with TemporaryDirectory() as dbpath:
|
|
91
|
+
env = lmdb.open(dbpath)
|
|
92
|
+
|
|
93
|
+
with env.begin(write=True) as txn:
|
|
94
|
+
key = b"foo"
|
|
95
|
+
data = b""
|
|
96
|
+
txn.put(key, data)
|
|
97
|
+
|
|
98
|
+
with env.begin() as txn:
|
|
99
|
+
cursor = txn.cursor()
|
|
100
|
+
assert cursor.first()
|
|
101
|
+
assert cursor.value() == b""
|
|
102
|
+
total = 1
|
|
103
|
+
while cursor.next():
|
|
104
|
+
total += 1
|
|
105
|
+
assert total == 1
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@pytest.mark.skipif(
|
|
109
|
+
platform.python_implementation() == "PyPy",
|
|
110
|
+
reason="behavioral difference on pypy (does not raise, but runs into traceback)",
|
|
111
|
+
)
|
|
112
|
+
def test_lmdb_insert_null_value_ok():
|
|
113
|
+
"""
|
|
114
|
+
Test that LMDB allows to insert record with NULL value and
|
|
115
|
+
returns b'' value when retrieving the record (!).
|
|
116
|
+
"""
|
|
117
|
+
with TemporaryDirectory() as dbpath:
|
|
118
|
+
env = lmdb.open(dbpath)
|
|
119
|
+
|
|
120
|
+
with env.begin(write=True) as txn:
|
|
121
|
+
key = b"foo"
|
|
122
|
+
data = None
|
|
123
|
+
txn.put(key, data)
|
|
124
|
+
|
|
125
|
+
with env.begin() as txn:
|
|
126
|
+
cursor = txn.cursor()
|
|
127
|
+
assert cursor.first()
|
|
128
|
+
assert cursor.value() == b""
|
|
129
|
+
total = 1
|
|
130
|
+
while cursor.next():
|
|
131
|
+
total += 1
|
|
132
|
+
assert total == 1
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def test_lmdb_insert():
|
|
136
|
+
"""
|
|
137
|
+
Test inserting and retrieving a couple of records.
|
|
138
|
+
"""
|
|
139
|
+
with TemporaryDirectory() as dbpath:
|
|
140
|
+
n = 100
|
|
141
|
+
total1 = 0
|
|
142
|
+
env = lmdb.open(dbpath)
|
|
143
|
+
|
|
144
|
+
with env.begin(write=True) as txn:
|
|
145
|
+
for i in range(n):
|
|
146
|
+
key = "key-{}".format(i).encode("utf8")
|
|
147
|
+
value = random.randint(0, 2**32 - 1)
|
|
148
|
+
total1 += value
|
|
149
|
+
data = struct.pack("<L", value)
|
|
150
|
+
txn.put(key, data)
|
|
151
|
+
|
|
152
|
+
with env.begin() as txn:
|
|
153
|
+
cursor = txn.cursor()
|
|
154
|
+
assert cursor.first()
|
|
155
|
+
|
|
156
|
+
count = 1
|
|
157
|
+
total2 = struct.unpack("<L", cursor.value())[0]
|
|
158
|
+
|
|
159
|
+
while cursor.next():
|
|
160
|
+
count += 1
|
|
161
|
+
total2 += struct.unpack("<L", cursor.value())[0]
|
|
162
|
+
|
|
163
|
+
assert count == n
|
|
164
|
+
assert total1 == total2
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_lmdb_delete():
|
|
168
|
+
"""
|
|
169
|
+
Test inserting and deleting again a couple of records.
|
|
170
|
+
"""
|
|
171
|
+
with TemporaryDirectory() as dbpath:
|
|
172
|
+
n = 100
|
|
173
|
+
env = lmdb.open(dbpath)
|
|
174
|
+
|
|
175
|
+
with env.begin(write=True) as txn:
|
|
176
|
+
for i in range(n):
|
|
177
|
+
key = "key-{}".format(i).encode("utf8")
|
|
178
|
+
value = os.urandom(16)
|
|
179
|
+
txn.put(key, value)
|
|
180
|
+
|
|
181
|
+
with env.begin(write=True) as txn:
|
|
182
|
+
for i in range(n):
|
|
183
|
+
key = "key-{}".format(i).encode("utf8")
|
|
184
|
+
assert txn.delete(key)
|
|
185
|
+
|
|
186
|
+
with env.begin() as txn:
|
|
187
|
+
cursor = txn.cursor()
|
|
188
|
+
assert not cursor.first()
|