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(register 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
, register 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_SetString(PyExc_KeyError
,
131 PyString_AS_STRING((PyStringObject
*)key
));
134 v
= PyString_FromStringAndSize(drec
.dptr
, drec
.dsize
);
140 dbm_ass_sub(dbmobject
*dp
, PyObject
*v
, PyObject
*w
)
144 if (!PyArg_Parse(v
, "s#", &krec
.dptr
, &krec
.dsize
) ) {
145 PyErr_SetString(PyExc_TypeError
,
146 "gdbm mappings have string indices only");
149 if (dp
->di_dbm
== NULL
) {
150 PyErr_SetString(DbmError
,
151 "GDBM object has already been closed");
156 if (gdbm_delete(dp
->di_dbm
, krec
) < 0) {
157 PyErr_SetString(PyExc_KeyError
,
158 PyString_AS_STRING((PyStringObject
*)v
));
163 if (!PyArg_Parse(w
, "s#", &drec
.dptr
, &drec
.dsize
)) {
164 PyErr_SetString(PyExc_TypeError
,
165 "gdbm mappings have string elements only");
169 if (gdbm_store(dp
->di_dbm
, krec
, drec
, GDBM_REPLACE
) < 0) {
171 PyErr_SetFromErrno(DbmError
);
173 PyErr_SetString(DbmError
,
174 gdbm_strerror(gdbm_errno
));
182 dbm_contains(register dbmobject
*dp
, PyObject
*arg
)
186 if ((dp
)->di_dbm
== NULL
) {
187 PyErr_SetString(DbmError
,
188 "GDBM object has already been closed");
191 if (!PyString_Check(arg
)) {
192 PyErr_Format(PyExc_TypeError
,
193 "gdbm key must be string, not %.100s",
194 arg
->ob_type
->tp_name
);
197 key
.dptr
= PyString_AS_STRING(arg
);
198 key
.dsize
= PyString_GET_SIZE(arg
);
199 return gdbm_exists(dp
->di_dbm
, key
);
202 static PySequenceMethods dbm_as_sequence
= {
203 (lenfunc
)dbm_length
, /*_length*/
210 (objobjproc
)dbm_contains
, /*sq_contains*/
211 0, /*sq_inplace_concat*/
212 0 /*sq_inplace_repeat*/
215 static PyMappingMethods dbm_as_mapping
= {
216 (lenfunc
)dbm_length
, /*mp_length*/
217 (binaryfunc
)dbm_subscript
, /*mp_subscript*/
218 (objobjargproc
)dbm_ass_sub
, /*mp_ass_subscript*/
221 PyDoc_STRVAR(dbm_close__doc__
,
223 Closes the database.");
226 dbm_close(register dbmobject
*dp
, PyObject
*unused
)
229 gdbm_close(dp
->di_dbm
);
235 PyDoc_STRVAR(dbm_keys__doc__
,
236 "keys() -> list_of_keys\n\
237 Get a list of all keys in the database.");
240 dbm_keys(register dbmobject
*dp
, PyObject
*unused
)
242 register PyObject
*v
, *item
;
246 if (dp
== NULL
|| !is_dbmobject(dp
)) {
247 PyErr_BadInternalCall();
250 check_dbmobject_open(dp
);
256 key
= gdbm_firstkey(dp
->di_dbm
);
258 item
= PyString_FromStringAndSize(key
.dptr
, key
.dsize
);
264 err
= PyList_Append(v
, item
);
271 nextkey
= gdbm_nextkey(dp
->di_dbm
, key
);
278 PyDoc_STRVAR(dbm_has_key__doc__
,
279 "has_key(key) -> boolean\n\
280 Find out whether or not the database contains a given key.");
283 dbm_has_key(register dbmobject
*dp
, PyObject
*args
)
287 if (!PyArg_ParseTuple(args
, "s#:has_key", &key
.dptr
, &key
.dsize
))
289 check_dbmobject_open(dp
);
290 return PyInt_FromLong((long) gdbm_exists(dp
->di_dbm
, key
));
293 PyDoc_STRVAR(dbm_firstkey__doc__
,
294 "firstkey() -> key\n\
295 It's possible to loop over every key in the database using this method\n\
296 and the nextkey() method. The traversal is ordered by GDBM's internal\n\
297 hash values, and won't be sorted by the key values. This method\n\
298 returns the starting key.");
301 dbm_firstkey(register dbmobject
*dp
, PyObject
*unused
)
303 register PyObject
*v
;
306 check_dbmobject_open(dp
);
307 key
= gdbm_firstkey(dp
->di_dbm
);
309 v
= PyString_FromStringAndSize(key
.dptr
, key
.dsize
);
319 PyDoc_STRVAR(dbm_nextkey__doc__
,
320 "nextkey(key) -> next_key\n\
321 Returns the key that follows key in the traversal.\n\
322 The following code prints every key in the database db, without having\n\
323 to create a list in memory that contains them all:\n\
331 dbm_nextkey(register dbmobject
*dp
, PyObject
*args
)
333 register PyObject
*v
;
336 if (!PyArg_ParseTuple(args
, "s#:nextkey", &key
.dptr
, &key
.dsize
))
338 check_dbmobject_open(dp
);
339 nextkey
= gdbm_nextkey(dp
->di_dbm
, key
);
341 v
= PyString_FromStringAndSize(nextkey
.dptr
, nextkey
.dsize
);
351 PyDoc_STRVAR(dbm_reorganize__doc__
,
352 "reorganize() -> None\n\
353 If you have carried out a lot of deletions and would like to shrink\n\
354 the space used by the GDBM file, this routine will reorganize the\n\
355 database. GDBM will not shorten the length of a database file except\n\
356 by using this reorganization; otherwise, deleted file space will be\n\
357 kept and reused as new (key,value) pairs are added.");
360 dbm_reorganize(register dbmobject
*dp
, PyObject
*unused
)
362 check_dbmobject_open(dp
);
364 if (gdbm_reorganize(dp
->di_dbm
) < 0) {
366 PyErr_SetFromErrno(DbmError
);
368 PyErr_SetString(DbmError
, gdbm_strerror(gdbm_errno
));
375 PyDoc_STRVAR(dbm_sync__doc__
,
377 When the database has been opened in fast mode, this method forces\n\
378 any unwritten data to be written to the disk.");
381 dbm_sync(register dbmobject
*dp
, PyObject
*unused
)
383 check_dbmobject_open(dp
);
384 gdbm_sync(dp
->di_dbm
);
389 static PyMethodDef dbm_methods
[] = {
390 {"close", (PyCFunction
)dbm_close
, METH_NOARGS
, dbm_close__doc__
},
391 {"keys", (PyCFunction
)dbm_keys
, METH_NOARGS
, dbm_keys__doc__
},
392 {"has_key", (PyCFunction
)dbm_has_key
, METH_VARARGS
, dbm_has_key__doc__
},
393 {"firstkey", (PyCFunction
)dbm_firstkey
,METH_NOARGS
, dbm_firstkey__doc__
},
394 {"nextkey", (PyCFunction
)dbm_nextkey
, METH_VARARGS
, dbm_nextkey__doc__
},
395 {"reorganize",(PyCFunction
)dbm_reorganize
,METH_NOARGS
, dbm_reorganize__doc__
},
396 {"sync", (PyCFunction
)dbm_sync
, METH_NOARGS
, dbm_sync__doc__
},
397 {NULL
, NULL
} /* sentinel */
401 dbm_getattr(dbmobject
*dp
, char *name
)
403 return Py_FindMethod(dbm_methods
, (PyObject
*)dp
, name
);
406 static PyTypeObject Dbmtype
= {
407 PyVarObject_HEAD_INIT(0, 0)
411 (destructor
)dbm_dealloc
, /*tp_dealloc*/
413 (getattrfunc
)dbm_getattr
, /*tp_getattr*/
418 &dbm_as_sequence
, /*tp_as_sequence*/
419 &dbm_as_mapping
, /*tp_as_mapping*/
426 Py_TPFLAGS_DEFAULT
, /*tp_xxx4*/
427 gdbm_object__doc__
, /*tp_doc*/
430 /* ----------------------------------------------------------------- */
432 PyDoc_STRVAR(dbmopen__doc__
,
433 "open(filename, [flags, [mode]]) -> dbm_object\n\
434 Open a dbm database and return a dbm object. The filename argument is\n\
435 the name of the database file.\n\
437 The optional flags argument can be 'r' (to open an existing database\n\
438 for reading only -- default), 'w' (to open an existing database for\n\
439 reading and writing), 'c' (which creates the database if it doesn't\n\
440 exist), or 'n' (which always creates a new empty database).\n\
442 Some versions of gdbm support additional flags which must be\n\
443 appended to one of the flags described above. The module constant\n\
444 'open_flags' is a string of valid additional flags. The 'f' flag\n\
445 opens the database in fast mode; altered data will not automatically\n\
446 be written to the disk after every change. This results in faster\n\
447 writes to the database, but may result in an inconsistent database\n\
448 if the program crashes while the database is still open. Use the\n\
449 sync() method to force any unwritten data to be written to the disk.\n\
450 The 's' flag causes all database operations to be synchronized to\n\
451 disk. The 'u' flag disables locking of the database file.\n\
453 The optional mode argument is the Unix mode of the file, used only\n\
454 when the database has to be created. It defaults to octal 0666. ");
457 dbmopen(PyObject
*self
, PyObject
*args
)
464 if (!PyArg_ParseTuple(args
, "s|si:open", &name
, &flags
, &mode
))
468 iflags
= GDBM_READER
;
471 iflags
= GDBM_WRITER
;
474 iflags
= GDBM_WRCREAT
;
480 PyErr_SetString(DbmError
,
481 "First flag must be one of 'r', 'w', 'c' or 'n'");
484 for (flags
++; *flags
!= '\0'; flags
++) {
499 iflags
|= GDBM_NOLOCK
;
503 PyOS_snprintf(buf
, sizeof(buf
), "Flag '%c' is not supported.",
505 PyErr_SetString(DbmError
, buf
);
510 return newdbmobject(name
, iflags
, mode
);
513 static char dbmmodule_open_flags
[] = "rwcn"
525 static PyMethodDef dbmmodule_methods
[] = {
526 { "open", (PyCFunction
)dbmopen
, METH_VARARGS
, dbmopen__doc__
},
534 Dbmtype
.ob_type
= &PyType_Type
;
535 m
= Py_InitModule4("gdbm", dbmmodule_methods
,
536 gdbmmodule__doc__
, (PyObject
*)NULL
,
540 d
= PyModule_GetDict(m
);
541 DbmError
= PyErr_NewException("gdbm.error", NULL
, NULL
);
542 if (DbmError
!= NULL
) {
543 PyDict_SetItemString(d
, "error", DbmError
);
544 s
= PyString_FromString(dbmmodule_open_flags
);
545 PyDict_SetItemString(d
, "open_flags", s
);