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 */