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

Skip to content

Commit 7317c1e

Browse files
committed
dbm.gnu and dbm.ndbm accept both strings and bytes as keys and values. For the
former they are converted to bytes before being written to the DB. Closes issue 3799. Reviewed by Skip Montanaro.
1 parent 50d5a1c commit 7317c1e

7 files changed

Lines changed: 40 additions & 19 deletions

File tree

Doc/library/dbm.rst

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252
The object returned by :func:`open` supports most of the same functionality as
5353
dictionaries; keys and their corresponding values can be stored, retrieved, and
5454
deleted, and the :keyword:`in` operator and the :meth:`keys` method are
55-
available. Keys and values must always be strings.
55+
available. Key and values are always stored as bytes. This means that when
56+
strings are used they are implicitly converted to the default encoding before
57+
being stored.
5658

5759
The following example records some hostnames and a corresponding title, and
5860
then prints out the contents of the database::
@@ -63,9 +65,15 @@ then prints out the contents of the database::
6365
db = dbm.open('cache', 'c')
6466

6567
# Record some values
68+
db[b'hello'] = b'there'
6669
db['www.python.org'] = 'Python Website'
6770
db['www.cnn.com'] = 'Cable News Network'
6871

72+
# Note that the keys are considered bytes now.
73+
assert db[b'www.python.org'] == b'Python Website'
74+
# Notice how the value is now in bytes.
75+
assert db['www.cnn.com'] == b'Cable News Network'
76+
6977
# Loop through contents. Other dictionary methods
7078
# such as .keys(), .values() also work.
7179
for k, v in db.iteritems():
@@ -98,17 +106,18 @@ The individual submodules are described in the following sections.
98106

99107
This module is quite similar to the :mod:`dbm` module, but uses the GNU library
100108
``gdbm`` instead to provide some additional functionality. Please note that the
101-
file formats created by ``gdbm`` and ``dbm`` are incompatible.
109+
file formats created by :mod:`dbm.gnu` and :mod:`dbm.ndbm` are incompatible.
102110

103111
The :mod:`dbm.gnu` module provides an interface to the GNU DBM library.
104-
``gdbm`` objects behave like mappings (dictionaries), except that keys and
105-
values are always strings. Printing a :mod:`dbm.gnu` object doesn't print the
112+
``dbm.gnu.gdbm`` objects behave like mappings (dictionaries), except that keys and
113+
values are always converted to bytes before storing. Printing a ``gdbm``
114+
object doesn't print the
106115
keys and values, and the :meth:`items` and :meth:`values` methods are not
107116
supported.
108117

109118
.. exception:: error
110119

111-
Raised on ``gdbm``\ -specific errors, such as I/O errors. :exc:`KeyError` is
120+
Raised on :mod:`dbm.gnu`-specific errors, such as I/O errors. :exc:`KeyError` is
112121
raised for general mapping errors like specifying an incorrect key.
113122

114123

@@ -183,7 +192,7 @@ supported.
183192

184193
If you have carried out a lot of deletions and would like to shrink the space
185194
used by the ``gdbm`` file, this routine will reorganize the database. ``gdbm``
186-
will not shorten the length of a database file except by using this
195+
objects will not shorten the length of a database file except by using this
187196
reorganization; otherwise, deleted file space will be kept and reused as new
188197
(key, value) pairs are added.
189198

@@ -203,8 +212,8 @@ supported.
203212

204213
The :mod:`dbm.ndbm` module provides an interface to the Unix "(n)dbm" library.
205214
Dbm objects behave like mappings (dictionaries), except that keys and values are
206-
always strings. Printing a dbm object doesn't print the keys and values, and the
207-
:meth:`items` and :meth:`values` methods are not supported.
215+
always stored as bytes. Printing a ``dbm`` object doesn't print the keys and
216+
values, and the :meth:`items` and :meth:`values` methods are not supported.
208217

209218
This module can be used with the "classic" ndbm interface, the BSD DB
210219
compatibility interface, or the GNU GDBM compatibility interface. On Unix, the
@@ -213,7 +222,7 @@ to simplify building this module.
213222

214223
.. exception:: error
215224

216-
Raised on dbm-specific errors, such as I/O errors. :exc:`KeyError` is raised
225+
Raised on :mod:`dbm.ndbm`-specific errors, such as I/O errors. :exc:`KeyError` is raised
217226
for general mapping errors like specifying an incorrect key.
218227

219228

@@ -224,7 +233,7 @@ to simplify building this module.
224233

225234
.. function:: open(filename[, flag[, mode]])
226235

227-
Open a dbm database and return a dbm object. The *filename* argument is the
236+
Open a dbm database and return a ``dbm`` object. The *filename* argument is the
228237
name of the database file (without the :file:`.dir` or :file:`.pag` extensions;
229238
note that the BSD DB implementation of the interface will append the extension
230239
:file:`.db` and only create one file).
@@ -264,27 +273,27 @@ to simplify building this module.
264273
.. note::
265274

