2 Python wrappers for TDB module
4 Copyright (C) Tim Potter, 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 NOTE: Since tdb is licenced under the GPL any program that uses these bindings
23 must be distributed under the GPL license terms since this is what
26 http://www.gnu.org/licenses/gpl-faq.html#IfInterpreterIsGPL
34 PyObject *py_tdb_error;
36 /* tdb handle object */
43 PyTypeObject tdb_hnd_type;
45 PyObject *new_tdb_hnd_object(TDB_CONTEXT *tdb)
49 obj = PyObject_New(tdb_hnd_object, &tdb_hnd_type);
52 return (PyObject *)obj;
55 PyObject *py_tdb_close(PyObject *self, PyObject *args)
59 if (!PyArg_ParseTuple(args, "O!", &tdb_hnd_type, &obj))
62 if (tdb_close(obj->tdb) == -1) {
64 PyErr_SetString(py_tdb_error, strerror(errno));
74 PyObject *py_tdb_open(PyObject *self, PyObject *args, PyObject *kw)
76 static char *kwlist[] = { "name", "hash_size", "tdb_flags",
77 "open_flags", "mode", NULL };
79 int hash_size = 0, flags = TDB_DEFAULT, open_flags = -1, open_mode = 0600;
82 if (!PyArg_ParseTupleAndKeywords(
83 args, kw, "s|iiii", kwlist, &name, &hash_size, &flags,
84 &open_flags, &open_mode))
87 /* Default open_flags to read/write */
89 if (open_flags == -1) {
90 if (access(name, W_OK) == -1)
91 open_flags = O_RDONLY;
96 if (!(tdb = tdb_open(name, hash_size, flags, open_flags, open_mode))) {
97 PyErr_SetString(py_tdb_error, strerror(errno));
101 return new_tdb_hnd_object(tdb);
105 * Allow a tdb to act as a python mapping (dictionary)
108 static int tdb_traverse_count(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
111 /* Do nothing - tdb_traverse will return the number of records
117 static int tdb_hnd_length(tdb_hnd_object *obj)
121 result = tdb_traverse(obj->tdb, tdb_traverse_count, NULL);
126 static PyObject *tdb_hnd_subscript(tdb_hnd_object *obj, PyObject *key)
131 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize))
134 drec = tdb_fetch(obj->tdb, krec);
137 PyErr_SetString(PyExc_KeyError,
138 PyString_AsString(key));
142 result = PyString_FromStringAndSize(drec.dptr, drec.dsize);
148 static int tdb_ass_subscript(tdb_hnd_object *obj, PyObject *key, PyObject *value)
152 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) {
153 PyErr_SetString(PyExc_TypeError,
154 "tdb mappings have string indices only");
160 py_tdb_error, "tdb object has been closed");
168 if (tdb_delete(obj->tdb, krec) == -1) {
169 PyErr_SetString(PyExc_KeyError,
170 PyString_AsString(value));
178 if (!PyArg_Parse(value, "s#", &drec.dptr, &drec.dsize)) {
179 PyErr_SetString(PyExc_TypeError,
180 "tdb mappings have string elements only");
186 if (tdb_store(obj->tdb, krec, drec, 0) < 0 ) {
188 PyErr_SetFromErrno(py_tdb_error);
192 (char *)tdb_errorstr(obj->tdb));
201 static PyMappingMethods tdb_mapping = {
202 (inquiry) tdb_hnd_length,
203 (binaryfunc) tdb_hnd_subscript,
204 (objobjargproc) tdb_ass_subscript
211 /* Return non-zero if a given key exists in the tdb */
213 PyObject *py_tdb_hnd_has_key(PyObject *self, PyObject *args)
215 tdb_hnd_object *obj = (tdb_hnd_object *)self;
218 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
223 py_tdb_error, "tdb object has been closed");
227 return PyInt_FromLong(tdb_exists(obj->tdb, key));
230 /* Return a list of keys in the tdb */
232 static int tdb_traverse_keys(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
235 PyObject *key_list = (PyObject *)state;
237 PyList_Append(key_list,
238 PyString_FromStringAndSize(key.dptr, key.dsize));
243 PyObject *py_tdb_hnd_keys(PyObject *self, PyObject *args)
245 tdb_hnd_object *obj = (tdb_hnd_object *)self;
246 PyObject *key_list = PyList_New(0);
249 PyErr_SetString(py_tdb_error, "tdb object has been closed");
253 if (tdb_traverse(obj->tdb, tdb_traverse_keys, key_list) == -1) {
254 PyErr_SetString(py_tdb_error, "error traversing tdb");
262 PyObject *py_tdb_hnd_first_key(PyObject *self, PyObject *args)
264 tdb_hnd_object *obj = (tdb_hnd_object *)self;
268 PyErr_SetString(py_tdb_error, "tdb object has been closed");
272 key = tdb_firstkey(obj->tdb);
274 return Py_BuildValue("s#", key.dptr, key.dsize);
277 PyObject *py_tdb_hnd_next_key(PyObject *self, PyObject *py_oldkey)
279 tdb_hnd_object *obj = (tdb_hnd_object *)self;
280 TDB_DATA key, oldkey;
283 PyErr_SetString(py_tdb_error, "tdb object has been closed");
287 if (!PyArg_Parse(py_oldkey, "s#", &oldkey.dptr, &oldkey.dsize))
290 key = tdb_nextkey(obj->tdb, oldkey);
292 return Py_BuildValue("s#", key.dptr, key.dsize);
299 PyObject *py_tdb_hnd_lock_all(PyObject *self, PyObject *args)
301 tdb_hnd_object *obj = (tdb_hnd_object *)self;
305 PyErr_SetString(py_tdb_error, "tdb object has been closed");
309 result = tdb_lockall(obj->tdb);
311 return PyInt_FromLong(result != -1);
314 PyObject *py_tdb_hnd_unlock_all(PyObject *self, PyObject *args)
316 tdb_hnd_object *obj = (tdb_hnd_object *)self;
319 PyErr_SetString(py_tdb_error, "tdb object has been closed");
323 tdb_unlockall(obj->tdb);
329 /* Return an array of keys from a python object which must be a string or a
332 static BOOL make_lock_list(PyObject *py_keys, TDB_DATA **keys, int *num_keys)
334 /* Are we a list or a string? */
336 if (!PyList_Check(py_keys) && !PyString_Check(py_keys)) {
337 PyErr_SetString(PyExc_TypeError, "arg must be list of string");
341 if (PyList_Check(py_keys)) {
344 /* Turn python list into array of keys */
346 *num_keys = PyList_Size(py_keys);
347 *keys = (TDB_DATA *)malloc(sizeof(TDB_DATA) * (*num_keys));
349 for (i = 0; i < *num_keys; i++) {
350 PyObject *key = PyList_GetItem(py_keys, i);
352 if (!PyString_Check(key)) {
355 "list elements must be strings");
359 PyArg_Parse(key, "s#", &(*keys)[i].dptr,
365 /* Turn python string into a single key */
367 *keys = (TDB_DATA *)malloc(sizeof(TDB_DATA));
369 PyArg_Parse(py_keys, "s#", &(*keys)->dptr, &(*keys)->dsize);
375 PyObject *py_tdb_hnd_lock(PyObject *self, PyObject *args)
377 tdb_hnd_object *obj = (tdb_hnd_object *)self;
380 int num_keys, result;
383 PyErr_SetString(py_tdb_error, "tdb object has been closed");
387 if (!PyArg_ParseTuple(args, "O", &py_keys))
390 if (!make_lock_list(py_keys, &keys, &num_keys))
393 result = tdb_lockkeys(obj->tdb, num_keys, keys);
397 return PyInt_FromLong(result != -1);
400 PyObject *py_tdb_hnd_unlock(PyObject *self, PyObject *args)
402 tdb_hnd_object *obj = (tdb_hnd_object *)self;
405 PyErr_SetString(py_tdb_error, "tdb object has been closed");
409 if (!PyArg_ParseTuple(args, ""))
412 tdb_unlockkeys(obj->tdb);
422 struct traverse_info {
427 static int tdb_traverse_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
430 struct traverse_info *info = state;
431 PyObject *arglist, *py_result;
434 arglist = Py_BuildValue("(s#s#O)", key.dptr, key.dsize, value.dptr,
435 value.dsize, info->state);
437 py_result = PyEval_CallObject(info->callback, arglist);
441 if (!PyInt_Check(py_result)) {
442 result = 1; /* Hmm - non-integer object returned by callback */
446 result = PyInt_AsLong(py_result);
449 Py_DECREF(py_result);
453 PyObject *py_tdb_hnd_traverse(PyObject *self, PyObject *args, PyObject *kw)
455 tdb_hnd_object *obj = (tdb_hnd_object *)self;
456 static char *kwlist[] = { "traverse_fn", "state", NULL };
457 PyObject *state = Py_None, *callback;
458 struct traverse_info info;
461 if (!PyArg_ParseTupleAndKeywords(
462 args, kw, "O|O", kwlist, &callback, &state))
465 if (!PyCallable_Check(callback)) {
466 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
473 info.callback = callback;
476 result = tdb_traverse(obj->tdb, tdb_traverse_traverse, &info);
481 return PyInt_FromLong(result);
485 * Method dispatch table for this module
488 static PyMethodDef tdb_methods[] = {
489 { "open", (PyCFunction)py_tdb_open, METH_VARARGS | METH_KEYWORDS },
490 { "close", (PyCFunction)py_tdb_close, METH_VARARGS },
495 * Methods on a tdb object
498 static PyMethodDef tdb_hnd_methods[] = {
499 { "keys", (PyCFunction)py_tdb_hnd_keys, METH_VARARGS },
500 { "has_key", (PyCFunction)py_tdb_hnd_has_key, METH_VARARGS },
501 { "first_key", (PyCFunction)py_tdb_hnd_first_key, METH_VARARGS },
502 { "next_key", (PyCFunction)py_tdb_hnd_next_key, METH_VARARGS },
503 { "lock_all", (PyCFunction)py_tdb_hnd_lock_all, METH_VARARGS },
504 { "unlock_all", (PyCFunction)py_tdb_hnd_unlock_all, METH_VARARGS },
505 { "lock", (PyCFunction)py_tdb_hnd_lock, METH_VARARGS },
506 { "unlock", (PyCFunction)py_tdb_hnd_unlock, METH_VARARGS },
507 { "traverse", (PyCFunction)py_tdb_hnd_traverse, METH_VARARGS | METH_KEYWORDS },
511 /* Deallocate a tdb handle object */
513 static void tdb_hnd_dealloc(PyObject* self)
515 tdb_hnd_object *hnd = (tdb_hnd_object *)self;
523 /* Return tdb handle attributes */
525 static PyObject *tdb_hnd_getattr(PyObject *self, char *attrname)
527 return Py_FindMethod(tdb_hnd_methods, self, attrname);
530 static char tdb_hnd_type_doc[] =
531 "Python wrapper for tdb.";
533 PyTypeObject tdb_hnd_type = {
534 PyObject_HEAD_INIT(NULL)
537 sizeof(tdb_hnd_object),
539 tdb_hnd_dealloc, /* tp_dealloc*/
541 tdb_hnd_getattr, /* tp_getattr*/
546 0, /* tp_as_sequence*/
547 &tdb_mapping, /* tp_as_mapping*/
554 Py_TPFLAGS_DEFAULT, /* tp_flags */
555 tdb_hnd_type_doc, /* tp_doc */
560 static struct const_vals {
563 } module_const_vals[] = {
565 /* Flags for tdb_open() */
567 { "TDB_DEFAULT", TDB_DEFAULT },
568 { "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST },
569 { "TDB_INTERNAL", TDB_INTERNAL },
570 { "TDB_NOLOCK", TDB_NOLOCK },
571 { "TDB_NOMMAP", TDB_NOMMAP },
572 { "TDB_CONVERT", TDB_CONVERT },
573 { "TDB_BIGENDIAN", TDB_BIGENDIAN },
578 static void const_init(PyObject *dict)
580 struct const_vals *tmp;
583 for (tmp = module_const_vals; tmp->name; tmp++) {
584 obj = PyInt_FromLong(tmp->value);
585 PyDict_SetItemString(dict, tmp->name, obj);
590 /* Module initialisation */
594 PyObject *module, *dict;
596 /* Initialise module */
598 module = Py_InitModule("tdb", tdb_methods);
599 dict = PyModule_GetDict(module);
601 py_tdb_error = PyErr_NewException("tdb.error", NULL, NULL);
602 PyDict_SetItemString(dict, "error", py_tdb_error);
604 /* Initialise policy handle object */
606 tdb_hnd_type.ob_type = &PyType_Type;
608 PyDict_SetItemString(dict, "tdb.hnd",
609 (PyObject *)&tdb_hnd_type);
611 /* Initialise constants */