https://github.com/python/cpython/commit/d5b79b33cedb1a578c92a855f94d53bc16407516
commit: d5b79b33cedb1a578c92a855f94d53bc16407516
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: hugovk <[email protected]>
date: 2026-10-25T16:11:04+02:00
summary:

[3.15] gh-131323: Add comprehensive key-value type documentation to dbm module 
(GH-137972) (#159648)

Co-authored-by: Furkan Onder <[email protected]>
Co-authored-by: Pieter Eendebak <[email protected]>

files:
M Doc/library/dbm.rst
M Lib/test/test_dbm_dumb.py
M Lib/test/test_dbm_sqlite3.py

diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst
index 646981e8692cc5..479817f896a8dd 100644
--- a/Doc/library/dbm.rst
+++ b/Doc/library/dbm.rst
@@ -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.
@@ -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
+-------------------
+
+The accepted types for keys and values vary by backend. Keys and values are
+handled the same way, except where noted below:
+
+* **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::
 
@@ -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.
diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py
index d977a81876df65..a1791a5ada7f67 100644
--- a/Lib/test/test_dbm_dumb.py
+++ b/Lib/test/test_dbm_dumb.py
@@ -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'!',
              }
 
@@ -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()
 
diff --git a/Lib/test/test_dbm_sqlite3.py b/Lib/test/test_dbm_sqlite3.py
index f367a98865d4aa..0e87bb1c6e8dbf 100644
--- a/Lib/test/test_dbm_sqlite3.py
+++ b/Lib/test/test_dbm_sqlite3.py
@@ -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):

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to