From b273837fea129df8477da557ad3cb23a0ed12c20 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sun, 23 Jul 2023 22:51:12 +0900 Subject: [PATCH] gh-107122: Add clear method to dbm.gdbm.module (gh-107127) --- Doc/library/dbm.rst | 7 ++++ Lib/test/test_dbm_gnu.py | 14 ++++++++ ...-07-23-13-07-34.gh-issue-107122.9HFUyb.rst | 1 + Modules/_gdbmmodule.c | 32 +++++++++++++++++++ Modules/clinic/_gdbmmodule.c.h | 24 +++++++++++++- 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-07-23-13-07-34.gh-issue-107122.9HFUyb.rst diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst index 2be499337a2..d226fa9f962 100644 --- a/Doc/library/dbm.rst +++ b/Doc/library/dbm.rst @@ -245,6 +245,13 @@ supported. Close the ``gdbm`` database. + .. method:: gdbm.clear() + + Remove all items from the ``gdbm`` database. + + .. versionadded:: 3.13 + + :mod:`dbm.ndbm` --- Interface based on ndbm ------------------------------------------- diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py index 73602cab518..e20addf1f04 100644 --- a/Lib/test/test_dbm_gnu.py +++ b/Lib/test/test_dbm_gnu.py @@ -192,6 +192,20 @@ class TestGdbm(unittest.TestCase): def test_open_with_pathlib_bytes_path(self): gdbm.open(FakePath(os.fsencode(filename)), "c").close() + def test_clear(self): + kvs = [('foo', 'bar'), ('1234', '5678')] + with gdbm.open(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-13-07-34.gh-issue-107122.9HFUyb.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-23-13-07-34.gh-issue-107122.9HFUyb.rst new file mode 100644 index 00000000000..c2e1c58c1b4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-23-13-07-34.gh-issue-107122.9HFUyb.rst @@ -0,0 +1 @@ +Add :meth:`dbm.gdbm.clear` to :mod:`dbm.gdbm`. Patch By Dong-hee Na. diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index bedbdc08142..47f2da8e0e3 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -561,6 +561,37 @@ _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls) Py_RETURN_NONE; } +/*[clinic input] +_gdbm.gdbm.clear + cls: defining_class + / +Remove all items from the database. + +[clinic start generated code]*/ + +static PyObject * +_gdbm_gdbm_clear_impl(gdbmobject *self, PyTypeObject *cls) +/*[clinic end generated code: output=673577c573318661 input=34136d52fcdd4210]*/ +{ + _gdbm_state *state = PyType_GetModuleState(cls); + assert(state != NULL); + check_gdbmobject_open(self, state->gdbm_error); + datum key; + // Invalidate cache + self->di_size = -1; + while (1) { + key = gdbm_firstkey(self->di_dbm); + if (key.dptr == NULL) { + break; + } + if (gdbm_delete(self->di_dbm, key) < 0) { + PyErr_SetString(state->gdbm_error, "cannot delete item from database"); + return NULL; + } + } + Py_RETURN_NONE; +} + static PyObject * gdbm__enter__(PyObject *self, PyObject *args) { @@ -582,6 +613,7 @@ static PyMethodDef gdbm_methods[] = { _GDBM_GDBM_SYNC_METHODDEF _GDBM_GDBM_GET_METHODDEF _GDBM_GDBM_SETDEFAULT_METHODDEF + _GDBM_GDBM_CLEAR_METHODDEF {"__enter__", gdbm__enter__, METH_NOARGS, NULL}, {"__exit__", gdbm__exit__, METH_VARARGS, NULL}, {NULL, NULL} /* sentinel */ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h index 5c6aeeee778..76f6db318f8 100644 --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -247,6 +247,28 @@ _gdbm_gdbm_sync(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_s return _gdbm_gdbm_sync_impl(self, cls); } +PyDoc_STRVAR(_gdbm_gdbm_clear__doc__, +"clear($self, /)\n" +"--\n" +"\n" +"Remove all items from the database."); + +#define _GDBM_GDBM_CLEAR_METHODDEF \ + {"clear", _PyCFunction_CAST(_gdbm_gdbm_clear), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_clear__doc__}, + +static PyObject * +_gdbm_gdbm_clear_impl(gdbmobject *self, PyTypeObject *cls); + +static PyObject * +_gdbm_gdbm_clear(gdbmobject *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 _gdbm_gdbm_clear_impl(self, cls); +} + PyDoc_STRVAR(dbmopen__doc__, "open($module, filename, flags=\'r\', mode=0o666, /)\n" "--\n" @@ -322,4 +344,4 @@ skip_optional: exit: return return_value; } -/*[clinic end generated code: output=c6e721d82335adb3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8c613cbd88e57480 input=a9049054013a1b77]*/