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
));
181 static PyMappingMethods dbm_as_mapping
= {
182 (lenfunc
)dbm_length
, /*mp_length*/
183 (binaryfunc
)dbm_subscript
, /*mp_subscript*/
184 (objobjargproc
)dbm_ass_sub
, /*mp_ass_subscript*/
187 PyDoc_STRVAR(dbm_close__doc__
,
189 Closes the database.");
192 dbm_close(register dbmobject
*dp
, PyObject
*unused
)
195 gdbm_close(dp
->di_dbm
);
201 PyDoc_STRVAR(dbm_keys__doc__
,
202 "keys() -> list_of_keys\n\
203 Get a list of all keys in the database.");
206 dbm_keys(register dbmobject
*dp
, PyObject
*unused
)
208 register PyObject
*v
, *item
;
212 if (dp
== NULL
|| !is_dbmobject(dp
)) {
213 PyErr_BadInternalCall();
216 check_dbmobject_open(dp
);
222 key
= gdbm_firstkey(dp
->di_dbm
);
224 item
= PyString_FromStringAndSize(key
.dptr
, key
.dsize
);
230 err
= PyList_Append(v
, item
);
237 nextkey
= gdbm_nextkey(dp
->di_dbm
, key
);
244 PyDoc_STRVAR(dbm_has_key__doc__
,
245 "has_key(key) -> boolean\n\
246 Find out whether or not the database contains a given key.");
249 dbm_has_key(register dbmobject
*dp
, PyObject
*args
)
253 if (!PyArg_ParseTuple(args
, "s#:has_key", &key
.dptr
, &key
.dsize
))
255 check_dbmobject_open(dp
);
256 return PyInt_FromLong((long) gdbm_exists(dp
->di_dbm
, key
));
259 PyDoc_STRVAR(dbm_firstkey__doc__
,
260 "firstkey() -> key\n\
261 It's possible to loop over every key in the database using this method\n\
262 and the nextkey() method. The traversal is ordered by GDBM's internal\n\
263 hash values, and won't be sorted by the key values. This method\n\
264 returns the starting key.");
267 dbm_firstkey(register dbmobject
*dp
, PyObject
*unused
)
269 register PyObject
*v
;
272 check_dbmobject_open(dp
);
273 key
= gdbm_firstkey(dp
->di_dbm
);
275 v
= PyString_FromStringAndSize(key
.dptr
, key
.dsize
);
285 PyDoc_STRVAR(dbm_nextkey__doc__
,
286 "nextkey(key) -> next_key\n\
287 Returns the key that follows key in the traversal.\n\
288 The following code prints every key in the database db, without having\n\
289 to create a list in memory that contains them all:\n\
297 dbm_nextkey(register dbmobject
*dp
, PyObject
*args
)
299 register PyObject
*v
;
302 if (!PyArg_ParseTuple(args
, "s#:nextkey", &key
.dptr
, &key
.dsize
))
304 check_dbmobject_open(dp
);
305 nextkey
= gdbm_nextkey(dp
->di_dbm
, key
);
307 v
= PyString_FromStringAndSize(nextkey
.dptr
, nextkey
.dsize
);
317 PyDoc_STRVAR(dbm_reorganize__doc__
,
318 "reorganize() -> None\n\
319 If you have carried out a lot of deletions and would like to shrink\n\
320 the space used by the GDBM file, this routine will reorganize the\n\
321 database. GDBM will not shorten the length of a database file except\n\
322 by using this reorganization; otherwise, deleted file space will be\n\
323 kept and reused as new (key,value) pairs are added.");
326 dbm_reorganize(register dbmobject
*dp
, PyObject
*unused
)
328 check_dbmobject_open(dp
);
330 if (gdbm_reorganize(dp
->di_dbm
) < 0) {
332 PyErr_SetFromErrno(DbmError
);
334 PyErr_SetString(DbmError
, gdbm_strerror(gdbm_errno
));
341 PyDoc_STRVAR(dbm_sync__doc__
,
343 When the database has been opened in fast mode, this method forces\n\
344 any unwritten data to be written to the disk.");
347 dbm_sync(register dbmobject
*dp
, PyObject
*unused
)
349 check_dbmobject_open(dp
);
350 gdbm_sync(dp
->di_dbm
);
355 static PyMethodDef dbm_methods
[] = {
356 {"close", (PyCFunction
)dbm_close
, METH_NOARGS
, dbm_close__doc__
},
357 {"keys", (PyCFunction
)dbm_keys
, METH_NOARGS
, dbm_keys__doc__
},
358 {"has_key", (PyCFunction
)dbm_has_key
, METH_VARARGS
, dbm_has_key__doc__
},
359 {"firstkey", (PyCFunction
)dbm_firstkey
,METH_NOARGS
, dbm_firstkey__doc__
},
360 {"nextkey", (PyCFunction
)dbm_nextkey
, METH_VARARGS
, dbm_nextkey__doc__
},
361 {"reorganize",(PyCFunction
)dbm_reorganize
,METH_NOARGS
, dbm_reorganize__doc__
},
362 {"sync", (PyCFunction
)dbm_sync
, METH_NOARGS
, dbm_sync__doc__
},
363 {NULL
, NULL
} /* sentinel */
367 dbm_getattr(dbmobject
*dp
, char *name
)
369 return Py_FindMethod(dbm_methods
, (PyObject
*)dp
, name
);
372 static PyTypeObject Dbmtype
= {
373 PyVarObject_HEAD_INIT(0, 0)
377 (destructor
)dbm_dealloc
, /*tp_dealloc*/
379 (getattrfunc
)dbm_getattr
, /*tp_getattr*/
384 0, /*tp_as_sequence*/
385 &dbm_as_mapping
, /*tp_as_mapping*/
393 gdbm_object__doc__
, /*tp_doc*/
396 /* ----------------------------------------------------------------- */
398 PyDoc_STRVAR(dbmopen__doc__
,
399 "open(filename, [flags, [mode]]) -> dbm_object\n\
400 Open a dbm database and return a dbm object. The filename argument is\n\
401 the name of the database file.\n\
403 The optional flags argument can be 'r' (to open an existing database\n\
404 for reading only -- default), 'w' (to open an existing database for\n\
405 reading and writing), 'c' (which creates the database if it doesn't\n\
406 exist), or 'n' (which always creates a new empty database).\n\
408 Some versions of gdbm support additional flags which must be\n\
409 appended to one of the flags described above. The module constant\n\
410 'open_flags' is a string of valid additional flags. The 'f' flag\n\
411 opens the database in fast mode; altered data will not automatically\n\
412 be written to the disk after every change. This results in faster\n\
413 writes to the database, but may result in an inconsistent database\n\
414 if the program crashes while the database is still open. Use the\n\
415 sync() method to force any unwritten data to be written to the disk.\n\
416 The 's' flag causes all database operations to be synchronized to\n\
417 disk. The 'u' flag disables locking of the database file.\n\
419 The optional mode argument is the Unix mode of the file, used only\n\
420 when the database has to be created. It defaults to octal 0666. ");
423 dbmopen(PyObject
*self
, PyObject
*args
)
430 if (!PyArg_ParseTuple(args
, "s|si:open", &name
, &flags
, &mode
))
434 iflags
= GDBM_READER
;
437 iflags
= GDBM_WRITER
;
440 iflags
= GDBM_WRCREAT
;
446 PyErr_SetString(DbmError
,
447 "First flag must be one of 'r', 'w', 'c' or 'n'");
450 for (flags
++; *flags
!= '\0'; flags
++) {
465 iflags
|= GDBM_NOLOCK
;
469 PyOS_snprintf(buf
, sizeof(buf
), "Flag '%c' is not supported.",
471 PyErr_SetString(DbmError
, buf
);
476 return newdbmobject(name
, iflags
, mode
);
479 static char dbmmodule_open_flags
[] = "rwcn"
491 static PyMethodDef dbmmodule_methods
[] = {
492 { "open", (PyCFunction
)dbmopen
, METH_VARARGS
, dbmopen__doc__
},
500 Dbmtype
.ob_type
= &PyType_Type
;
501 m
= Py_InitModule4("gdbm", dbmmodule_methods
,
502 gdbmmodule__doc__
, (PyObject
*)NULL
,
506 d
= PyModule_GetDict(m
);
507 DbmError
= PyErr_NewException("gdbm.error", NULL
, NULL
);
508 if (DbmError
!= NULL
) {
509 PyDict_SetItemString(d
, "error", DbmError
);
510 s
= PyString_FromString(dbmmodule_open_flags
);
511 PyDict_SetItemString(d
, "open_flags", s
);