266275
The :mod:`dbm.dumb` module is intended as a last resort fallback for the
267-
:mod:`dbm` module when no more robust module is available. The :mod:`dbm.dumb`
276+
:mod:`dbm` module when a more robust module is not available. The :mod:`dbm.dumb`
268277
module is not written for speed and is not nearly as heavily used as the other
269278
database modules.
270279

271280
The :mod:`dbm.dumb` module provides a persistent dictionary-like interface which
272-
is written entirely in Python. Unlike other modules such as :mod:`gdbm` no
281+
is written entirely in Python. Unlike other modules such as :mod:`dbm.gnu` no
273282
external library is required. As with other persistent mappings, the keys and
274-
values must always be strings.
283+
values are always stored as bytes.
275284

276285
The module defines the following:
277286

278287

279288
.. exception:: error
280289

281-
Raised on dbm.dumb-specific errors, such as I/O errors. :exc:`KeyError` is
290+
Raised on :mod:`dbm.dumb`-specific errors, such as I/O errors. :exc:`KeyError` is
282291
raised for general mapping errors like specifying an incorrect key.
283292

284293

285294
.. function:: open(filename[, flag[, mode]])
286295

287-
Open a dumbdbm database and return a dumbdbm object. The *filename* argument is
296+
Open a ``dumbdbm`` database and return a dumbdbm object. The *filename* argument is
288297
the basename of the database file (without any specific extensions). When a
289298
dumbdbm database is created, files with :file:`.dat` and :file:`.dir` extensions
290299
are created.

Lib/test/test_dbm_dumb.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,13 @@ def test_str_write_contains(self):
115115
self.init_db()
116116
f = dumbdbm.open(_fname)
117117
f['\u00fc'] = b'!'
118+
f['1'] = 'a'
118119
f.close()
119120
f = dumbdbm.open(_fname, 'r')
120121
self.assert_('\u00fc' in f)
121122
self.assertEqual(f['\u00fc'.encode('utf-8')],
122123
self._dict['\u00fc'.encode('utf-8')])
124+
self.assertEqual(f[b'1'], b'a')
123125

124126
def test_line_endings(self):
125127
# test for bug #1172763: dumbdbm would die if the line endings

Lib/test/test_dbm_gnu.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ def test_key_methods(self):
2020
self.assertEqual(self.g.keys(), [])
2121
self.g['a'] = 'b'
2222
self.g['12345678910'] = '019237410982340912840198242'
23+
self.g[b'bytes'] = b'data'
2324
key_set = set(self.g.keys())
2425
self.assertEqual(key_set, set([b'a', b'12345678910']))
2526
self.assert_(b'a' in self.g)
27+
self.assertEqual(self.g[b'bytes'], b'data')
2628
key = self.g.firstkey()
2729
while key:
2830
self.assert_(key in key_set)

Lib/test/test_dbm_ndbm.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ def test_keys(self):
2020
self.d = dbm.ndbm.open(self.filename, 'c')
2121
self.assert_(self.d.keys() == [])
2222
self.d['a'] = 'b'
23+
self.d[b'bytes'] = b'data'
2324
self.d['12345678910'] = '019237410982340912840198242'
2425
self.d.keys()
2526
self.assert_(b'a' in self.d)
27+
self.assertEqual(self.d[b'bytes'], b'data')
2628
self.d.close()
2729

2830
def test_modes(self):

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ Library
2828
- Issue #4383: When IDLE cannot make the connection to its subprocess, it would
2929
fail to properly display the error message.
3030

31+
Docs
32+
----
33+
34+
- Issue #3799: Document that dbm.gnu and dbm.ndbm will accept string arguments
35+
for keys and values which will be converted to bytes before committal.
36+
3137

3238
What's New in Python 3.0 release candidate 3?
3339
=============================================

Modules/_dbmmodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
122122

123123
if ( !PyArg_Parse(v, "s#", &krec.dptr, &tmp_size) ) {
124124
PyErr_SetString(PyExc_TypeError,
125-
"dbm mappings have string keys only");
125+
"dbm mappings have bytes or string keys only");
126126
return -1;
127127
}
128128
krec.dsize = tmp_size;
@@ -140,7 +140,7 @@ dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
140140
} else {
141141
if ( !PyArg_Parse(w, "s#", &drec.dptr, &tmp_size) ) {
142142
PyErr_SetString(PyExc_TypeError,
143-
"dbm mappings have byte string elements only");
143+
"dbm mappings have byte or string elements only");
144144
return -1;
145145
}
146146
drec.dsize = tmp_size;

Modules/_gdbmmodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
142142

143143
if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
144144
PyErr_SetString(PyExc_TypeError,
145-
"gdbm mappings have string indices only");
145+
"gdbm mappings have bytes or string indices only");
146146
return -1;
147147
}
148148
if (dp->di_dbm == NULL) {
@@ -160,7 +160,7 @@ dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
160160
else {
161161
if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
162162
PyErr_SetString(PyExc_TypeError,
163-
"gdbm mappings have byte string elements only");
163+
"gdbm mappings have byte or string elements only");
164164
return -1;
165165
}
166166
errno = 0;

0 commit comments

Comments
 (0)