-
-
Notifications
You must be signed in to change notification settings - Fork 32.6k
Description
Bug report
Bug description:
dbm.sqlite3
fails with "NOT NULL constraint failed: Dict.value"
when trying to store None values, breaking compatibility with dict interface and other DBM backends. This particularly affects the setdefault() method which should default to None when called with a single argument.
Expected Behavior
According to dbm documentation:
"The object returned by open() supports the same basic functionality as a dict; keys and their corresponding values can be stored, retrieved, and deleted, and the in operator and the keys() method are available, as well as get() and setdefault() methods."
Actual Behavior
import dbm.sqlite3
import tempfile
d = {}
result = d.setdefault('missing')
print(d['missing'])
with tempfile.NamedTemporaryFile() as tmp:
db = dbm.sqlite3.open(tmp.name, 'c')
result = db.setdefault('missing_key')
db.close()
Output:
None
Traceback (most recent call last):
File "<frozen _collections_abc>", line 1000, in setdefault
File "/usr/lib/python3.13/dbm/sqlite3.py", line 92, in __getitem__
raise KeyError(key)
KeyError: 'missing_key'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.13/dbm/sqlite3.py", line 79, in _execute
return closing(self._cx.execute(*args, **kwargs))
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
sqlite3.IntegrityError: NOT NULL constraint failed: Dict.value
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/arf/repro.py", line 10, in <module>
result = db.setdefault('missing_key')
File "<frozen _collections_abc>", line 1002, in setdefault
File "/usr/lib/python3.13/dbm/sqlite3.py", line 96, in __setitem__
self._execute(STORE_KV, (key, value))
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.13/dbm/sqlite3.py", line 81, in _execute
raise error(str(exc))
dbm.sqlite3.error: NOT NULL constraint failed: Dict.value
There is no issue when a default argument is explicitly provided to setdefault.
import dbm.sqlite3
import tempfile
with tempfile.NamedTemporaryFile() as tmp:
db = dbm.sqlite3.open(tmp.name, 'c')
result = db.setdefault('missing_key', "default")
print(result)
db.close()
This behavior has also been reported for dbm.gnu and dbm.dumb objects in issue #77566.
CPython versions tested on:
CPython main branch, 3.14, 3.15, 3.13
Operating systems tested on:
Linux