2 Python wrappers for TDB module
4 Copyright (C) Tim Potter, 2002-2003
6 ** NOTE! The following LGPL license applies to the tdb python
7 ** scripting library. This does NOT imply that all of Samba is
8 ** released under the LGPL
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 /* This symbol is used in both includes.h and Python.h which causes an
27 annoying compiler warning. */
37 PyObject *py_tdb_error;
39 /* tdb handle object */
46 PyTypeObject tdb_hnd_type;
48 PyObject *new_tdb_hnd_object(TDB_CONTEXT *tdb)
52 obj = PyObject_New(tdb_hnd_object, &tdb_hnd_type);
55 return (PyObject *)obj;
58 PyObject *py_tdb_close(PyObject *self, PyObject *args)
62 if (!PyArg_ParseTuple(args, "O!", &tdb_hnd_type, &obj))
65 if (tdb_close(obj->tdb) == -1) {
67 PyErr_SetString(py_tdb_error, strerror(errno));
77 PyObject *py_tdb_open(PyObject *self, PyObject *args, PyObject *kw)
79 static char *kwlist[] = { "name", "hash_size", "tdb_flags",
80 "open_flags", "mode", NULL };
82 int hash_size = 0, flags = TDB_DEFAULT, open_flags = -1, open_mode = 0600;
85 if (!PyArg_ParseTupleAndKeywords(
86 args, kw, "s|iiii", kwlist, &name, &hash_size, &flags,
87 &open_flags, &open_mode))
90 /* Default open_flags to read/write */
92 if (open_flags == -1) {
93 if (access(name, W_OK) == -1)
94 open_flags = O_RDONLY;
99 if (!(tdb = tdb_open(name, hash_size, flags, open_flags, open_mode))) {
100 PyErr_SetString(py_tdb_error, strerror(errno));
104 return new_tdb_hnd_object(tdb);
108 * Allow a tdb to act as a python mapping (dictionary)
111 static int tdb_traverse_count(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
114 /* Do nothing - tdb_traverse will return the number of records
120 static int tdb_hnd_length(tdb_hnd_object *obj)
124 result = tdb_traverse(obj->tdb, tdb_traverse_count, NULL);
129 static PyObject *tdb_hnd_subscript(tdb_hnd_object *obj, PyObject *key)
134 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize))
137 drec = tdb_fetch(obj->tdb, krec);
140 PyErr_SetString(PyExc_KeyError,
141 PyString_AsString(key));
145 result = PyString_FromStringAndSize(drec.dptr, drec.dsize);
151 static int tdb_ass_subscript(tdb_hnd_object *obj, PyObject *key, PyObject *value)
155 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) {
156 PyErr_SetString(PyExc_TypeError,
157 "tdb mappings have string indices only");
163 py_tdb_error, "tdb object has been closed");
171 if (tdb_delete(obj->tdb, krec) == -1) {
172 PyErr_SetString(PyExc_KeyError,
173 PyString_AsString(value));
181 if (!PyArg_Parse(value, "s#", &drec.dptr, &drec.dsize)) {
182 PyErr_SetString(PyExc_TypeError,
183 "tdb mappings have string elements only");
189 if (tdb_store(obj->tdb, krec, drec, 0) < 0 ) {
191 PyErr_SetFromErrno(py_tdb_error);
195 (char *)tdb_errorstr(obj->tdb));
204 static PyMappingMethods tdb_mapping = {
205 (inquiry) tdb_hnd_length,
206 (binaryfunc) tdb_hnd_subscript,
207 (objobjargproc) tdb_ass_subscript
214 /* Return non-zero if a given key exists in the tdb */
216 PyObject *py_tdb_hnd_has_key(PyObject *self, PyObject *args)
218 tdb_hnd_object *obj = (tdb_hnd_object *)self;
221 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
226 py_tdb_error, "tdb object has been closed");
230 return PyInt_FromLong(tdb_exists(obj->tdb, key));
233 /* Return a list of keys in the tdb */
235 static int tdb_traverse_keys(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
238 PyObject *key_list = (PyObject *)state;
240 PyList_Append(key_list,
241 PyString_FromStringAndSize(key.dptr, key.dsize));
246 PyObject *py_tdb_hnd_keys(PyObject *self, PyObject *args)
248 tdb_hnd_object *obj = (tdb_hnd_object *)self;
249 PyObject *key_list = PyList_New(0);
252 PyErr_SetString(py_tdb_error, "tdb object has been closed");
256 if (tdb_traverse(obj->tdb, tdb_traverse_keys, key_list) == -1) {
257 PyErr_SetString(py_tdb_error, "error traversing tdb");
265 PyObject *py_tdb_hnd_first_key(PyObject *self, PyObject *args)
267 tdb_hnd_object *obj = (tdb_hnd_object *)self;
271 PyErr_SetString(py_tdb_error, "tdb object has been closed");
275 key = tdb_firstkey(obj->tdb);
277 return Py_BuildValue("s#", key.dptr, key.dsize);
280 PyObject *py_tdb_hnd_next_key(PyObject *self, PyObject *py_oldkey)
282 tdb_hnd_object *obj = (tdb_hnd_object *)self;
283 TDB_DATA key, oldkey;
286 PyErr_SetString(py_tdb_error, "tdb object has been closed");
290 if (!PyArg_Parse(py_oldkey, "s#", &oldkey.dptr, &oldkey.dsize))
293 key = tdb_nextkey(obj->tdb, oldkey);
295 return Py_BuildValue("s#", key.dptr, key.dsize);
302 PyObject *py_tdb_hnd_lock_all(PyObject *self, PyObject *args)
304 tdb_hnd_object *obj = (tdb_hnd_object *)self;
308 PyErr_SetString(py_tdb_error, "tdb object has been closed");
312 result = tdb_lockall(obj->tdb);
314 return PyInt_FromLong(result != -1);
317 PyObject *py_tdb_hnd_unlock_all(PyObject *self, PyObject *args)
319 tdb_hnd_object *obj = (tdb_hnd_object *)self;
322 PyErr_SetString(py_tdb_error, "tdb object has been closed");
326 tdb_unlockall(obj->tdb);
332 /* Return an array of keys from a python object which must be a string or a
335 static BOOL make_lock_list(PyObject *py_keys, TDB_DATA **keys, int *num_keys)
337 /* Are we a list or a string? */
339 if (!PyList_Check(py_keys) && !PyString_Check(py_keys)) {
340 PyErr_SetString(PyExc_TypeError, "arg must be list of string");
344 if (PyList_Check(py_keys)) {
347 /* Turn python list into array of keys */
349 *num_keys = PyList_Size(py_keys);
350 *keys = (TDB_DATA *)SMB_XMALLOC_ARRAY(TDB_DATA, (*num_keys));
352 for (i = 0; i < *num_keys; i++) {
353 PyObject *key = PyList_GetItem(py_keys, i);
355 if (!PyString_Check(key)) {
358 "list elements must be strings");
362 PyArg_Parse(key, "s#", &(*keys)[i].dptr,
368 /* Turn python string into a single key */
370 *keys = (TDB_DATA *)SMB_XMALLOC_P(TDB_DATA);
372 PyArg_Parse(py_keys, "s#", &(*keys)->dptr, &(*keys)->dsize);
382 struct traverse_info {
387 static int tdb_traverse_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
390 struct traverse_info *info = state;
391 PyObject *arglist, *py_result;
394 arglist = Py_BuildValue("(s#s#O)", key.dptr, key.dsize, value.dptr,
395 value.dsize, info->state);
397 py_result = PyEval_CallObject(info->callback, arglist);
401 if (!PyInt_Check(py_result)) {
402 result = 1; /* Hmm - non-integer object returned by callback */
406 result = PyInt_AsLong(py_result);
409 Py_DECREF(py_result);
413 PyObject *py_tdb_hnd_traverse(PyObject *self, PyObject *args, PyObject *kw)
415 tdb_hnd_object *obj = (tdb_hnd_object *)self;
416 static char *kwlist[] = { "traverse_fn", "state", NULL };
417 PyObject *state = Py_None, *callback;
418 struct traverse_info info;
421 if (!PyArg_ParseTupleAndKeywords(
422 args, kw, "O|O", kwlist, &callback, &state))
425 if (!PyCallable_Check(callback)) {
426 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
433 info.callback = callback;
436 result = tdb_traverse(obj->tdb, tdb_traverse_traverse, &info);
441 return PyInt_FromLong(result);
444 PyObject *py_tdb_hnd_chainlock(PyObject *self, PyObject *args)
446 tdb_hnd_object *obj = (tdb_hnd_object *)self;
451 PyErr_SetString(py_tdb_error, "tdb object has been closed");
455 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
458 result = tdb_chainlock(obj->tdb, key);
460 return PyInt_FromLong(result != -1);
463 PyObject *py_tdb_hnd_chainunlock(PyObject *self, PyObject *args)
465 tdb_hnd_object *obj = (tdb_hnd_object *)self;
470 PyErr_SetString(py_tdb_error, "tdb object has been closed");
474 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
477 result = tdb_chainunlock(obj->tdb, key);
479 return PyInt_FromLong(result != -1);
482 PyObject *py_tdb_hnd_lock_bystring(PyObject *self, PyObject *args)
484 tdb_hnd_object *obj = (tdb_hnd_object *)self;
485 int result, timeout = 30;
489 PyErr_SetString(py_tdb_error, "tdb object has been closed");
493 if (!PyArg_ParseTuple(args, "s|i", &s, &timeout))
496 result = tdb_lock_bystring_with_timeout(obj->tdb, s, timeout);
498 return PyInt_FromLong(result != -1);
501 PyObject *py_tdb_hnd_unlock_bystring(PyObject *self, PyObject *args)
503 tdb_hnd_object *obj = (tdb_hnd_object *)self;
507 PyErr_SetString(py_tdb_error, "tdb object has been closed");
511 if (!PyArg_ParseTuple(args, "s", &s))
514 tdb_unlock_bystring(obj->tdb, s);
521 * Method dispatch table for this module
524 static PyMethodDef tdb_methods[] = {
525 { "open", (PyCFunction)py_tdb_open, METH_VARARGS | METH_KEYWORDS },
526 { "close", (PyCFunction)py_tdb_close, METH_VARARGS },
531 * Methods on a tdb object
534 static PyMethodDef tdb_hnd_methods[] = {
535 { "keys", (PyCFunction)py_tdb_hnd_keys, METH_VARARGS },
536 { "has_key", (PyCFunction)py_tdb_hnd_has_key, METH_VARARGS },
537 { "first_key", (PyCFunction)py_tdb_hnd_first_key, METH_VARARGS },
538 { "next_key", (PyCFunction)py_tdb_hnd_next_key, METH_VARARGS },
539 { "lock_all", (PyCFunction)py_tdb_hnd_lock_all, METH_VARARGS },
540 { "unlock_all", (PyCFunction)py_tdb_hnd_unlock_all, METH_VARARGS },
541 { "traverse", (PyCFunction)py_tdb_hnd_traverse, METH_VARARGS | METH_KEYWORDS },
542 { "chainlock", (PyCFunction)py_tdb_hnd_chainlock, METH_VARARGS | METH_KEYWORDS },
543 { "chainunlock", (PyCFunction)py_tdb_hnd_chainunlock, METH_VARARGS | METH_KEYWORDS },
544 { "lock_bystring", (PyCFunction)py_tdb_hnd_lock_bystring, METH_VARARGS | METH_KEYWORDS },
545 { "unlock_bystring", (PyCFunction)py_tdb_hnd_unlock_bystring, METH_VARARGS | METH_KEYWORDS },
549 /* Deallocate a tdb handle object */
551 static void tdb_hnd_dealloc(PyObject* self)
553 tdb_hnd_object *hnd = (tdb_hnd_object *)self;
561 /* Return tdb handle attributes */
563 static PyObject *tdb_hnd_getattr(PyObject *self, char *attrname)
565 return Py_FindMethod(tdb_hnd_methods, self, attrname);
568 static char tdb_hnd_type_doc[] =
569 "Python wrapper for tdb.";
571 PyTypeObject tdb_hnd_type = {
572 PyObject_HEAD_INIT(NULL)
575 sizeof(tdb_hnd_object),
577 tdb_hnd_dealloc, /* tp_dealloc*/
579 tdb_hnd_getattr, /* tp_getattr*/
584 0, /* tp_as_sequence*/
585 &tdb_mapping, /* tp_as_mapping*/
592 Py_TPFLAGS_DEFAULT, /* tp_flags */
593 tdb_hnd_type_doc, /* tp_doc */
598 static struct const_vals {
601 } module_const_vals[] = {
603 /* Flags for tdb_open() */
605 { "TDB_DEFAULT", TDB_DEFAULT },
606 { "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST },
607 { "TDB_INTERNAL", TDB_INTERNAL },
608 { "TDB_NOLOCK", TDB_NOLOCK },
609 { "TDB_NOMMAP", TDB_NOMMAP },
610 { "TDB_CONVERT", TDB_CONVERT },
611 { "TDB_BIGENDIAN", TDB_BIGENDIAN },
616 static void const_init(PyObject *dict)
618 struct const_vals *tmp;
621 for (tmp = module_const_vals; tmp->name; tmp++) {
622 obj = PyInt_FromLong(tmp->value);
623 PyDict_SetItemString(dict, tmp->name, obj);
628 /* Module initialisation */
632 PyObject *module, *dict;
634 /* Initialise module */
636 module = Py_InitModule("tdb", tdb_methods);
637 dict = PyModule_GetDict(module);
639 py_tdb_error = PyErr_NewException("tdb.error", NULL, NULL);
640 PyDict_SetItemString(dict, "error", py_tdb_error);
642 /* Initialise policy handle object */
644 tdb_hnd_type.ob_type = &PyType_Type;
646 PyDict_SetItemString(dict, "tdb.hnd",
647 (PyObject *)&tdb_hnd_type);
649 /* Initialise constants */