]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-107122: Add clear method to dbm.ndbm module (gh-107126)
authorDong-hee Na <donghee.na@python.org>
Sun, 23 Jul 2023 14:26:23 +0000 (23:26 +0900)
committerGitHub <noreply@github.com>
Sun, 23 Jul 2023 14:26:23 +0000 (14:26 +0000)
Doc/library/dbm.rst
Lib/test/test_dbm.py
Lib/test/test_dbm_ndbm.py
Misc/NEWS.d/next/Core and Builtins/2023-07-23-21-16-54.gh-issue-107122.VNuNcq.rst [new file with mode: 0644]
Modules/_dbmmodule.c
Modules/clinic/_dbmmodule.c.h

index d226fa9f962cb41a6a84034795206b8b9d067020..766847b971b645af3a1da6b85d5083fbe76931c0 100644 (file)
@@ -320,6 +320,12 @@ to locate the appropriate header file to simplify building this module.
 
       Close the ``ndbm`` database.
 
+   .. method:: ndbm.clear()
+
+      Remove all items from the ``ndbm`` database.
+
+      .. versionadded:: 3.13
+
 
 :mod:`dbm.dumb` --- Portable DBM implementation
 -----------------------------------------------
index f21eebc6530c768bd43180eed61001e7aeefcfd0..e3924d8ec8b5c1d2fcb163934b8b98e16eb51395 100644 (file)
@@ -155,6 +155,21 @@ class AnyDBMTestCase:
             self.assertNotIn(b'xxx', d)
             self.assertRaises(KeyError, lambda: d[b'xxx'])
 
+    def test_clear(self):
+        with dbm.open(_fname, 'c') as d:
+            self.assertEqual(d.keys(), [])
+            a = [(b'a', b'b'), (b'12345678910', b'019237410982340912840198242')]
+            for k, v in a:
+                d[k] = v
+            for k, _ in a:
+                self.assertIn(k, d)
+            self.assertEqual(len(d), len(a))
+
+            d.clear()
+            self.assertEqual(len(d), 0)
+            for k, _ in a:
+                self.assertNotIn(k, d)
+
     def setUp(self):
         self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod)
         dbm._defaultmod = self.module
index 8f37e3cc624e2e68139e418f8341cd57b60f15e1..e0f31c9a9a337d2921a797aad08b4ab1ca2188e0 100644 (file)
@@ -147,6 +147,19 @@ class DbmTestCase(unittest.TestCase):
             db['a'] = 'b'
         self.assertRaises(dbm.ndbm.error, bool, db)
 
+    def test_clear(self):
+        kvs = [('foo', 'bar'), ('1234', '5678')]
+        with dbm.ndbm.open(self.filename, 'c') as db:
+            for k, v in kvs:
+                db[k] = v
+                self.assertIn(k, db)
+            self.assertEqual(len(db), len(kvs))
+
+            db.clear()
+            for k, v in kvs:
+                self.assertNotIn(k, db)
+            self.assertEqual(len(db), 0)
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-23-21-16-54.gh-issue-107122.VNuNcq.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-23-21-16-54.gh-issue-107122.VNuNcq.rst
new file mode 100644 (file)
index 0000000..d63aeb5
--- /dev/null
@@ -0,0 +1 @@
+Add :meth:`dbm.ndbm.clear` to :mod:`dbm.ndbm`. Patch By Dong-hee Na.
index 5be444d53e8da39191b0d0be14e7d8c76ce5d18b..bd807698927e8659dd09a3d97085abb3d5d1d0ef 100644 (file)
@@ -414,6 +414,38 @@ _dbm_dbm_setdefault_impl(dbmobject *self, PyTypeObject *cls, const char *key,
     return default_value;
 }
 
+/*[clinic input]
+_dbm.dbm.clear
+    cls: defining_class
+    /
+Remove all items from the database.
+
+[clinic start generated code]*/
+
+static PyObject *
+_dbm_dbm_clear_impl(dbmobject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=8d126b9e1d01a434 input=43aa6ca1acb7f5f5]*/
+{
+    _dbm_state *state = PyType_GetModuleState(cls);
+    assert(state != NULL);
+    check_dbmobject_open(self, state->dbm_error);
+    datum key;
+    // Invalidate cache
+    self->di_size = -1;
+    while (1) {
+        key = dbm_firstkey(self->di_dbm);
+        if (key.dptr == NULL) {
+            break;
+        }
+        if (dbm_delete(self->di_dbm, key) < 0) {
+            dbm_clearerr(self->di_dbm);
+            PyErr_SetString(state->dbm_error, "cannot delete item from database");
+            return NULL;
+        }
+    }
+    Py_RETURN_NONE;
+}
+
 static PyObject *
 dbm__enter__(PyObject *self, PyObject *args)
 {
@@ -431,6 +463,7 @@ static PyMethodDef dbm_methods[] = {
     _DBM_DBM_KEYS_METHODDEF
     _DBM_DBM_GET_METHODDEF
     _DBM_DBM_SETDEFAULT_METHODDEF
+    _DBM_DBM_CLEAR_METHODDEF
     {"__enter__", dbm__enter__, METH_NOARGS, NULL},
     {"__exit__",  dbm__exit__, METH_VARARGS, NULL},
     {NULL,  NULL}           /* sentinel */
index 172dc4b9d5793e5d49dc319aa67e586ea23ae1a3..98aac07423c8ab1fe6d01d7a32bfcf4e0b39004b 100644 (file)
@@ -138,6 +138,28 @@ exit:
     return return_value;
 }
 
+PyDoc_STRVAR(_dbm_dbm_clear__doc__,
+"clear($self, /)\n"
+"--\n"
+"\n"
+"Remove all items from the database.");
+
+#define _DBM_DBM_CLEAR_METHODDEF    \
+    {"clear", _PyCFunction_CAST(_dbm_dbm_clear), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _dbm_dbm_clear__doc__},
+
+static PyObject *
+_dbm_dbm_clear_impl(dbmobject *self, PyTypeObject *cls);
+
+static PyObject *
+_dbm_dbm_clear(dbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    if (nargs) {
+        PyErr_SetString(PyExc_TypeError, "clear() takes no arguments");
+        return NULL;
+    }
+    return _dbm_dbm_clear_impl(self, cls);
+}
+
 PyDoc_STRVAR(dbmopen__doc__,
 "open($module, filename, flags=\'r\', mode=0o666, /)\n"
 "--\n"
@@ -200,4 +222,4 @@ skip_optional:
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=28dcf736654137c2 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b3053c67ecfcc29c input=a9049054013a1b77]*/