Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions Doc/library/dbm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ The :meth:`!setdefault` method requires two arguments.

Key and values are always stored as :class:`bytes`. This means that when
strings are used they are implicitly converted to the default encoding before
being stored.
being stored. For detailed information about accepted types, see
:ref:`dbm-key-value-types`.

These objects also support being used in a :keyword:`with` statement, which
will automatically close them when done.
Expand All @@ -121,6 +122,47 @@ will automatically close them when done.
:meth:`!clear` methods are now available for all :mod:`!dbm` backends.


.. _dbm-key-value-types:

Key and value types
-------------------
Comment thread
furkanonder marked this conversation as resolved.

The accepted types for keys and values vary by backend. Keys and values are
handled identically:

* **Traditional backends:**

* :mod:`dbm.gnu` and :mod:`dbm.ndbm`: Accept :class:`str` and :class:`bytes`
objects.
* :mod:`dbm.dumb`: Accepts :class:`str` and :class:`bytes` objects;
:class:`bytearray` is acceptable as a value, but not as a key.

* **SQLite backend** (:mod:`dbm.sqlite3`): Accepts :class:`str`, :class:`bytes`,
:class:`int`, :class:`float`, :class:`bool`, :class:`bytearray`,
:class:`memoryview`, and :class:`array.array` objects.

**Storage format:**

All keys and values are stored as :class:`bytes` objects in the database.
When retrieving, you'll always get bytes back, regardless of the original
type stored.

**Type conversion examples:**

* ``db['key'] = 'string'`` stored as ``b'string'``
* ``db['key'] = bytearray(b'data')`` stored as ``b'data'``
(:mod:`dbm.dumb` and :mod:`dbm.sqlite3` only)
* ``db['key'] = 42`` stored as ``b'42'`` (:mod:`dbm.sqlite3` only)
* ``db['key'] = 3.14`` stored as ``b'3.14'`` (:mod:`dbm.sqlite3` only)
* ``db['key'] = True`` stored as ``b'1'`` (:mod:`dbm.sqlite3` only)
* ``db['key'] = False`` stored as ``b'0'`` (:mod:`dbm.sqlite3` only)
* ``db['key'] = memoryview(b'data')`` stored as ``b'data'``
(:mod:`dbm.sqlite3` only)
* ``db['key'] = array.array('i', [1, 2, 3])`` stored as bytes (for example, on
little-endian: ``b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'``)
(:mod:`dbm.sqlite3` only)


The following example records some hostnames and a corresponding title, and
then prints out the contents of the database::

Expand All @@ -142,8 +184,9 @@ then prints out the contents of the database::
# Often-used methods of the dict interface work too.
print(db.get('python.org', b'not present'))

# Storing a non-string key or value will raise an exception (most
# likely a TypeError).
# Storing a non-string key or value behavior depends on the backend:
# - Traditional backends (ndbm, gnu, dumb) will raise a TypeError
# - The sqlite3 backend accepts it and converts to bytes
db['www.yahoo.com'] = 4

# db is automatically closed when leaving the with statement.
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_dbm_dumb.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class DumbDBMTestCase(unittest.TestCase):
b'd': b'way',
b'f': b'Guido',
b'g': b'intended',
b'h': bytearray(b'bytearray_value'),
'\u00fc'.encode('utf-8') : b'!',
}

Expand Down Expand Up @@ -378,6 +379,14 @@ def test_nonascii_filename(self):
self.assertTrue(b'key' in db)
self.assertEqual(db[b'key'], b'value')

def test_bytearray(self):
self.init_db()
with contextlib.closing(dumbdbm.open(_fname, 'r')) as f:
self.assertEqual(f[b'h'], b'bytearray_value')
with contextlib.closing(dumbdbm.open(_fname)) as f:
with self.assertRaises(TypeError):
f[bytearray(b'bytearray_key')] = b'value'

def test_open_with_pathlib_path(self):
dumbdbm.open(os_helper.FakePath(_fname), "c").close()

Expand Down
4 changes: 4 additions & 0 deletions Lib/test/test_dbm_sqlite3.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ class DataTypes(_SQLiteDbmTests):
(3.14, b"3.14"),
("string", b"string"),
(b"bytes", b"bytes"),
(True, b"1"),
(False, b"0"),
(bytearray(b"bytearray"), b"bytearray"),
(memoryview(b"memoryview"), b"memoryview"),
)

def setUp(self):
Expand Down
Loading