]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
#6045: provide at least get() and setdefault() for all dbm modules.
authorGeorg Brandl <georg@python.org>
Sat, 4 Dec 2010 09:14:36 +0000 (09:14 +0000)
committerGeorg Brandl <georg@python.org>
Sat, 4 Dec 2010 09:14:36 +0000 (09:14 +0000)
Doc/library/dbm.rst
Lib/dbm/dumb.py
Lib/test/test_dbm_gnu.py
Misc/NEWS
Modules/_gdbmmodule.c

index 6926ca6d10998f44ed610a8d6f517069041e7afd..67c0025fe9d944960c7a5c26009fd7702846f285 100644 (file)
@@ -61,10 +61,15 @@ the Oracle Berkeley DB.
    modified by the prevailing umask).
 
 
-The object returned by :func:`.open` supports most of the same functionality as
+The object returned by :func:`.open` supports the same basic functionality as
 dictionaries; keys and their corresponding values can be stored, retrieved, and
 deleted, and the :keyword:`in` operator and the :meth:`keys` method are
-available. Key and values are always stored as bytes. This means that when
+available, as well as :meth:`get` and :meth:`setdefault`.
+
+.. versionchanged:: 3.2
+   :meth:`get` and :meth:`setdefault` are now available in all database modules.
+
+Key and values are always stored as bytes. This means that when
 strings are used they are implicitly converted to the default encoding before
 being stored.
 
index 4d804daa0f6ee56195bb6c411bd2e52832732677..cfb912371c9de1123e195d844a9e77f22be058ee 100644 (file)
@@ -203,7 +203,7 @@ class _Database(collections.MutableMapping):
         # The blocks used by the associated value are lost.
         del self._index[key]
         # XXX It's unclear why we do a _commit() here (the code always
-        # XXX has, so I'm not changing it).  _setitem__ doesn't try to
+        # XXX has, so I'm not changing it).  __setitem__ doesn't try to
         # XXX keep the directory file in synch.  Why should we?  Or
         # XXX why shouldn't __setitem__?
         self._commit()
@@ -232,7 +232,7 @@ class _Database(collections.MutableMapping):
 
     __del__ = close
 
-    def _chmod (self, file):
+    def _chmod(self, file):
         if hasattr(self._os, 'chmod'):
             self._os.chmod(file, self._mode)
 
index dad56e6bd99d5e626c0184f7d55c0897a785aca2..ce96ce465e72eba9f2b12a0f15c3346689a57775 100755 (executable)
@@ -32,6 +32,10 @@ class TestGdbm(unittest.TestCase):
             key_set.remove(key)
             key = self.g.nextkey(key)
         self.assertRaises(KeyError, lambda: self.g['xxx'])
+        # get() and setdefault() work as in the dict interface
+        self.assertEqual(self.g.get(b'xxx', b'foo'), b'foo')
+        self.assertEqual(self.g.setdefault(b'xxx', b'foo'), b'foo')
+        self.assertEqual(self.g[b'xxx'], b'foo')
 
     def test_error_conditions(self):
         # Try to open a non-existent database.
index f53a48689291cf0c424e2c089428efe0d9651a86..bc4cd254d4634248d9e08f8f5b3f6a393c368c75 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -37,7 +37,9 @@ Core and Builtins
 Library
 -------
 
-- Issue 10620: `python -m unittest` can accept file paths instead of module
+- Issue #6045: dbm.gnu databases now support get() and setdefault() methods.
+
+- Issue #10620: `python -m unittest` can accept file paths instead of module
   names for running specific tests.
 
 - Issue #9424: Deprecate the `unittest.TestCase` methods `assertEquals`,
index f15fefdf8222cddf3ec2c983e6d13b6a10cd83a2..474561b235f28f805ae2bc1655fda85ec8dc9ccf 100644 (file)
@@ -135,6 +135,28 @@ dbm_subscript(dbmobject *dp, register PyObject *key)
     return v;
 }
 
+PyDoc_STRVAR(dbm_get__doc__,
+"get(key[, default]) -> value\n\
+Get the value for key, or default if not present; if not given,\n\
+default is None.");
+
+static PyObject *
+dbm_get(dbmobject *dp, PyObject *args)
+{
+    PyObject *v, *res;
+    PyObject *def = Py_None;
+
+    if (!PyArg_UnpackTuple(args, "get", 1, 2, &v, &def))
+        return NULL;
+    res = dbm_subscript(dp, v);
+    if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
+        PyErr_Clear();
+        Py_INCREF(def);
+        return def;
+    }
+    return res;
+}
+
 static int
 dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
 {
@@ -176,6 +198,29 @@ dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
     return 0;
 }
 
+PyDoc_STRVAR(dbm_setdefault__doc__,
+"setdefault(key[, default]) -> value\n\
+Get value for key, or set it to default and return default if not present;\n\
+if not given, default is None.");
+
+static PyObject *
+dbm_setdefault(dbmobject *dp, PyObject *args)
+{
+    PyObject *v, *res;
+    PyObject *def = Py_None;
+
+    if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &v, &def))
+        return NULL;
+    res = dbm_subscript(dp, v);
+    if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
+        PyErr_Clear();
+        if (dbm_ass_sub(dp, v, def) < 0)
+            return NULL;
+        return dbm_subscript(dp, v);
+    }
+    return res;
+}
+
 static PyMappingMethods dbm_as_mapping = {
     (lenfunc)dbm_length,                /*mp_length*/
     (binaryfunc)dbm_subscript,          /*mp_subscript*/
@@ -378,6 +423,8 @@ static PyMethodDef dbm_methods[] = {
     {"nextkey",   (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
     {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
     {"sync",      (PyCFunction)dbm_sync,    METH_NOARGS, dbm_sync__doc__},
+    {"get",       (PyCFunction)dbm_get,     METH_VARARGS, dbm_get__doc__},
+    {"setdefault",(PyCFunction)dbm_setdefault,METH_VARARGS, dbm_setdefault__doc__},
     {NULL,              NULL}           /* sentinel */
 };