Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 64ce505

Browse files
committed
Make bsddb use bytes as keys and values. Add StringKeys
and StringValues classes. Fix test suite.
1 parent 33d2689 commit 64ce505

4 files changed

Lines changed: 183 additions & 51 deletions

File tree

Doc/lib/libbsddb.tex

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,17 @@ \section{\module{bsddb} ---
9393
interpretation.
9494
\end{funcdesc}
9595

96+
\begin{classdesc}{StringKeys}{db}
97+
Wrapper class around a DB object that supports string keys
98+
(rather than bytes). All keys are encoded as UTF-8, then passed
99+
to the underlying object. \versionadded{3.0}
100+
\end{classdesc}
101+
102+
\begin{classdesc}{StringValues}{db}
103+
Wrapper class around a DB object that supports string values
104+
(rather than bytes). All values are encoded as UTF-8, then passed
105+
to the underlying object. \versionadded{3.0}
106+
\end{classdesc}
96107

97108
\begin{seealso}
98109
\seemodule{dbhash}{DBM-style interface to the \module{bsddb}}

Lib/bsddb/__init__.py

Lines changed: 136 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,9 @@
6464

6565
#----------------------------------------------------------------------
6666

67-
import sys, os
68-
69-
# for backwards compatibility with python versions older than 2.3, the
70-
# iterator interface is dynamically defined and added using a mixin
71-
# class. old python can't tokenize it due to the yield keyword.
72-
if sys.version >= '2.3':
73-
import UserDict
74-
from weakref import ref
75-
exec("""
67+
import sys, os, UserDict
68+
from weakref import ref
69+
7670
class _iter_mixin(UserDict.DictMixin):
7771
def _make_iter_cursor(self):
7872
cur = _DeadlockWrap(self.db.cursor)
@@ -145,10 +139,6 @@ def iteritems(self):
145139
except _bsddb.DBCursorClosedError:
146140
# the database was modified during iteration. abort.
147141
return
148-
""")
149-
else:
150-
class _iter_mixin: pass
151-
152142

153143
class _DBWithCursor(_iter_mixin):
154144
"""
@@ -290,6 +280,138 @@ def sync(self):
290280
self._checkOpen()
291281
return _DeadlockWrap(self.db.sync)
292282

283+
class _ExposedProperties:
284+
@property
285+
def _cursor_refs(self):
286+
return self.db._cursor_refs
287+
288+
class StringKeys(UserDict.DictMixin, _ExposedProperties):
289+
"""Wrapper around DB object that automatically encodes
290+
all keys as UTF-8; the keys must be strings."""
291+
292+
def __init__(self, db):
293+
self.db = db
294+
295+
def __len__(self):
296+
return len(self.db)
297+
298+
def __getitem__(self, key):
299+
return self.db[key.encode("utf-8")]
300+
301+
def __setitem__(self, key, value):
302+
self.db[key.encode("utf-8")] = value
303+
304+
def __delitem__(self, key):
305+
del self.db[key.encode("utf-8")]
306+
307+
def __iter__(self):
308+
for k in self.db:
309+
yield k.decode("utf-8")
310+
311+
def close(self):
312+
self.db.close()
313+
314+
def keys(self):
315+
for k in self.db.keys():
316+
yield k.decode("utf-8")
317+
318+
def has_key(self, key):
319+
return self.db.has_key(key.encode("utf-8"))
320+
321+
__contains__ = has_key
322+
323+
def values(self):
324+
return self.db.values()
325+
326+
def items(self):
327+
for k,v in self.db.items():
328+
yield k.decode("utf-8"), v
329+
330+
def set_location(self, key):
331+
return self.db.set_location(key.encode("utf-8"))
332+
333+
def next(self):
334+
key, value = self.db.next()
335+
return key.decode("utf-8"), value
336+
337+
def previous(self):
338+
key, value = self.db.previous()
339+
return key.decode("utf-8"), value
340+
341+
def first(self):
342+
key, value = self.db.first()
343+
return key.decode("utf-8"), value
344+
345+
def last(self):
346+
key, value = self.db.last()
347+
return key.decode("utf-8"), value
348+
349+
def sync(self):
350+
return self.db.sync()
351+
352+
class StringValues(UserDict.DictMixin, _ExposedProperties):
353+
"""Wrapper around DB object that automatically encodes
354+
all keys as UTF-8; the keys must be strings."""
355+
356+
def __init__(self, db):
357+
self.db = db
358+
359+
def __len__(self):
360+
return len(self.db)
361+
362+
def __getitem__(self, key):
363+
return self.db[key].decode("utf-8")
364+
365+
def __setitem__(self, key, value):
366+
self.db[key] = value.encode("utf-8")
367+
368+
def __delitem__(self, key):
369+
del self.db[key]
370+
371+
def __iter__(self):
372+
return iter(self.db)
373+
374+
def close(self):
375+
self.db.close()
376+
377+
def keys(self):
378+
return self.db.keys()
379+
380+
def has_key(self, key):
381+
return self.db.has_key(key)
382+
383+
__contains__ = has_key
384+
385+
def values(self):
386+
for v in self.db.values():
387+
yield v.decode("utf-8")
388+
389+
def items(self):
390+
for k,v in self.db.items():
391+
yield k, v.decode("utf-8")
392+
393+
def set_location(self, key):
394+
return self.db.set_location(key)
395+
396+
def next(self):
397+
key, value = self.db.next()
398+
return key, value.decode("utf-8")
399+
400+
def previous(self):
401+
key, value = self.db.previous()
402+
return key, value.decode("utf-8")
403+
404+
def first(self):
405+
key, value = self.db.first()
406+
return key, value.decode("utf-8")
407+
408+
def last(self):
409+
key, value = self.db.last()
410+
return key, value.decode("utf-8")
411+
412+
def sync(self):
413+
return self.db.sync()
414+
293415

294416
#----------------------------------------------------------------------
295417
# Compatibility object factory functions
@@ -375,7 +497,7 @@ def _checkflag(flag, file):
375497
if file is not None and os.path.isfile(file):
376498
os.unlink(file)
377499
else:
378-
raise error, "flags should be one of 'r', 'w', 'c' or 'n'"
500+
raise error, "flags should be one of 'r', 'w', 'c' or 'n', not "+repr(flag)
379501
return flags | db.DB_THREAD
380502

381503
#----------------------------------------------------------------------

Lib/test/test_bsddb.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
class TestBSDDB(unittest.TestCase):
1313
openflag = 'c'
1414

15+
def do_open(self, *args, **kw):
16+
# openmethod is a list so that it's not mistaken as an instance method
17+
return bsddb.StringValues(bsddb.StringKeys(self.openmethod[0](*args, **kw)))
18+
1519
def setUp(self):
16-
self.f = self.openmethod[0](self.fname, self.openflag, cachesize=32768)
20+
self.f = self.do_open(self.fname, self.openflag, cachesize=32768)
1721
self.d = dict(q='Guido', w='van', e='Rossum', r='invented', t='Python', y='')
1822
for k, v in self.d.items():
1923
self.f[k] = v
@@ -47,7 +51,7 @@ def test_close_and_reopen(self):
4751
# so finish here.
4852
return
4953
self.f.close()
50-
self.f = self.openmethod[0](self.fname, 'w')
54+
self.f = self.do_open(self.fname, 'w')
5155
for k, v in self.d.items():
5256
self.assertEqual(self.f[k], v)
5357

0 commit comments

Comments
 (0)