2 /* DBM module using dictionary interface */
3 /* Author: Anthony Baxter, after dbmmodule.c */
4 /* Doc strings: Mitch Chapman */
15 #include "gdbmerrno.h"
16 extern const char * gdbm_strerror(gdbm_error
);
19 static char 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 staticforward PyTypeObject Dbmtype
;
39 #define is_dbmobject(v) ((v)->ob_type == &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 static char 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) {
102 for (key
=gdbm_firstkey(dp
->di_dbm
); key
.dptr
;
103 key
= gdbm_nextkey(dp
->di_dbm
,okey
)) {
105 if(okey
.dsize
) free(okey
.dptr
);
114 dbm_subscript(dbmobject
*dp
, register PyObject
*key
)
119 if (!PyArg_Parse(key
, "s#", &krec
.dptr
, &krec
.dsize
) )
122 if (dp
->di_dbm
== NULL
) {
123 PyErr_SetString(DbmError
,
124 "GDBM object has already been closed");
127 drec
= gdbm_fetch(dp
->di_dbm
, krec
);
128 if (drec
.dptr
== 0) {
129 PyErr_SetString(PyExc_KeyError
,
130 PyString_AS_STRING((PyStringObject
*)key
));
133 v
= PyString_FromStringAndSize(drec
.dptr
, drec
.dsize
);
139 dbm_ass_sub(dbmobject
*dp
, PyObject
*v
, PyObject
*w
)
143 if (!PyArg_Parse(v
, "s#", &krec
.dptr
, &krec
.dsize
) ) {
144 PyErr_SetString(PyExc_TypeError
,
145 "gdbm mappings have string indices only");
148 if (dp
->di_dbm
== NULL
) {
149 PyErr_SetString(DbmError
,
150 "GDBM object has already been closed");
155 if (gdbm_delete(dp
->di_dbm
, krec
) < 0) {
156 PyErr_SetString(PyExc_KeyError
,
157 PyString_AS_STRING((PyStringObject
*)v
));
162 if (!PyArg_Parse(w
, "s#", &drec
.dptr
, &drec
.dsize
)) {
163 PyErr_SetString(PyExc_TypeError
,
164 "gdbm mappings have string elements only");
168 if (gdbm_store(dp
->di_dbm
, krec
, drec
, GDBM_REPLACE
) < 0) {
170 PyErr_SetFromErrno(DbmError
);
172 PyErr_SetString(DbmError
,
173 gdbm_strerror(gdbm_errno
));
180 static PyMappingMethods dbm_as_mapping
= {
181 (inquiry
)dbm_length
, /*mp_length*/
182 (binaryfunc
)dbm_subscript
, /*mp_subscript*/
183 (objobjargproc
)dbm_ass_sub
, /*mp_ass_subscript*/
186 static char dbm_close__doc__
[] = "\
188 Closes the database.";
191 dbm_close(register dbmobject
*dp
, PyObject
*args
)
193 if (!PyArg_ParseTuple(args
, ":close"))
196 gdbm_close(dp
->di_dbm
);
202 static char dbm_keys__doc__
[] = "\
203 keys() -> list_of_keys\n\
204 Get a list of all keys in the database.";
207 dbm_keys(register dbmobject
*dp
, PyObject
*args
)
209 register PyObject
*v
, *item
;
213 if (dp
== NULL
|| !is_dbmobject(dp
)) {
214 PyErr_BadInternalCall();
217 if (!PyArg_ParseTuple(args
, ":keys"))
220 check_dbmobject_open(dp
);
226 key
= gdbm_firstkey(dp
->di_dbm
);
228 item
= PyString_FromStringAndSize(key
.dptr
, key
.dsize
);
234 err
= PyList_Append(v
, item
);
241 nextkey
= gdbm_nextkey(dp
->di_dbm
, key
);
248 static char dbm_has_key__doc__
[] = "\
249 has_key(key) -> boolean\n\
250 Find out whether or not the database contains a given key.";
253 dbm_has_key(register dbmobject
*dp
, PyObject
*args
)
257 if (!PyArg_ParseTuple(args
, "s#:has_key", &key
.dptr
, &key
.dsize
))
259 check_dbmobject_open(dp
);
260 return PyInt_FromLong((long) gdbm_exists(dp
->di_dbm
, key
));
263 static char dbm_firstkey__doc__
[] = "\
265 It's possible to loop over every key in the database using this method\n\
266 and the nextkey() method. The traversal is ordered by GDBM's internal\n\
267 hash values, and won't be sorted by the key values. This method\n\
268 returns the starting key.";
271 dbm_firstkey(register dbmobject
*dp
, PyObject
*args
)
273 register PyObject
*v
;
276 if (!PyArg_ParseTuple(args
, ":firstkey"))
278 check_dbmobject_open(dp
);
279 key
= gdbm_firstkey(dp
->di_dbm
);
281 v
= PyString_FromStringAndSize(key
.dptr
, key
.dsize
);
291 static char dbm_nextkey__doc__
[] = "\
292 nextkey(key) -> next_key\n\
293 Returns the key that follows key in the traversal.\n\
294 The following code prints every key in the database db, without having\n\
295 to create a list in memory that contains them all:\n\
303 dbm_nextkey(register dbmobject
*dp
, PyObject
*args
)
305 register PyObject
*v
;
308 if (!PyArg_ParseTuple(args
, "s#:nextkey", &key
.dptr
, &key
.dsize
))
310 check_dbmobject_open(dp
);
311 nextkey
= gdbm_nextkey(dp
->di_dbm
, key
);
313 v
= PyString_FromStringAndSize(nextkey
.dptr
, nextkey
.dsize
);
323 static char dbm_reorganize__doc__
[] = "\
324 reorganize() -> None\n\
325 If you have carried out a lot of deletions and would like to shrink\n\
326 the space used by the GDBM file, this routine will reorganize the\n\
327 database. GDBM will not shorten the length of a database file except\n\
328 by using this reorganization; otherwise, deleted file space will be\n\
329 kept and reused as new (key,value) pairs are added.";
332 dbm_reorganize(register dbmobject
*dp
, PyObject
*args
)
334 if (!PyArg_ParseTuple(args
, ":reorganize"))
336 check_dbmobject_open(dp
);
338 if (gdbm_reorganize(dp
->di_dbm
) < 0) {
340 PyErr_SetFromErrno(DbmError
);
342 PyErr_SetString(DbmError
, gdbm_strerror(gdbm_errno
));
349 static char dbm_sync__doc__
[] = "\
351 When the database has been opened in fast mode, this method forces\n\
352 any unwritten data to be written to the disk.";
355 dbm_sync(register dbmobject
*dp
, PyObject
*args
)
357 if (!PyArg_ParseTuple(args
, ":sync"))
359 check_dbmobject_open(dp
);
360 gdbm_sync(dp
->di_dbm
);
365 static PyMethodDef dbm_methods
[] = {
366 {"close", (PyCFunction
)dbm_close
, METH_VARARGS
, dbm_close__doc__
},
367 {"keys", (PyCFunction
)dbm_keys
, METH_VARARGS
, dbm_keys__doc__
},
368 {"has_key", (PyCFunction
)dbm_has_key
, METH_VARARGS
, dbm_has_key__doc__
},
369 {"firstkey", (PyCFunction
)dbm_firstkey
,METH_VARARGS
, dbm_firstkey__doc__
},
370 {"nextkey", (PyCFunction
)dbm_nextkey
, METH_VARARGS
, dbm_nextkey__doc__
},
371 {"reorganize",(PyCFunction
)dbm_reorganize
,METH_VARARGS
, dbm_reorganize__doc__
},
372 {"sync", (PyCFunction
)dbm_sync
, METH_VARARGS
, dbm_sync__doc__
},
373 {NULL
, NULL
} /* sentinel */
377 dbm_getattr(dbmobject
*dp
, char *name
)
379 return Py_FindMethod(dbm_methods
, (PyObject
*)dp
, name
);
382 static PyTypeObject Dbmtype
= {
383 PyObject_HEAD_INIT(0)
388 (destructor
)dbm_dealloc
, /*tp_dealloc*/
390 (getattrfunc
)dbm_getattr
, /*tp_getattr*/
395 0, /*tp_as_sequence*/
396 &dbm_as_mapping
, /*tp_as_mapping*/
404 gdbm_object__doc__
, /*tp_doc*/
407 /* ----------------------------------------------------------------- */
409 static char dbmopen__doc__
[] = "\
410 open(filename, [flags, [mode]]) -> dbm_object\n\
411 Open a dbm database and return a dbm object. The filename argument is\n\
412 the name of the database file.\n\
414 The optional flags argument can be 'r' (to open an existing database\n\
415 for reading only -- default), 'w' (to open an existing database for\n\
416 reading and writing), 'c' (which creates the database if it doesn't\n\
417 exist), or 'n' (which always creates a new empty database).\n\
419 Some versions of gdbm support additional flags which must be\n\
420 appended to one of the flags described above. The module constant\n\
421 'open_flags' is a string of valid additional flags. The 'f' flag\n\
422 opens the database in fast mode; altered data will not automatically\n\
423 be written to the disk after every change. This results in faster\n\
424 writes to the database, but may result in an inconsistent database\n\
425 if the program crashes while the database is still open. Use the\n\
426 sync() method to force any unwritten data to be written to the disk.\n\
427 The 's' flag causes all database operations to be synchronized to\n\
428 disk. The 'u' flag disables locking of the database file.\n\
430 The optional mode argument is the Unix mode of the file, used only\n\
431 when the database has to be created. It defaults to octal 0666. ";
434 dbmopen(PyObject
*self
, PyObject
*args
)
441 if (!PyArg_ParseTuple(args
, "s|si:open", &name
, &flags
, &mode
))
445 iflags
= GDBM_READER
;
448 iflags
= GDBM_WRITER
;
451 iflags
= GDBM_WRCREAT
;
457 PyErr_SetString(DbmError
,
458 "First flag must be one of 'r', 'w', 'c' or 'n'");
461 for (flags
++; *flags
!= '\0'; flags
++) {
476 iflags
|= GDBM_NOLOCK
;
480 sprintf(buf
, "Flag '%c' is not supported.", *flags
);
481 PyErr_SetString(DbmError
, buf
);
486 return newdbmobject(name
, iflags
, mode
);
489 static char dbmmodule_open_flags
[] = "rwcn"
501 static PyMethodDef dbmmodule_methods
[] = {
502 { "open", (PyCFunction
)dbmopen
, METH_VARARGS
, dbmopen__doc__
},
510 Dbmtype
.ob_type
= &PyType_Type
;
511 m
= Py_InitModule4("gdbm", dbmmodule_methods
,
512 gdbmmodule__doc__
, (PyObject
*)NULL
,
514 d
= PyModule_GetDict(m
);
515 DbmError
= PyErr_NewException("gdbm.error", NULL
, NULL
);
516 if (DbmError
!= NULL
) {
517 PyDict_SetItemString(d
, "error", DbmError
);
518 PyDict_SetItemString(d
, "open_flags",
519 PyString_FromString(dbmmodule_open_flags
));