2005-11-15 Robert McQueen <robot101@debian.org>
[platform/upstream/dbus.git] / python / dbus_bindings.pyx
index 0060373..8b1b221 100644 (file)
@@ -77,9 +77,74 @@ class ByteArray(str):
     def __init__(self, value):
         str.__init__(self, value)
 
+class SignatureIter(object):
+    def __init__(self, string):
+        object.__init__(self)
+        self.remaining = string
+
+    def next(self):
+        if self.remaining == '':
+            raise StopIteration
+
+        signature = self.remaining
+        block_depth = 0
+        block_type = None
+        end = len(signature)
+
+        for marker in range(0, end):
+            cur_sig = ord(signature[marker])
+
+            if cur_sig == TYPE_ARRAY:
+                pass
+            elif cur_sig == DICT_ENTRY_BEGIN or cur_sig == STRUCT_BEGIN:
+                if block_type == None:
+                    block_type = cur_sig
+
+                if block_type == cur_sig:
+                    block_depth = block_depth + 1
+
+            elif cur_sig == DICT_ENTRY_END:
+                if block_type == DICT_ENTRY_BEGIN:
+                    block_depth = block_depth - 1
+
+                if block_depth == 0:
+                    end = marker
+                    break
+
+            elif cur_sig == STRUCT_END:
+                if block_type == STRUCT_BEGIN:
+                    block_depth = block_depth - 1
+
+                if block_depth == 0:
+                    end = marker
+                    break
+
+            else:
+                if block_depth == 0:
+                    end = marker
+                    break
+
+        end = end + 1
+        self.remaining = signature[end:]
+        return Signature(signature[0:end])
+
 class Signature(str):
+    """An iterable method signature. Iterating gives the signature of each
+    argument in turn."""
     def __init__(self, value):
-        str.__init__(self, value)
+        return str.__init__(self, value)
+
+    def __iter__(self):
+        return SignatureIter(self)
+
+class VariantSignature(object):
+    """A fake method signature which when iterated, is an endless stream
+    of variants (handy with zip()). It has no string representation."""
+    def __iter__(self):
+        return self
+
+    def next(self):
+        return 'v'
 
 class Byte(int):
     def __init__(self, value):
@@ -123,9 +188,9 @@ class Double(float):
     def __init__(self, value):
         float.__init__(self, value)
 
-class String(str):
+class String(unicode):
     def __init__(self, value):
-        str.__init__(self, value)
+        unicode.__init__(self, value)
 
 class Array(list):
     def __init__(self, value, type=None, signature=None):
@@ -278,8 +343,8 @@ cdef class Connection:
     def get_unique_name(self):
         return bus_get_unique_name(self)
 
-    def disconnect(self):
-        dbus_connection_disconnect(self.conn)
+    def close(self):
+        dbus_connection_close(self.conn)
 
     def get_is_connected(self):
         return dbus_connection_get_is_connected(self.conn)
@@ -392,13 +457,12 @@ cdef class Connection:
             dbus_error_free (&error)
             raise DBusException, errormsg
 
-        if retval == NULL:
-            raise AssertionError
-        
+        assert(retval != NULL)
+
         m = EmptyMessage()
         m._set_msg(retval)
 
-        return m 
+        return m
 
     def set_watch_functions(self, add_function, remove_function, data):
         pass
@@ -733,8 +797,9 @@ cdef class MessageIter:
     def get_string(self):
         cdef char *c_str
         dbus_message_iter_get_basic(self.iter, <char **>&c_str)
+        ret = c_str.decode('utf8')
 
-        return c_str
+        return ret
 
     def get_object_path(self):
         object_path_string = self.get_string()
@@ -828,7 +893,7 @@ cdef class MessageIter:
         ptype = type(value)
         ret = ""
         if ptype == bool:
-            ret = TYPE_BOOL
+            ret = TYPE_BOOLEAN
             ret = str(chr(ret))
         elif ptype == int:
             ret = TYPE_INT32
@@ -836,7 +901,7 @@ cdef class MessageIter:
         elif ptype == long:
             ret = TYPE_INT64
             ret = str(chr(ret))
