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 2 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, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 /* This symbol is used in both includes.h and Python.h which causes an
28 annoying compiler warning. */
38 PyObject
*py_tdb_error
;
40 /* tdb handle object */
47 PyTypeObject tdb_hnd_type
;
49 PyObject
*new_tdb_hnd_object(TDB_CONTEXT
*tdb
)
53 obj
= PyObject_New(tdb_hnd_object
, &tdb_hnd_type
);
56 return (PyObject
*)obj
;
59 PyObject
*py_tdb_close(PyObject
*self
, PyObject
*args
)
63 if (!PyArg_ParseTuple(args
, "O!", &tdb_hnd_type
, &obj
))
66 if (tdb_close(obj
->tdb
) == -1) {
68 PyErr_SetString(py_tdb_error
, strerror(errno
));
78 PyObject
*py_tdb_open(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
80 static char *kwlist
[] = { "name", "hash_size", "tdb_flags",
81 "open_flags", "mode", NULL
};
83 int hash_size
= 0, flags
= TDB_DEFAULT
, open_flags
= -1, open_mode
= 0600;
86 if (!PyArg_ParseTupleAndKeywords(
87 args
, kw
, "s|iiii", kwlist
, &name
, &hash_size
, &flags
,
88 &open_flags
, &open_mode
))
91 /* Default open_flags to read/write */
93 if (open_flags
== -1) {
94 if (access(name
, W_OK
) == -1)
95 open_flags
= O_RDONLY
;
100 if (!(tdb
= tdb_open(name
, hash_size
, flags
, open_flags
, open_mode
))) {
101 PyErr_SetString(py_tdb_error
, strerror(errno
));
105 return new_tdb_hnd_object(tdb
);
109 * Allow a tdb to act as a python mapping (dictionary)
112 static int tdb_traverse_count(TDB_CONTEXT
*tdb
, TDB_DATA key
, TDB_DATA value
,
115 /* Do nothing - tdb_traverse will return the number of records
121 static int tdb_hnd_length(tdb_hnd_object
*obj
)
125 result
= tdb_traverse(obj
->tdb
, tdb_traverse_count
, NULL
);
130 static PyObject
*tdb_hnd_subscript(tdb_hnd_object
*obj
, PyObject
*key
)
135 if (!PyArg_Parse(key
, "s#", &krec
.dptr
, &krec
.dsize
))
138 drec
= tdb_fetch(obj
->tdb
, krec
);
141 PyErr_SetString(PyExc_KeyError
,
142 PyString_AsString(key
));
146 result
= PyString_FromStringAndSize(drec
.dptr
, drec
.dsize
);
152 static int tdb_ass_subscript(tdb_hnd_object
*obj
, PyObject
*key
, PyObject
*value
)
156 if (!PyArg_Parse(key
, "s#", &krec
.dptr
, &krec
.dsize
)) {
157 PyErr_SetString(PyExc_TypeError
,
158 "tdb mappings have string indices only");
164 py_tdb_error
, "tdb object has been closed");
172 if (tdb_delete(obj
->tdb
, krec
) == -1) {
173 PyErr_SetString(PyExc_KeyError
,
174 PyString_AsString(value
));
182 if (!PyArg_Parse(value
, "s#", &drec
.dptr
, &drec
.dsize
)) {
183 PyErr_SetString(PyExc_TypeError
,
184 "tdb mappings have string elements only");
190 if (tdb_store(obj
->tdb
, krec
, drec
, 0) < 0 ) {
192 PyErr_SetFromErrno(py_tdb_error
);
196 (char *)tdb_errorstr(obj
->tdb
));
205 static PyMappingMethods tdb_mapping
= {
206 (inquiry
) tdb_hnd_length
,
207 (binaryfunc
) tdb_hnd_subscript
,
208 (objobjargproc
) tdb_ass_subscript
215 /* Return non-zero if a given key exists in the tdb */
217 PyObject
*py_tdb_hnd_has_key(PyObject
*self
, PyObject
*args
)
219 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
222 if (!PyArg_ParseTuple(args
, "s#", &key
.dptr
, &key
.dsize
))
227 py_tdb_error
, "tdb object has been closed");
231 return PyInt_FromLong(tdb_exists(obj
->tdb
, key
));
234 /* Return a list of keys in the tdb */
236 static int tdb_traverse_keys(TDB_CONTEXT
*tdb
, TDB_DATA key
, TDB_DATA value
,
239 PyObject
*key_list
= (PyObject
*)state
;
241 PyList_Append(key_list
,
242 PyString_FromStringAndSize(key
.dptr
, key
.dsize
));
247 PyObject
*py_tdb_hnd_keys(PyObject
*self
, PyObject
*args
)
249 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
250 PyObject
*key_list
= PyList_New(0);
253 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
257 if (tdb_traverse(obj
->tdb
, tdb_traverse_keys
, key_list
) == -1) {
258 PyErr_SetString(py_tdb_error
, "error traversing tdb");
266 PyObject
*py_tdb_hnd_first_key(PyObject
*self
, PyObject
*args
)
268 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
272 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
276 key
= tdb_firstkey(obj
->tdb
);
278 return Py_BuildValue("s#", key
.dptr
, key
.dsize
);
281 PyObject
*py_tdb_hnd_next_key(PyObject
*self
, PyObject
*py_oldkey
)
283 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
284 TDB_DATA key
, oldkey
;
287 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
291 if (!PyArg_Parse(py_oldkey
, "s#", &oldkey
.dptr
, &oldkey
.dsize
))
294 key
= tdb_nextkey(obj
->tdb
, oldkey
);
296 return Py_BuildValue("s#", key
.dptr
, key
.dsize
);
303 PyObject
*py_tdb_hnd_lock_all(PyObject
*self
, PyObject
*args
)
305 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
309 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
313 result
= tdb_lockall(obj
->tdb
);
315 return PyInt_FromLong(result
!= -1);
318 PyObject
*py_tdb_hnd_unlock_all(PyObject
*self
, PyObject
*args
)
320 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
323 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
327 tdb_unlockall(obj
->tdb
);
333 /* Return an array of keys from a python object which must be a string or a
336 static BOOL
make_lock_list(PyObject
*py_keys
, TDB_DATA
**keys
, int *num_keys
)
338 /* Are we a list or a string? */
340 if (!PyList_Check(py_keys
) && !PyString_Check(py_keys
)) {
341 PyErr_SetString(PyExc_TypeError
, "arg must be list of string");
345 if (PyList_Check(py_keys
)) {
348 /* Turn python list into array of keys */
350 *num_keys
= PyList_Size(py_keys
);
351 *keys
= (TDB_DATA
*)SMB_XMALLOC_ARRAY(TDB_DATA
, (*num_keys
));
353 for (i
= 0; i
< *num_keys
; i
++) {
354 PyObject
*key
= PyList_GetItem(py_keys
, i
);
356 if (!PyString_Check(key
)) {
359 "list elements must be strings");
363 PyArg_Parse(key
, "s#", &(*keys
)[i
].dptr
,
369 /* Turn python string into a single key */
371 *keys
= (TDB_DATA
*)SMB_XMALLOC_P(TDB_DATA
);
373 PyArg_Parse(py_keys
, "s#", &(*keys
)->dptr
, &(*keys
)->dsize
);
383 struct traverse_info
{
388 static int tdb_traverse_traverse(TDB_CONTEXT
*tdb
, TDB_DATA key
, TDB_DATA value
,
391 struct traverse_info
*info
= state
;
392 PyObject
*arglist
, *py_result
;
395 arglist
= Py_BuildValue("(s#s#O)", key
.dptr
, key
.dsize
, value
.dptr
,
396 value
.dsize
, info
->state
);
398 py_result
= PyEval_CallObject(info
->callback
, arglist
);
402 if (!PyInt_Check(py_result
)) {
403 result
= 1; /* Hmm - non-integer object returned by callback */
407 result
= PyInt_AsLong(py_result
);
410 Py_DECREF(py_result
);
414 PyObject
*py_tdb_hnd_traverse(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
416 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
417 static char *kwlist
[] = { "traverse_fn", "state", NULL
};
418 PyObject
*state
= Py_None
, *callback
;
419 struct traverse_info info
;
422 if (!PyArg_ParseTupleAndKeywords(
423 args
, kw
, "O|O", kwlist
, &callback
, &state
))
426 if (!PyCallable_Check(callback
)) {
427 PyErr_SetString(PyExc_TypeError
, "parameter must be callable");
434 info
.callback
= callback
;
437 result
= tdb_traverse(obj
->tdb
, tdb_traverse_traverse
, &info
);
442 return PyInt_FromLong(result
);
445 PyObject
*py_tdb_hnd_chainlock(PyObject
*self
, PyObject
*args
)
447 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
452 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
456 if (!PyArg_ParseTuple(args
, "s#", &key
.dptr
, &key
.dsize
))
459 result
= tdb_chainlock(obj
->tdb
, key
);
461 return PyInt_FromLong(result
!= -1);
464 PyObject
*py_tdb_hnd_chainunlock(PyObject
*self
, PyObject
*args
)
466 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
471 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
475 if (!PyArg_ParseTuple(args
, "s#", &key
.dptr
, &key
.dsize
))
478 result
= tdb_chainunlock(obj
->tdb
, key
);
480 return PyInt_FromLong(result
!= -1);
483 PyObject
*py_tdb_hnd_lock_bystring(PyObject
*self
, PyObject
*args
)
485 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
486 int result
, timeout
= 30;
490 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
494 if (!PyArg_ParseTuple(args
, "s|i", &s
, &timeout
))
497 result
= tdb_lock_bystring_with_timeout(obj
->tdb
, s
, timeout
);
499 return PyInt_FromLong(result
!= -1);
502 PyObject
*py_tdb_hnd_unlock_bystring(PyObject
*self
, PyObject
*args
)
504 tdb_hnd_object
*obj
= (tdb_hnd_object
*)self
;
508 PyErr_SetString(py_tdb_error
, "tdb object has been closed");
512 if (!PyArg_ParseTuple(args
, "s", &s
))
515 tdb_unlock_bystring(obj
->tdb
, s
);
522 * Method dispatch table for this module
525 static PyMethodDef tdb_methods
[] = {
526 { "open", (PyCFunction
)py_tdb_open
, METH_VARARGS
| METH_KEYWORDS
},
527 { "close", (PyCFunction
)py_tdb_close
, METH_VARARGS
},
532 * Methods on a tdb object
535 static PyMethodDef tdb_hnd_methods
[] = {
536 { "keys", (PyCFunction
)py_tdb_hnd_keys
, METH_VARARGS
},
537 { "has_key", (PyCFunction
)py_tdb_hnd_has_key
, METH_VARARGS
},
538 { "first_key", (PyCFunction
)py_tdb_hnd_first_key
, METH_VARARGS
},
539 { "next_key", (PyCFunction
)py_tdb_hnd_next_key
, METH_VARARGS
},
540 { "lock_all", (PyCFunction
)py_tdb_hnd_lock_all
, METH_VARARGS
},
541 { "unlock_all", (PyCFunction
)py_tdb_hnd_unlock_all
, METH_VARARGS
},
542 { "traverse", (PyCFunction
)py_tdb_hnd_traverse
, METH_VARARGS
| METH_KEYWORDS
},
543 { "chainlock", (PyCFunction
)py_tdb_hnd_chainlock
, METH_VARARGS
| METH_KEYWORDS
},
544 { "chainunlock", (PyCFunction
)py_tdb_hnd_chainunlock
, METH_VARARGS
| METH_KEYWORDS
},
545 { "lock_bystring", (PyCFunction
)py_tdb_hnd_lock_bystring
, METH_VARARGS
| METH_KEYWORDS
},
546 { "unlock_bystring", (PyCFunction
)py_tdb_hnd_unlock_bystring
, METH_VARARGS
| METH_KEYWORDS
},
550 /* Deallocate a tdb handle object */
552 static void tdb_hnd_dealloc(PyObject
* self
)
554 tdb_hnd_object
*hnd
= (tdb_hnd_object
*)self
;
562 /* Return tdb handle attributes */
564 static PyObject
*tdb_hnd_getattr(PyObject
*self
, char *attrname
)
566 return Py_FindMethod(tdb_hnd_methods
, self
, attrname
);
569 static char tdb_hnd_type_doc
[] =
570 "Python wrapper for tdb.";
572 PyTypeObject tdb_hnd_type
= {
573 PyObject_HEAD_INIT(NULL
)
576 sizeof(tdb_hnd_object
),
578 tdb_hnd_dealloc
, /* tp_dealloc*/
580 tdb_hnd_getattr
, /* tp_getattr*/
585 0, /* tp_as_sequence*/
586 &tdb_mapping
, /* tp_as_mapping*/
593 Py_TPFLAGS_DEFAULT
, /* tp_flags */
594 tdb_hnd_type_doc
, /* tp_doc */
599 static struct const_vals
{
602 } module_const_vals
[] = {
604 /* Flags for tdb_open() */
606 { "TDB_DEFAULT", TDB_DEFAULT
},
607 { "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST
},
608 { "TDB_INTERNAL", TDB_INTERNAL
},
609 { "TDB_NOLOCK", TDB_NOLOCK
},
610 { "TDB_NOMMAP", TDB_NOMMAP
},
611 { "TDB_CONVERT", TDB_CONVERT
},
612 { "TDB_BIGENDIAN", TDB_BIGENDIAN
},
617 static void const_init(PyObject
*dict
)
619 struct const_vals
*tmp
;
622 for (tmp
= module_const_vals
; tmp
->name
; tmp
++) {
623 obj
= PyInt_FromLong(tmp
->value
);
624 PyDict_SetItemString(dict
, tmp
->name
, obj
);
629 /* Module initialisation */
633 PyObject
*module
, *dict
;
635 /* Initialise module */
637 module
= Py_InitModule("tdb", tdb_methods
);
638 dict
= PyModule_GetDict(module
);
640 py_tdb_error
= PyErr_NewException("tdb.error", NULL
, NULL
);
641 PyDict_SetItemString(dict
, "error", py_tdb_error
);
643 /* Initialise policy handle object */
645 tdb_hnd_type
.ob_type
= &PyType_Type
;
647 PyDict_SetItemString(dict
, "tdb.hnd",
648 (PyObject
*)&tdb_hnd_type
);
650 /* Initialise constants */