From 2a98fd770a2e35c3c297140ae04d29a955dbbba4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 21 Nov 2007 12:31:38 +0100 Subject: r26077: Import updated TDB bindings. (This used to be commit afe091d92ebb1dc15ae3d8df9a5ba8832933a83c) --- source4/lib/tdb/config.mk | 5 +- source4/lib/tdb/python/tests/simple.py | 97 +++++++++++++ source4/lib/tdb/swig/Tdb.py | 119 ---------------- source4/lib/tdb/swig/tdb.i | 152 -------------------- source4/lib/tdb/tdb.i | 252 +++++++++++++++++++++++++++++++++ source4/samba4-skip | 1 + source4/selftest/samba4_tests.sh | 1 + 7 files changed, 353 insertions(+), 274 deletions(-) create mode 100644 source4/lib/tdb/python/tests/simple.py delete mode 100644 source4/lib/tdb/swig/Tdb.py delete mode 100644 source4/lib/tdb/swig/tdb.i create mode 100644 source4/lib/tdb/tdb.i (limited to 'source4') diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index ab90ed728d..d0d1dfb492 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -60,9 +60,8 @@ PRIVATE_DEPENDENCIES = \ ####################### # Start LIBRARY swig_tdb -[LIBRARY::swig_tdb] -LIBRARY_REALNAME = swig/_tdb.$(SHLIBEXT) -OBJ_FILES = swig/tdb_wrap.o +[PYTHON::swig_tdb] +SWIG_FILE = tdb.i PUBLIC_DEPENDENCIES = LIBTDB DYNCONFIG # End LIBRARY swig_tdb ####################### diff --git a/source4/lib/tdb/python/tests/simple.py b/source4/lib/tdb/python/tests/simple.py new file mode 100644 index 0000000000..43d066c4a3 --- /dev/null +++ b/source4/lib/tdb/python/tests/simple.py @@ -0,0 +1,97 @@ +#!/usr/bin/python +# Some simple tests for the Python bindings for TDB +# Note that this tests the interface of the Python bindings +# It does not test tdb itself. +# +# Copyright (C) 2007 Jelmer Vernooij +# Published under the GNU LGPL + +import tdb +from unittest import TestCase +import os + +class SimpleTdbTests(TestCase): + def setUp(self): + super(SimpleTdbTests, self).setUp() + self.tdb = tdb.Tdb(os.tmpnam(), 0, tdb.DEFAULT, os.O_CREAT|os.O_RDWR) + self.assertNotEqual(None, self.tdb) + + def tearDown(self): + del self.tdb + + def test_lockall(self): + self.tdb.lock_all() + + def test_max_dead(self): + self.tdb.max_dead = 20 + + def test_unlockall(self): + self.tdb.lock_all() + self.tdb.unlock_all() + + def test_lockall_read(self): + self.tdb.read_lock_all() + self.tdb.read_unlock_all() + + def test_reopen(self): + self.tdb.reopen() + + def test_store(self): + self.tdb.store("bar", "bla") + self.assertEquals("bla", self.tdb.fetch("bar")) + + def test_fetch(self): + self.tdb["bar"] = "foo" + self.tdb.reopen() + self.assertEquals("foo", self.tdb["bar"]) + + def test_delete(self): + self.tdb["bar"] = "foo" + del self.tdb["bar"] + self.assertRaises(KeyError, lambda: self.tdb["bar"]) + + def test_contains(self): + self.tdb["bla"] = "bloe" + self.assertTrue("bla" in self.tdb) + + def test_keyerror(self): + self.assertRaises(KeyError, lambda: self.tdb["bla"]) + + def test_hash_size(self): + self.tdb.hash_size + + def test_map_size(self): + self.tdb.map_size + + def test_name(self): + self.tdb.name + + def test_iterator(self): + self.tdb["bla"] = "1" + self.tdb["brainslug"] = "2" + self.assertEquals(["bla", "brainslug"], list(self.tdb)) + + def test_items(self): + self.tdb["bla"] = "1" + self.tdb["brainslug"] = "2" + self.assertEquals([("bla", "1"), ("brainslug", "2")], self.tdb.items()) + + def test_transaction_cancel(self): + self.tdb["bloe"] = "2" + self.tdb.transaction_start() + self.tdb["bloe"] = "1" + self.tdb.transaction_cancel() + self.assertEquals("2", self.tdb["bloe"]) + + def test_transaction_commit(self): + self.tdb["bloe"] = "2" + self.tdb.transaction_start() + self.tdb["bloe"] = "1" + self.tdb.transaction_commit() + self.assertEquals("1", self.tdb["bloe"]) + + def test_iterator(self): + self.tdb["bloe"] = "2" + self.tdb["bla"] = "hoi" + i = iter(self.tdb) + self.assertEquals(set(["bloe", "bla"]), set([i.next(), i.next()])) diff --git a/source4/lib/tdb/swig/Tdb.py b/source4/lib/tdb/swig/Tdb.py deleted file mode 100644 index d1a506e69c..0000000000 --- a/source4/lib/tdb/swig/Tdb.py +++ /dev/null @@ -1,119 +0,0 @@ -"""Provide a more Pythonic and object-oriented interface to tdb.""" - -# -# Swig interface to Samba -# -# Copyright (C) Tim Potter 2006 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# - -import os -from tdb import * - -# Open flags - -DEFAULT = TDB_DEFAULT -CLEAR_IF_FIRST = TDB_CLEAR_IF_FIRST -INTERNAL = TDB_INTERNAL -NOLOCK = TDB_NOLOCK -NOMMAP = TDB_NOMMAP - -# Class representing a TDB file - -class Tdb: - - # Create and destroy Tdb objects - - def __init__(self, name, hash_size = 0, flags = TDB_DEFAULT, - open_flags = os.O_RDWR | os.O_CREAT, mode = 0600): - self.tdb = tdb_open(name, hash_size, flags, open_flags, mode) - if self.tdb is None: - raise IOError, tdb_errorstr(self.tdb) - - def __del__(self): - self.close() - - def close(self): - if hasattr(self, 'tdb') and self.tdb is not None: - if tdb_close(self.tdb) == -1: - raise IOError, tdb_errorstr(self.tdb) - self.tdb = None - - # Random access to keys, values - - def __getitem__(self, key): - result = tdb_fetch(self.tdb, key) - if result is None: - raise KeyError, '%s: %s' % (key, tdb_errorstr(self.tdb)) - return result - - def __setitem__(self, key, item): - if tdb_store(self.tdb, key, item) == -1: - raise IOError, tdb_errorstr(self.tdb) - - def __delitem__(self, key): - if not tdb_exists(self.tdb, key): - raise KeyError, '%s: %s' % (key, tdb_errorstr(self.tdb)) - tdb_delete(self.tdb, key) - - def has_key(self, key): - return tdb_exists(self.tdb, key) != 0 - - # Tdb iterator - - class TdbIterator: - def __init__(self, tdb): - self.tdb = tdb - self.key = None - - def __iter__(self): - return self - - def next(self): - if self.key is None: - self.key = tdb_firstkey(self.tdb) - if self.key is None: - raise StopIteration - return self.key - else: - self.key = tdb_nextkey(self.tdb, self.key) - if self.key is None: - raise StopIteration - return self.key - - def __iter__(self): - return Tdb.TdbIterator(self.tdb) - - # Implement other dict functions using TdbIterator - - def keys(self): - return [k for k in iter(self)] - - def values(self): - return [self[k] for k in iter(self)] - - def items(self): - return [(k, self[k]) for k in iter(self)] - - def __len__(self): - return len(self.keys()) - - def clear(self): - for k in iter(self): - del(self[k]) - - # TODO: iterkeys, itervalues, iteritems - - # TODO: any other missing methods for container types diff --git a/source4/lib/tdb/swig/tdb.i b/source4/lib/tdb/swig/tdb.i deleted file mode 100644 index 1ff21f53b5..0000000000 --- a/source4/lib/tdb/swig/tdb.i +++ /dev/null @@ -1,152 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Swig interface to tdb. - - Copyright (C) 2004,2005 Tim Potter - - ** NOTE! The following LGPL license applies to the tdb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -%module tdb - -%{ - -/* This symbol is used in both includes.h and Python.h which causes an - annoying compiler warning. */ - -#ifdef HAVE_FSTAT -#undef HAVE_FSTAT -#endif - -#if (__GNUC__ >= 3) -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif - -/* Include tdb headers */ - -#include "lib/tdb/include/tdb.h" - -%} - -/* The tdb functions will crash if a NULL tdb context is passed */ - -%include exception.i - -%typemap(check) TDB_CONTEXT* { - if ($1 == NULL) - SWIG_exception(SWIG_ValueError, - "tdb context must be non-NULL"); -} - -/* In and out typemaps for the TDB_DATA structure. This is converted to - and from the Python string type which can contain arbitrary binary - data.. */ - -%typemap(in) TDB_DATA { - if (!PyString_Check($input)) { - PyErr_SetString(PyExc_TypeError, "string arg expected"); - return NULL; - } - $1.dsize = PyString_Size($input); - $1.dptr = PyString_AsString($input); -} - -%typemap(out) TDB_DATA { - if ($1.dptr == NULL && $1.dsize == 0) { - $result = Py_None; - } else { - $result = PyString_FromStringAndSize($1.dptr, $1.dsize); - free($1.dptr); - } -} - -/* Treat a mode_t as an unsigned integer */ - -typedef int mode_t; - -/* flags to tdb_store() */ - -#define TDB_REPLACE 1 -#define TDB_INSERT 2 -#define TDB_MODIFY 3 - -/* flags for tdb_open() */ - -#define TDB_DEFAULT 0 /* just a readability place holder */ -#define TDB_CLEAR_IF_FIRST 1 -#define TDB_INTERNAL 2 /* don't store on disk */ -#define TDB_NOLOCK 4 /* don't do any locking */ -#define TDB_NOMMAP 8 /* don't use mmap */ -#define TDB_CONVERT 16 /* convert endian (internal use) */ -#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ - -enum TDB_ERROR { - TDB_SUCCESS=0, - TDB_ERR_CORRUPT, - TDB_ERR_IO, - TDB_ERR_LOCK, - TDB_ERR_OOM, - TDB_ERR_EXISTS, - TDB_ERR_NOLOCK, - TDB_ERR_LOCK_TIMEOUT, - TDB_ERR_NOEXIST, - TDB_ERR_EINVAL, - TDB_ERR_RDONLY -}; - -/* Throw an IOError exception from errno if tdb_open() returns NULL */ - -%exception { - $action - if (result == NULL) { - PyErr_SetFromErrno(PyExc_IOError); - SWIG_fail; - } -} - -TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode); - -%exception; - -enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb); - -const char *tdb_errorstr(TDB_CONTEXT *tdb); - -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); - -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); - -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag = TDB_REPLACE); - -int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf); - -int tdb_close(TDB_CONTEXT *tdb); - -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); - -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); - -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); diff --git a/source4/lib/tdb/tdb.i b/source4/lib/tdb/tdb.i new file mode 100644 index 0000000000..2f6b249c28 --- /dev/null +++ b/source4/lib/tdb/tdb.i @@ -0,0 +1,252 @@ +/* + Unix SMB/CIFS implementation. + + Swig interface to tdb. + + Copyright (C) 2004-2006 Tim Potter + Copyright (C) 2007 Jelmer Vernooij + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +%module tdb + +%{ + +/* This symbol is used in both includes.h and Python.h which causes an + annoying compiler warning. */ + +#ifdef HAVE_FSTAT +#undef HAVE_FSTAT +#endif + +/* Include tdb headers */ +#include +#include + +typedef TDB_CONTEXT tdb; +%} + +/* The tdb functions will crash if a NULL tdb context is passed */ + +%include exception.i + +%typemap(check) TDB_CONTEXT* { + if ($1 == NULL) + SWIG_exception(SWIG_ValueError, + "tdb context must be non-NULL"); +} + +/* In and out typemaps for the TDB_DATA structure. This is converted to + and from the Python string type which can contain arbitrary binary + data.. */ + +%typemap(in) TDB_DATA { + if (!PyString_Check($input)) { + PyErr_SetString(PyExc_TypeError, "string arg expected"); + return NULL; + } + $1.dsize = PyString_Size($input); + $1.dptr = (uint8_t *)PyString_AsString($input); +} + +%typemap(out) TDB_DATA { + if ($1.dptr == NULL && $1.dsize == 0) { + $result = Py_None; + } else { + $result = PyString_FromStringAndSize((const char *)$1.dptr, $1.dsize); + free($1.dptr); + } +} + +/* Treat a mode_t as an unsigned integer */ +typedef int mode_t; + +/* flags to tdb_store() */ +%constant int REPLACE = TDB_REPLACE; +%constant int INSERT = TDB_INSERT; +%constant int MODIFY = TDB_MODIFY; + +/* flags for tdb_open() */ +%constant int DEFAULT = TDB_DEFAULT; +%constant int CLEAR_IF_FIRST = TDB_CLEAR_IF_FIRST; +%constant int INTERNAL = TDB_INTERNAL; +%constant int NOLOCK = TDB_NOLOCK; +%constant int NOMMAP = TDB_NOMMAP; +%constant int CONVERT = TDB_CONVERT; +%constant int BIGENDIAN = TDB_BIGENDIAN; + +enum TDB_ERROR { + TDB_SUCCESS=0, + TDB_ERR_CORRUPT, + TDB_ERR_IO, + TDB_ERR_LOCK, + TDB_ERR_OOM, + TDB_ERR_EXISTS, + TDB_ERR_NOLOCK, + TDB_ERR_LOCK_TIMEOUT, + TDB_ERR_NOEXIST, + TDB_ERR_EINVAL, + TDB_ERR_RDONLY +}; + +%rename(Tdb) tdb; +%rename(lock_all) tdb_context::lockall; +%rename(unlock_all) tdb_context::unlockall; + +%rename(read_lock_all) tdb_context::lockall_read; +%rename(read_unlock_all) tdb_context::unlockall_read; + +%typemap(default) int tdb_flags { + $1 = TDB_DEFAULT; +} + +%typemap(default) int open_flags { + $1 = O_RDWR; +} + +%typemap(default) int hash_size { + $1 = 0; +} + +%typemap(default) mode_t mode { + $1 = 0600; +} + +%typemap(default) int flag { + $1 = TDB_REPLACE; +} + +typedef struct tdb_context { + %extend { + tdb(const char *name, int hash_size, + int tdb_flags, + int open_flags, mode_t mode) + { + tdb *ret = tdb_open(name, hash_size, tdb_flags, open_flags, mode); + + /* Throw an IOError exception from errno if tdb_open() returns + NULL */ + if (ret == NULL) { + PyErr_SetFromErrno(PyExc_IOError); + SWIG_fail; + } + +fail: + return ret; + } + enum TDB_ERROR error(); + ~tdb() { tdb_close($self); } + int close(); + int append(TDB_DATA key, TDB_DATA new_dbuf); + const char *errorstr(); + TDB_DATA fetch(TDB_DATA key); + int delete(TDB_DATA key); + int store(TDB_DATA key, TDB_DATA dbuf, int flag); + int exists(TDB_DATA key); + TDB_DATA firstkey(); + TDB_DATA nextkey(TDB_DATA key); + int lockall(); + int unlockall(); + int lockall_read(); + int unlockall_read(); + int reopen(); + int transaction_start(); + int transaction_commit(); + int transaction_cancel(); + int transaction_recover(); + int hash_size(); + size_t map_size(); + int get_flags(); + void set_max_dead(int max_dead); + const char *name(); + } + + %pythoncode { + def __str__(self): + return self.name() + + # Random access to keys, values + def __getitem__(self, key): + result = self.fetch(key) + if result is None: + raise KeyError, '%s: %s' % (key, self.errorstr()) + return result + + def __setitem__(self, key, item): + if self.store(key, item) == -1: + raise IOError, self.errorstr() + + def __delitem__(self, key): + if not self.exists(key): + raise KeyError, '%s: %s' % (key, self.errorstr()) + self.delete(key) + + def __contains__(self, key): + return self.exists(key) != 0 + + def has_key(self, key): + return self.exists(key) != 0 + + # Tdb iterator + class TdbIterator: + def __init__(self, tdb): + self.tdb = tdb + self.key = None + + def __iter__(self): + return self + + def next(self): + if self.key is None: + self.key = self.tdb.firstkey() + if self.key is None: + raise StopIteration + return self.key + else: + self.key = self.tdb.nextkey(self.key) + if self.key is None: + raise StopIteration + return self.key + + def __iter__(self): + return self.TdbIterator(self) + + # Implement other dict functions using TdbIterator + + def keys(self): + return [k for k in iter(self)] + + def values(self): + return [self[k] for k in iter(self)] + + def items(self): + return [(k, self[k]) for k in iter(self)] + + def __len__(self): + return len(self.keys()) + + def clear(self): + for k in iter(self): + del(self[k]) + + # TODO: iterkeys, itervalues, iteritems + + # TODO: any other missing methods for container types + } +} tdb; diff --git a/source4/samba4-skip b/source4/samba4-skip index 76f07dea1a..9f8b9b0eeb 100644 --- a/source4/samba4-skip +++ b/source4/samba4-skip @@ -52,3 +52,4 @@ NSS-TEST # Fails samba4.ldb.python # Fails to link properly samba4.credentials.python # Fails to link properly samba4.registry.python # Fails to link properly +samba4.tdb.python # Fails to link properly diff --git a/source4/selftest/samba4_tests.sh b/source4/selftest/samba4_tests.sh index dd00a2b349..d57c6f34bd 100755 --- a/source4/selftest/samba4_tests.sh +++ b/source4/selftest/samba4_tests.sh @@ -297,4 +297,5 @@ then plantest "ldb.python" none PYTHONPATH=bin/python trial lib/ldb/tests/python/api.py plantest "credentials.python" none PYTHONPATH=bin/python trial auth/credentials/tests/bindings.py plantest "registry.python" none PYTHONPATH=bin/python trial lib/registry/tests/bindings.py + plantest "tdb.python" none PYTHONPATH=bin/python trial lib/tdb/python/tests/simple.py fi -- cgit