pyldb: Add a text-based interface for Python 3
authorPetr Viktorin <pviktori@redhat.com>
Thu, 18 Jun 2015 11:43:27 +0000 (13:43 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Tue, 21 Jul 2015 17:04:15 +0000 (19:04 +0200)
Signed-off-by: Petr Viktorin <pviktori@redhat.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
lib/tdb/_tdb_text.py [new file with mode: 0644]
lib/tdb/pytdb.c
lib/tdb/wscript

diff --git a/lib/tdb/_tdb_text.py b/lib/tdb/_tdb_text.py
new file mode 100644 (file)
index 0000000..c823bf8
--- /dev/null
@@ -0,0 +1,138 @@
+# Text wrapper for tdb bindings
+#
+# Copyright (C) 2015 Petr Viktorin <pviktori@redhat.com>
+# Published under the GNU LGPLv3 or later
+
+import sys
+import functools
+
+import tdb
+
+
+class TdbTextWrapper(object):
+    """Text interface for a TDB file"""
+
+    def __init__(self, tdb):
+        self._tdb = tdb
+
+    @property
+    def raw(self):
+        return self._tdb
+
+    def get(self, key):
+        key = key.encode('utf-8')
+        result = self._tdb.get(key)
+        if result is not None:
+            return result.decode('utf-8')
+
+    def append(self, key, value):
+        key = key.encode('utf-8')
+        value = value.encode('utf-8')
+        self._tdb.append(key, value)
+
+    def firstkey(self):
+        result = self._tdb.firstkey()
+        if result:
+            return result.decode('utf-8')
+
+    def nextkey(self, key):
+        key = key.encode('utf-8')
+        result = self._tdb.nextkey(key)
+        if result is not None:
+            return result.decode('utf-8')
+
+    def delete(self, key):
+        key = key.encode('utf-8')
+        self._tdb.delete(key)
+
+    def store(self, key, value):
+        key = key.encode('utf-8')
+        value = value.encode('utf-8')
+        self._tdb.store(key, value)
+
+    def __iter__(self):
+        for key in iter(self._tdb):
+            yield key.decode('utf-8')
+
+    def __getitem__(self, key):
+        key = key.encode('utf-8')
+        result = self._tdb[key]
+        return result.decode('utf-8')
+
+    def __contains__(self, key):
+        key = key.encode('utf-8')
+        return key in self._tdb
+
+    def __repr__(self):
+        return '<TdbTextWrapper for %r>' % self._tdb
+
+    def __setitem__(self, key, value):
+        key = key.encode('utf-8')
+        value = value.encode('utf-8')
+        self._tdb[key] = value
+
+    def __delitem__(self, key):
+        key = key.encode('utf-8')
+        del self._tdb[key]
+
+    if sys.version_info > (3, 0):
+        keys = __iter__
+    else:
+        iterkeys = __iter__
+        has_key = __contains__
+
+
+## Add wrappers for functions and getters that don't deal with text
+
+def _add_wrapper(name):
+    orig = getattr(tdb.Tdb, name)
+
+    def wrapper(self, *args, **kwargs):
+        return orig(self._tdb, *args, **kwargs)
+    wrapper.__name__ = orig.__name__
+    wrapper.__doc__ = orig.__doc__
+
+    setattr(TdbTextWrapper, name, wrapper)
+
+for name in ("transaction_cancel",
+             "transaction_commit",
+             "transaction_prepare_commit",
+             "transaction_start",
+             "reopen",
+             "lock_all",
+             "unlock_all",
+             "read_lock_all",
+             "read_unlock_all",
+             "close",
+             "add_flags",
+             "remove_flags",
+             "clear",
+             "repack",
+             "enable_seqnum",
+             "increment_seqnum_nonblock",
+            ):
+    _add_wrapper(name)
+
+
+def _add_getter(name):
+    orig = getattr(tdb.Tdb, name)
+    doc = orig.__doc__
+
+    def getter(self):
+        return getattr(self._tdb, name)
+
+    def setter(self, value):
+        return setattr(self._tdb, name, value)
+
+    setattr(TdbTextWrapper, name, property(getter, setter, doc=doc))
+
+for name in ("hash_size",
+             "map_size",
+             "freelist_size",
+             "flags",
+             "max_dead",
+             "filename",
+             "seqnum",
+             "text",
+            ):
+    _add_getter(name)
index 7f7c14513ea6a3ff1ea0d8996cebaddd862f5fca..b0f9cd961d77774e2f3e88321a03da5c861ac7fb 100644 (file)
@@ -581,6 +581,22 @@ static PyObject *obj_get_seqnum(PyTdbObject *self, void *closure)
        return PyInt_FromLong(tdb_get_seqnum(self->ctx));
 }
 
+static PyObject *obj_get_text(PyTdbObject *self, void *closure)
+{
+       PyObject *mod, *cls, *inst;
+       mod = PyImport_ImportModule("_tdb_text");
+       if (mod == NULL)
+               return NULL;
+       cls = PyObject_GetAttrString(mod, "TdbTextWrapper");
+       if (cls == NULL) {
+               Py_DECREF(mod);
+               return NULL;
+       }
+       inst = PyObject_CallFunction(cls, discard_const_p(char, "O"), self);
+       Py_DECREF(mod);
+       Py_DECREF(cls);
+       return inst;
+}
 
 static PyGetSetDef tdb_object_getsetters[] = {
        { discard_const_p(char, "hash_size"),
@@ -598,6 +614,8 @@ static PyGetSetDef tdb_object_getsetters[] = {
          discard_const_p(char, "The filename of this TDB file.") },
        { discard_const_p(char, "seqnum"),
          (getter)obj_get_seqnum, NULL, NULL },
+       { discard_const_p(char, "text"),
+         (getter)obj_get_text, NULL, NULL },
        { NULL }
 };
 
index 3b446975404754bc7dc3287ac6b239bb1af4679c..556dceb03d070d5f55f0400593c50ba7d193f429 100644 (file)
@@ -187,6 +187,13 @@ def build(bld):
                              realname='tdb.so',
                              cflags='-DPACKAGE_VERSION=\"%s\"' % VERSION)
 
+        for env in bld.gen_python_environments(['PKGCONFIGDIR']):
+            bld.SAMBA_SCRIPT('_tdb_text.py',
+                             pattern='_tdb_text.py',
+                             installdir='python')
+
+            bld.INSTALL_FILES('${PYTHONARCHDIR}', '_tdb_text.py')
+
 def testonly(ctx):
     '''run tdb testsuite'''
     import Utils, samba_utils, shutil