r23796: main COPYING file for samba4, plus some formatting varients
[samba.git] / source / lib / ldb / swig / Ldb.py
index 099fbcd6e0a4a75c2849501913da06c4070c18c5..8cc7663cc3641b535f29bdfd80f2a423899ac3ce 100644 (file)
@@ -7,7 +7,7 @@
 #
 # 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
+# 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,
 # 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
@@ -29,10 +38,16 @@ 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."""
+    """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."""
     
@@ -41,14 +56,13 @@ class LdbMessage:
         self.msg = ldb_msg_new(self.mem_ctx)
 
     def __del__(self):
-        self.close()
-
-    def close(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)
@@ -57,11 +71,13 @@ class LdbMessage:
     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
         
-    def len(self):
-        return self.msg.num_elements
+    # Get and set individual elements
 
     def __getitem__(self, key):
 
@@ -74,11 +90,33 @@ class LdbMessage:
                 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."""
 
@@ -88,7 +126,7 @@ class 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)
+        result = ldb_connect(self.ldb_ctx, url, flags, None)
 
         if result != LDB_SUCCESS:
             raise LdbError, (result, ldb_strerror(result))