Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Doc/library/dbm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ supported.

Close the ``gdbm`` database.

.. method:: gdbm.count()

Count the number of records in the database. This method requires GNU
DBM version 1.11 or greater.

.. versionadded:: 3.9

:mod:`dbm.ndbm` --- Interface based on ndbm
-------------------------------------------

Expand Down
28 changes: 21 additions & 7 deletions Lib/test/test_dbm_gnu.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@
import os
from test.support import TESTFN, TESTFN_NONASCII, unlink

try:
from _gdbm import _GDBM_VERSION as gdbm_version
except ImportError:
gdbm_version = None

filename = TESTFN

class TestGdbm(unittest.TestCase):
@staticmethod
def setUpClass():
if support.verbose:
try:
from _gdbm import _GDBM_VERSION as version
except ImportError:
pass
else:
print(f"gdbm version: {version}")
if support.verbose and gdbm_version:
print(f"gdbm version: {gdbm_version}")

def setUp(self):
self.g = None
Expand Down Expand Up @@ -162,6 +161,21 @@ def test_nonexisting_file(self):
self.assertIn(nonexisting_file, str(cm.exception))
self.assertEqual(cm.exception.filename, nonexisting_file)

@unittest.skipUnless(gdbm_version and gdbm_version >= (1, 11, 0),
'needs >= 1.11')
def test_count(self):
self.g = gdbm.open(filename, 'c')
self.assertEqual(self.g.count(), 0)

self.g['a'] = 'a'
self.assertEqual(self.g.count(), 1)
self.g['b'] = 'b'
self.assertEqual(self.g.count(), 2)
del self.g['a']
self.assertEqual(self.g.count(), 1)
del self.g['b']
self.assertEqual(self.g.count(), 0)


if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add :meth:`gdbm.count` to wrap the ``gdbm_count()`` function added in GDBM
1.11.
27 changes: 27 additions & 0 deletions Modules/_gdbmmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,32 @@ _gdbm_gdbm_sync_impl(dbmobject *self)
Py_RETURN_NONE;
}

#if GDBM_VERSION_MAJOR >= 1 && GDBM_VERSION_MINOR >= 11
/*[clinic input]
_gdbm.gdbm.count

Count the number of records in the database.
[clinic start generated code]*/

static PyObject *
_gdbm_gdbm_count_impl(dbmobject *self)
/*[clinic end generated code: output=8b62b02ae4c2fcee input=1b9d3f0877315a04]*/
{
gdbm_count_t count;
check_dbmobject_open(self);
if (gdbm_count(self->di_dbm, &count) == -1) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to set errno = 0 before this.

if (errno != 0) {
PyErr_SetFromErrno(DbmError);
}
else {
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
}
return NULL;
}
return PyLong_FromUnsignedLongLong(count);
}
#endif

static PyObject *
dbm__enter__(PyObject *self, PyObject *args)
{
Expand All @@ -509,6 +535,7 @@ static PyMethodDef dbm_methods[] = {
_GDBM_GDBM_SYNC_METHODDEF
_GDBM_GDBM_GET_METHODDEF
_GDBM_GDBM_SETDEFAULT_METHODDEF
_GDBM_GDBM_COUNT_METHODDEF
{"__enter__", dbm__enter__, METH_NOARGS, NULL},
{"__exit__", dbm__exit__, METH_VARARGS, NULL},
{NULL, NULL} /* sentinel */
Expand Down
28 changes: 27 additions & 1 deletion Modules/clinic/_gdbmmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.