summaryrefslogtreecommitdiff
path: root/source3/lib/ldb/swig/Ldb.py
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2006-09-24 02:49:04 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:14:36 -0500
commit3e2c696e45b24b0192ab7b1ddaf1dd4d79571609 (patch)
tree9c4423bdb006f7c183fea0c87331d23e7043d0b1 /source3/lib/ldb/swig/Ldb.py
parent0c3194816b513e3743ddcacd1eca2b683ca39b88 (diff)
downloadsamba-3e2c696e45b24b0192ab7b1ddaf1dd4d79571609.tar.gz
samba-3e2c696e45b24b0192ab7b1ddaf1dd4d79571609.tar.bz2
samba-3e2c696e45b24b0192ab7b1ddaf1dd4d79571609.zip
r18866: Jeremy and Volker have given the go-ahead on the group mapping ldb
code. Yay! This first commit copies lib/ldb/ from Samba4. A huge congratulations should go to Simo on this - he has put an enormous amount of work into ldb, and it's great to see it go into the Samba3 tree. (This used to be commit bbedf2e34315f5c420a3a05dfe22b1d5cf79f042)
Diffstat (limited to 'source3/lib/ldb/swig/Ldb.py')
-rw-r--r--source3/lib/ldb/swig/Ldb.py179
1 files changed, 179 insertions, 0 deletions
diff --git a/source3/lib/ldb/swig/Ldb.py b/source3/lib/ldb/swig/Ldb.py
new file mode 100644
index 0000000000..c7e6191c8a
--- /dev/null
+++ b/source3/lib/ldb/swig/Ldb.py
@@ -0,0 +1,179 @@
+"""Provide a more Pythonic and object-oriented interface to ldb."""
+
+#
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+#
+# Interface notes:
+#
+# - should an empty dn be represented as None, or an empty string?
+#
+# - should single-valued attributes be a string, or a list with one
+# element?
+#
+
+from ldb import *
+
+# Global initialisation
+
+result = ldb_global_init()
+
+if result != 0:
+ raise LdbError, (result, 'ldb_global_init failed')
+
+# Ldb exceptions
+
+class LdbError(Exception):
+ """An exception raised when a ldb error occurs.
+ The exception data is a tuple consisting of the ldb number and a
+ string description of the error."""
+ pass
+
+# Ldb classes
+
+class LdbMessage:
+ """A class representing a ldb message as a Python dictionary."""
+
+ def __init__(self):
+ self.mem_ctx = talloc_init(None)
+ self.msg = ldb_msg_new(self.mem_ctx)
+
+ def __del__(self):
+ if self.mem_ctx is not None:
+ talloc_free(self.mem_ctx)
+ self.mem_ctx = None
+ self.msg = None
+
+ # Make the dn attribute of the object dynamic
+
+ def __getattr__(self, attr):
+ if attr == 'dn':
+ return ldb_dn_linearize(None, self.msg.dn)
+ return self.__dict__[attr]
+
+ def __setattr__(self, attr, value):
+ if attr == 'dn':
+ self.msg.dn = ldb_dn_explode(self.msg, value)
+ if self.msg.dn == None:
+ err = LDB_ERR_INVALID_DN_SYNTAX
+ raise LdbError(err, ldb_strerror(err))
+ return
+ self.__dict__[attr] = value
+
+ # Get and set individual elements
+
+ def __getitem__(self, key):
+
+ elt = ldb_msg_find_element(self.msg, key)
+
+ if elt is None:
+ raise KeyError, "No such attribute '%s'" % key
+
+ return [ldb_val_array_getitem(elt.values, i)
+ for i in range(elt.num_values)]
+
+ def __setitem__(self, key, value):
+ ldb_msg_remove_attr(self.msg, key)
+ if type(value) in (list, tuple):
+ [ldb_msg_add_value(self.msg, key, v) for v in value]
+ else:
+ ldb_msg_add_value(self.msg, key, value)
+
+ # Dictionary interface
+ # TODO: move to iterator based interface
+
+ def len(self):
+ return self.msg.num_elements
+
+ def keys(self):
+ return [ldb_message_element_array_getitem(self.msg.elements, i).name
+ for i in range(self.msg.num_elements)]
+
+ def values(self):
+ return [self[k] for k in self.keys()]
+
+ def items(self):
+ return [(k, self[k]) for k in self.keys()]
+
+ # Misc stuff
+
+ def sanity_check(self):
+ return ldb_msg_sanity_check(self.msg)
+
+class Ldb:
+ """A class representing a binding to a ldb file."""
+
+ def __init__(self, url, flags = 0):
+ """Initialise underlying ldb."""
+
+ self.mem_ctx = talloc_init('mem_ctx for ldb 0x%x' % id(self))
+ self.ldb_ctx = ldb_init(self.mem_ctx)
+
+ result = ldb_connect(self.ldb_ctx, url, flags, None)
+
+ if result != LDB_SUCCESS:
+ raise LdbError, (result, ldb_strerror(result))
+
+ def __del__(self):
+ """Called when the object is to be garbage collected."""
+ self.close()
+
+ def close(self):
+ """Close down a ldb."""
+ if self.mem_ctx is not None:
+ talloc_free(self.mem_ctx)
+ self.mem_ctx = None
+ self.ldb_ctx = None
+
+ def _ldb_call(self, fn, *args):
+ """Call a ldb function with args. Raise a LdbError exception
+ if the function returns a non-zero return value."""
+
+ result = fn(*args)
+
+ if result != LDB_SUCCESS:
+ raise LdbError, (result, ldb_strerror(result))
+
+ def search(self, expression):
+ """Search a ldb for a given expression."""
+
+ self._ldb_call(ldb_search, self.ldb_ctx, None, LDB_SCOPE_DEFAULT,
+ expression, None);
+
+ return [LdbMessage(ldb_message_ptr_array_getitem(result.msgs, ndx))
+ for ndx in range(result.count)]
+
+ def delete(self, dn):
+ """Delete a dn."""
+
+ _dn = ldb_dn_explode(self.ldb_ctx, dn)
+
+ self._ldb_call(ldb_delete, self.ldb_ctx, _dn)
+
+ def rename(self, olddn, newdn):
+ """Rename a dn."""
+
+ _olddn = ldb_dn_explode(self.ldb_ctx, olddn)
+ _newdn = ldb_dn_explode(self.ldb_ctx, newdn)
+
+ self._ldb_call(ldb_rename, self.ldb_ctx, _olddn, _newdn)
+
+ def add(self, m):
+ self._ldb_call(ldb_add, self.ldb_ctx, m.msg)