2
/* DBM module using dictionary interface */
3
/* Author: Anthony Baxter, after dbmmodule.c */
4
/* Doc strings: Mitch Chapman */
14
#if defined(WIN32) && !defined(__CYGWIN__)
15
#include "gdbmerrno.h"
16
extern const char * gdbm_strerror(gdbm_error);
19
PyDoc_STRVAR(gdbmmodule__doc__,
20
"This module provides an interface to the GNU DBM (GDBM) library.\n\
22
This module is quite similar to the dbm module, but uses GDBM instead to\n\
23
provide some additional functionality. Please note that the file formats\n\
24
created by GDBM and dbm are incompatible. \n\
26
GDBM objects behave like mappings (dictionaries), except that keys and\n\
27
values are always strings. Printing a GDBM object doesn't print the\n\
28
keys and values, and the items() and values() methods are not\n\
33
int di_size; /* -1 means recompute */
37
static PyTypeObject Dbmtype;
39
#define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype)
40
#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
41
{ PyErr_SetString(DbmError, "GDBM object has already been closed"); \
46
static PyObject *DbmError;
48
PyDoc_STRVAR(gdbm_object__doc__,
49
"This object represents a GDBM database.\n\
50
GDBM objects behave like mappings (dictionaries), except that keys and\n\
51
values are always strings. Printing a GDBM object doesn't print the\n\
52
keys and values, and the items() and values() methods are not\n\
55
GDBM objects also support additional operations such as firstkey,\n\
56
nextkey, reorganize, and sync.");
59
newdbmobject(char *file, int flags, int mode)
63
dp = PyObject_New(dbmobject, &Dbmtype);
68
if ((dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0) {
70
PyErr_SetFromErrno(DbmError);
72
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
76
return (PyObject *)dp;
82
dbm_dealloc(dbmobject *dp)
85
gdbm_close(dp->di_dbm);
90
dbm_length(dbmobject *dp)
92
if (dp->di_dbm == NULL) {
93
PyErr_SetString(DbmError, "GDBM object has already been closed");
96
if (dp->di_size < 0) {
103
for (key=gdbm_firstkey(dp->di_dbm); key.dptr;
104
key = gdbm_nextkey(dp->di_dbm,okey)) {
106
if(okey.dsize) free(okey.dptr);
115
dbm_subscript(dbmobject *dp, PyObject *key)
120
if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
123
if (dp->di_dbm == NULL) {
124
PyErr_SetString(DbmError,
125
"GDBM object has already been closed");
128
drec = gdbm_fetch(dp->di_dbm, krec);
129
if (drec.dptr == 0) {
130
PyErr_SetObject(PyExc_KeyError, key);
133
v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
138
PyDoc_STRVAR(dbm_get__doc__,
139
"get(key[, default]) -> value\n\
140
Get the value for key, or default if not present; if not given,\n\
144
dbm_get(dbmobject *dp, PyObject *args)
147
PyObject *def = Py_None;
149
if (!PyArg_UnpackTuple(args, "get", 1, 2, &v, &def))
151
res = dbm_subscript(dp, v);
152
if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
161
dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
165
if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
166
PyErr_SetString(PyExc_TypeError,
167
"gdbm mappings have bytes or string indices only");
170
if (dp->di_dbm == NULL) {
171
PyErr_SetString(DbmError,
172
"GDBM object has already been closed");
177
if (gdbm_delete(dp->di_dbm, krec) < 0) {
178
PyErr_SetObject(PyExc_KeyError, v);
183
if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
184
PyErr_SetString(PyExc_TypeError,
185
"gdbm mappings have byte or string elements only");
189
if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
191
PyErr_SetFromErrno(DbmError);
193
PyErr_SetString(DbmError,
194
gdbm_strerror(gdbm_errno));
201
PyDoc_STRVAR(dbm_setdefault__doc__,
202
"setdefault(key[, default]) -> value\n\
203
Get value for key, or set it to default and return default if not present;\n\
204
if not given, default is None.");
207
dbm_setdefault(dbmobject *dp, PyObject *args)
210
PyObject *def = Py_None;
212
if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &v, &def))
214
res = dbm_subscript(dp, v);
215
if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
217
if (dbm_ass_sub(dp, v, def) < 0)
219
return dbm_subscript(dp, v);
224
static PyMappingMethods dbm_as_mapping = {
225
(lenfunc)dbm_length, /*mp_length*/
226
(binaryfunc)dbm_subscript, /*mp_subscript*/
227
(objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
230
PyDoc_STRVAR(dbm_close__doc__,
232
Closes the database.");
235
dbm_close(dbmobject *dp, PyObject *unused)
238
gdbm_close(dp->di_dbm);
244
/* XXX Should return a set or a set view */
245
PyDoc_STRVAR(dbm_keys__doc__,
246
"keys() -> list_of_keys\n\
247
Get a list of all keys in the database.");
250
dbm_keys(dbmobject *dp, PyObject *unused)
256
if (dp == NULL || !is_dbmobject(dp)) {
257
PyErr_BadInternalCall();
260
check_dbmobject_open(dp);
266
key = gdbm_firstkey(dp->di_dbm);
268
item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
274
err = PyList_Append(v, item);
281
nextkey = gdbm_nextkey(dp->di_dbm, key);
289
dbm_contains(PyObject *self, PyObject *arg)
291
dbmobject *dp = (dbmobject *)self;
295
if ((dp)->di_dbm == NULL) {
296
PyErr_SetString(DbmError,
297
"GDBM object has already been closed");
300
if (PyUnicode_Check(arg)) {
301
key.dptr = PyUnicode_AsUTF8AndSize(arg, &size);
303
if (key.dptr == NULL)
306
else if (!PyBytes_Check(arg)) {
307
PyErr_Format(PyExc_TypeError,
308
"gdbm key must be bytes or string, not %.100s",
309
arg->ob_type->tp_name);
313
key.dptr = PyBytes_AS_STRING(arg);
314
key.dsize = PyBytes_GET_SIZE(arg);
316
return gdbm_exists(dp->di_dbm, key);
319
static PySequenceMethods dbm_as_sequence = {
326
0, /* sq_ass_slice */
327
dbm_contains, /* sq_contains */
328
0, /* sq_inplace_concat */
329
0, /* sq_inplace_repeat */
332
PyDoc_STRVAR(dbm_firstkey__doc__,
333
"firstkey() -> key\n\
334
It's possible to loop over every key in the database using this method\n\
335
and the nextkey() method. The traversal is ordered by GDBM's internal\n\
336
hash values, and won't be sorted by the key values. This method\n\
337
returns the starting key.");
340
dbm_firstkey(dbmobject *dp, PyObject *unused)
345
check_dbmobject_open(dp);
346
key = gdbm_firstkey(dp->di_dbm);
348
v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
358
PyDoc_STRVAR(dbm_nextkey__doc__,
359
"nextkey(key) -> next_key\n\
360
Returns the key that follows key in the traversal.\n\
361
The following code prints every key in the database db, without having\n\
362
to create a list in memory that contains them all:\n\
370
dbm_nextkey(dbmobject *dp, PyObject *args)
375
if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
377
check_dbmobject_open(dp);
378
nextkey = gdbm_nextkey(dp->di_dbm, key);
380
v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
390
PyDoc_STRVAR(dbm_reorganize__doc__,
391
"reorganize() -> None\n\
392
If you have carried out a lot of deletions and would like to shrink\n\
393
the space used by the GDBM file, this routine will reorganize the\n\
394
database. GDBM will not shorten the length of a database file except\n\
395
by using this reorganization; otherwise, deleted file space will be\n\
396
kept and reused as new (key,value) pairs are added.");
399
dbm_reorganize(dbmobject *dp, PyObject *unused)
401
check_dbmobject_open(dp);
403
if (gdbm_reorganize(dp->di_dbm) < 0) {
405
PyErr_SetFromErrno(DbmError);
407
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
414
PyDoc_STRVAR(dbm_sync__doc__,
416
When the database has been opened in fast mode, this method forces\n\
417
any unwritten data to be written to the disk.");
420
dbm_sync(dbmobject *dp, PyObject *unused)
422
check_dbmobject_open(dp);
423
gdbm_sync(dp->di_dbm);
429
dbm__enter__(PyObject *self, PyObject *args)
436
dbm__exit__(PyObject *self, PyObject *args)
438
_Py_IDENTIFIER(close);
439
return _PyObject_CallMethodId(self, &PyId_close, NULL);
442
static PyMethodDef dbm_methods[] = {
443
{"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
444
{"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
445
{"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
446
{"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
447
{"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
448
{"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
449
{"get", (PyCFunction)dbm_get, METH_VARARGS, dbm_get__doc__},
450
{"setdefault",(PyCFunction)dbm_setdefault,METH_VARARGS, dbm_setdefault__doc__},
451
{"__enter__", dbm__enter__, METH_NOARGS, NULL},
452
{"__exit__", dbm__exit__, METH_VARARGS, NULL},
453
{NULL, NULL} /* sentinel */
456
static PyTypeObject Dbmtype = {
457
PyVarObject_HEAD_INIT(0, 0)
461
(destructor)dbm_dealloc, /*tp_dealloc*/
468
&dbm_as_sequence, /*tp_as_sequence*/
469
&dbm_as_mapping, /*tp_as_mapping*/
476
Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
477
gdbm_object__doc__, /*tp_doc*/
480
0, /*tp_richcompare*/
481
0, /*tp_weaklistoffset*/
484
dbm_methods, /*tp_methods*/
487
/* ----------------------------------------------------------------- */
489
PyDoc_STRVAR(dbmopen__doc__,
490
"open(filename, [flags, [mode]]) -> dbm_object\n\
491
Open a dbm database and return a dbm object. The filename argument is\n\
492
the name of the database file.\n\
494
The optional flags argument can be 'r' (to open an existing database\n\
495
for reading only -- default), 'w' (to open an existing database for\n\
496
reading and writing), 'c' (which creates the database if it doesn't\n\
497
exist), or 'n' (which always creates a new empty database).\n\
499
Some versions of gdbm support additional flags which must be\n\
500
appended to one of the flags described above. The module constant\n\
501
'open_flags' is a string of valid additional flags. The 'f' flag\n\
502
opens the database in fast mode; altered data will not automatically\n\
503
be written to the disk after every change. This results in faster\n\
504
writes to the database, but may result in an inconsistent database\n\
505
if the program crashes while the database is still open. Use the\n\
506
sync() method to force any unwritten data to be written to the disk.\n\
507
The 's' flag causes all database operations to be synchronized to\n\
508
disk. The 'u' flag disables locking of the database file.\n\
510
The optional mode argument is the Unix mode of the file, used only\n\
511
when the database has to be created. It defaults to octal 0666. ");
514
dbmopen(PyObject *self, PyObject *args)
521
if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
525
iflags = GDBM_READER;
528
iflags = GDBM_WRITER;
531
iflags = GDBM_WRCREAT;
537
PyErr_SetString(DbmError,
538
"First flag must be one of 'r', 'w', 'c' or 'n'");
541
for (flags++; *flags != '\0'; flags++) {
556
iflags |= GDBM_NOLOCK;
560
PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
562
PyErr_SetString(DbmError, buf);
567
return newdbmobject(name, iflags, mode);
570
static char dbmmodule_open_flags[] = "rwcn"
582
static PyMethodDef dbmmodule_methods[] = {
583
{ "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
588
static struct PyModuleDef _gdbmmodule = {
589
PyModuleDef_HEAD_INIT,
604
if (PyType_Ready(&Dbmtype) < 0)
606
m = PyModule_Create(&_gdbmmodule);
609
d = PyModule_GetDict(m);
610
DbmError = PyErr_NewException("_gdbm.error", PyExc_IOError, NULL);
611
if (DbmError != NULL) {
612
PyDict_SetItemString(d, "error", DbmError);
613
s = PyUnicode_FromString(dbmmodule_open_flags);
614
PyDict_SetItemString(d, "open_flags", s);