-        elif ptype == str:
+        elif (ptype == str or ptype == unicode):
             ret = TYPE_STRING
             ret = str(chr(ret))
         elif ptype == float:
@@ -872,7 +937,7 @@ cdef class MessageIter:
             ret = TYPE_BYTE
             ret = str(chr(ret))
         elif isinstance(value, Boolean) or value == Boolean:
-            ret = TYPE_BOOL
+            ret = TYPE_BOOLEAN
             ret = str(chr(ret))
         elif isinstance(value, Int16) or value == Int16:
             ret = TYPE_INT16
@@ -936,49 +1001,7 @@ cdef class MessageIter:
 
         return ret
 
-    def parse_signature_block(self, signature):
-        remainder = ''
-        sig = ''
-        block_depth = 0
-        block_type = None
-       
-        for marker in range(0, len(signature)):
-            cur_sig = ord(signature[marker])
-
-            if cur_sig == TYPE_ARRAY:
-                pass
-            elif cur_sig == DICT_ENTRY_BEGIN or cur_sig == STRUCT_BEGIN:
-                if block_type == None:
-                    block_type = cur_sig
-
-                if block_type == cur_sig:
-                    block_depth = block_depth + 1
-
-            elif cur_sig == DICT_ENTRY_END:
-                if block_type == DICT_ENTRY_BEGIN:
-                    block_depth = block_depth - 1
-
-                if block_depth == 0:
-                    break
-
-            elif cur_sig == STRUCT_END:
-                if block_type == STRUCT_BEGIN:
-                    block_depth = block_depth - 1
-
-                if block_depth == 0:
-                    break
-
-            else:
-                if block_depth == 0:
-                    break
-        
-        marker = marker + 1
-        sig = signature[0:marker]
-        remainder = signature[marker:]
-        return (sig, remainder)
-  
     def append_strict(self, value, sig):
-        
     
         if sig == TYPE_INVALID or sig == None:
             raise TypeError, 'Invalid arg type sent to append_strict'
@@ -986,7 +1009,7 @@ cdef class MessageIter:
         sig_type = ord(sig[0])
            
         if sig_type == TYPE_STRING:
-            retval = self.append(value)
+            retval = self.append_string(value)
         elif sig_type == TYPE_INT16:
             retval = self.append_int16(value)
         elif sig_type == TYPE_UINT16:
@@ -1023,7 +1046,10 @@ cdef class MessageIter:
                 retval = self.append_array(Array(value, signature=tmp_sig))
         elif sig_type == TYPE_OBJECT_PATH:
             retval = self.append_object_path(value)
-        elif sig_type == TYPE_STRUCT:
+        elif sig_type == STRUCT_BEGIN:
+            if ord(sig[-1]) != STRUCT_END:
+                raise TypeError, "Invalid struct entry in append_strict. No termination in signature %s." % (sig)
+
             tmp_sig = sig[1:-1]
             retval = self.append_struct(value, signature = tmp_sig)
         elif sig_type == TYPE_VARIANT:
@@ -1043,7 +1069,7 @@ cdef class MessageIter:
             retval = self.append_int32(value)
         elif value_type == long:
             retval = self.append_int64(value)
-        elif value_type == str:
+        elif (value_type == str or value_type == unicode):
             retval = self.append_string(value)
         elif value_type == float:
             retval = self.append_double(value)
@@ -1147,8 +1173,9 @@ cdef class MessageIter:
 
     def append_string(self, value):
         cdef char *c_value
-        c_value = value
-        return dbus_message_iter_append_basic(self.iter, TYPE_STRING, <char **>&c_value)    
+        tmp = value.encode('utf8')
+        c_value = tmp
+        return dbus_message_iter_append_basic(self.iter, TYPE_STRING, <char **>&c_value)
 
     def append_object_path(self, value):
         cdef char *c_value
@@ -1200,13 +1227,14 @@ cdef class MessageIter:
             dict_entry_iter.__cinit__(&c_dict_entry_iter)
 
             if signature:
-                (tmp_sig, remainder) = self.parse_signature_block(signature)
+                signature_iter = iter(Signature(signature))
+                tmp_sig = signature_iter.next()
                 if not dict_entry_iter.append_strict(key, tmp_sig):
                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
                     return False
 
-                (tmp_sig, remainder) = self.parse_signature_block(remainder)
+                tmp_sig = signature_iter.next()
                 if not dict_entry_iter.append_strict(value, tmp_sig):
                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
@@ -1238,10 +1266,10 @@ cdef class MessageIter:
         struct_iter = MessageIter(level)
         struct_iter.__cinit__(&c_struct_iter)
 
-        remainder = signature
+        signature_iter = iter(Signature(signature))
         for item in python_struct:
             if signature:
-                (sig, remainder) = self.parse_signature_block(remainder)
+                sig = signature_iter.next()
 
                 if sig == '':
                     dbus_message_iter_close_container(self.iter, struct_iter.iter)
@@ -1639,14 +1667,18 @@ BUS_SESSION = DBUS_BUS_SESSION
 BUS_SYSTEM = DBUS_BUS_SYSTEM
 BUS_STARTER = DBUS_BUS_STARTER
 
-def bus_get (bus_type):
+def bus_get (bus_type, private=False):
     cdef DBusError error
     cdef Connection conn
-    dbus_error_init(&error)
     cdef DBusConnection *connection
 
-    connection = dbus_bus_get(bus_type,
-                              &error)
+    dbus_error_init(&error)
+    if private:
+        connection = dbus_bus_get_private(bus_type,
+                                          &error)
+    else:
+        connection = dbus_bus_get(bus_type,
+                                  &error)
 
     if dbus_error_is_set(&error):
         errormsg = error.message
@@ -1678,10 +1710,10 @@ def bus_get_unix_user(Connection connection, service_name):
 
     return retval
 
-#These are defines, not enums so they aren't auto generated
-DBUS_START_REPLY_SUCCESS = 0 
-DBUS_START_REPLY_ALREADY_RUNNING = 1 
-    
+# these are defines, not enums, so they aren't auto generated
+DBUS_START_REPLY_SUCCESS = 0
+DBUS_START_REPLY_ALREADY_RUNNING = 1
+
 def bus_start_service_by_name(Connection connection, service_name, flags=0):
     cdef DBusError error
     dbus_error_init(&error)
@@ -1716,8 +1748,13 @@ def bus_register(Connection connection):
 
     return retval
 
-SERVICE_FLAG_PROHIBIT_REPLACEMENT = 0x1
-SERVICE_FLAG_REPLACE_EXISTING     = 0x2
+NAME_FLAG_PROHIBIT_REPLACEMENT = 0x1
+NAME_FLAG_REPLACE_EXISTING     = 0x2
+
+REQUEST_NAME_REPLY_PRIMARY_OWNER = 1
+REQUEST_NAME_REPLY_IN_QUEUE      = 2
+REQUEST_NAME_REPLY_EXISTS        = 3
+REQUEST_NAME_REPLY_ALREADY_OWNER = 4
 
 def bus_request_name(Connection connection, service_name, flags=0):
     cdef DBusError error
@@ -1734,9 +1771,30 @@ def bus_request_name(Connection connection, service_name, flags=0):
         errormsg = error.message
         dbus_error_free(&error)
         raise DBusException, errormsg
-        
+
     return retval
-    
+
+RELEASE_NAME_REPLY_RELEASED = 1
+RELEASE_NAME_REPLY_NON_EXISTENT = 2
+RELEASE_NAME_REPLY_NOT_OWNER = 3
+
+def bus_release_name(Connection connection, service_name):
+    cdef DBusError error
+    dbus_error_init(&error)
+    cdef int retval
+    cdef DBusConnection *conn
+
+    conn = connection._get_conn()
+    retval = dbus_bus_release_name(conn,
+                                   service_name,
+                                   &error)
+    if dbus_error_is_set(&error):
+        errormsg = error.message
+        dbus_error_free(&error)
+        raise DBusException, errormsg
+
+    return retval
+
 def bus_name_has_owner(Connection connection, service_name):
     cdef DBusError error
     dbus_error_init(&error)