2005-11-15 Robert McQueen <robot101@debian.org>
[platform/upstream/dbus.git] / python / dbus_bindings.pyx
index 6973944..8b1b221 100644 (file)
@@ -63,9 +63,6 @@ ctypedef struct DBusObjectPathVTable:
   void (* dbus_internal_pad3) (void *)
   void (* dbus_internal_pad4) (void *)
 
-
-_user_data_references = [ ]
-
 class DBusException(Exception):
     pass
 
@@ -80,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):
@@ -126,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):
@@ -178,52 +240,68 @@ cdef class PendingCall
 cdef class Watch
 cdef class MessageIter
 
+cdef void _GIL_safe_cunregister_function_handler (DBusConnection *connection,
+                                                  void *user_data):
+    cdef Connection conn
+
+    tup = <object>user_data
+    assert (type(tup) == tuple)    
+    function = tup[1]
+    conn = Connection()
+    conn.__cinit__(None, connection)
+
+    args = (conn)
+    function(*args)
+    Py_XDECREF(tup) 
+
 cdef void cunregister_function_handler (DBusConnection *connection,
                                         void *user_data):
-    cdef Connection conn
     cdef PyGILState_STATE gil
-
     gil = PyGILState_Ensure()
     try:
-        itup = <object>user_data
-        assert (type(tup) == list)    
-        function = tup[1]
-        conn = Connection()
-        conn.__cinit__(None, connection)
-
-        args = [conn]
-        function(*args)
+        _GIL_safe_cunregister_function_handler (connection, user_data);
     finally:
         PyGILState_Release(gil)
 
-cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
+
+
+cdef DBusHandlerResult _GIL_safe_cmessage_function_handler ( 
+                                                  DBusConnection *connection,
                                                   DBusMessage *msg,
                                                   void *user_data):
     cdef Connection conn
     cdef Message message
-    cdef PyGILState_STATE gil
 
+    tup = <object>user_data
+    assert (type(tup) == tuple)
+    function = tup[0]
+    message = EmptyMessage()
+
+    #we don't own the message so we need to ref it
+    dbus_message_ref(msg)
+    message._set_msg(msg)
+    conn = Connection()
+    conn.__cinit__(None, connection)
+    args = (conn,
+            message)
+    retval = function(*args)
+
+    if (retval == None):
+        retval = DBUS_HANDLER_RESULT_HANDLED
+    return retval
+
+cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
+                                                  DBusMessage *msg,
+                                                  void *user_data):
+    cdef PyGILState_STATE gil
     gil = PyGILState_Ensure()
     try:
-        tup = <object>user_data
-        assert (type(tup) == list)
-        function = tup[0]
-        message = EmptyMessage()
-
-       #we don't own the message so we need to ref it
-        dbus_message_ref(msg)
-        message._set_msg(msg)
-        conn = Connection()
-        conn.__cinit__(None, connection)  
-        args = [conn,
-                message]
-        retval = function(*args)
-        if (retval == None):
-            retval = DBUS_HANDLER_RESULT_HANDLED
-        return retval
+        return _GIL_safe_cmessage_function_handler (connection, msg, user_data);
     finally:
         PyGILState_Release(gil)
 
+
 cdef class Connection:
     def __init__(self, address=None, Connection _conn=None):
         cdef DBusConnection *c_conn
@@ -248,9 +326,11 @@ cdef class Connection:
             self.conn = dbus_connection_open(address,
                                          &error)
             if dbus_error_is_set(&error):
-                raise DBusException, error.message
+                errormsg = error.message
+                dbus_error_free (&error)
+                raise DBusException, errormsg
 
-    def __del__(self):
+    def __dealloc__(self):
         if self.conn != NULL:
             dbus_connection_unref(self.conn)
 
@@ -263,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)
@@ -335,12 +415,9 @@ cdef class Connection:
     def send_with_reply(self, Message message, timeout_milliseconds):
         cdef dbus_bool_t retval
         cdef DBusPendingCall *cpending_call
-        cdef DBusError error
         cdef DBusMessage *msg
         cdef PendingCall pending_call
 
-        dbus_error_init(&error)
-
         cpending_call = NULL
         
         msg = message._get_msg()
@@ -350,9 +427,6 @@ cdef class Connection:
                                                  &cpending_call,
                                                  timeout_milliseconds)
 
-        if dbus_error_is_set(&error):
-            raise DBusException, error.message
-
         if (cpending_call != NULL):
             pending_call = PendingCall()
             pending_call.__cinit__(cpending_call)
@@ -379,15 +453,16 @@ cdef class Connection:
             &error)
 
         if dbus_error_is_set(&error):
-            raise DBusException, error.message
+            errormsg = error.message
+            dbus_error_free (&error)
+            raise DBusException, errormsg
+
+        assert(retval != NULL)
 
-        if retval == NULL:
-            raise AssertionError
-        
         m = EmptyMessage()
         m._set_msg(retval)
 
-        return m 
+        return m
 
     def set_watch_functions(self, add_function, remove_function, data):
         pass
@@ -401,10 +476,9 @@ cdef class Connection:
     # FIXME: set_dispatch_status_function, get_unix_user, set_unix_user_function
 
     def add_filter(self, filter_function):
-        user_data = [ filter_function ]
-        global _user_data_references
-        _user_data_references.append(user_data)
-        
+        user_data = (filter_function,)
+        Py_XINCREF(user_data)
+       
         return dbus_connection_add_filter(self.conn,
                                           cmessage_function_handler,
                                           <void*>user_data,
@@ -444,9 +518,8 @@ cdef class Connection:
         cvtable.unregister_function = cunregister_function_handler 
         cvtable.message_function    = cmessage_function_handler
 
-        user_data = [message_cb, unregister_cb]
-        global _user_data_references
-        _user_data_references.append(user_data)
+        user_data = (message_cb, unregister_cb)
+        Py_XINCREF(user_data)
         
         return dbus_connection_register_object_path(self.conn, path, &cvtable,
                                                     <void*>user_data) 
@@ -457,10 +530,9 @@ cdef class Connection:
         cvtable.unregister_function = cunregister_function_handler 
         cvtable.message_function    = cmessage_function_handler
 
-        user_data = [message_cb, unregister_cb]
-        global _user_data_references
-        _user_data_references.append(user_data)        
-        
+        user_data = (message_cb, unregister_cb)
+        Py_XINCREF(user_data)
+       
         return dbus_connection_register_fallback(self.conn, path, &cvtable,
                                                  <void*>user_data) 
 
@@ -487,11 +559,11 @@ cdef class Connection:
 
         return child_entries
 
-cdef void _pending_call_notification(DBusPendingCall *pending_call, void *user_data):
+cdef void _GIL_safe_pending_call_notification (DBusPendingCall *pending_call, 
+                                               void *user_data):
     cdef DBusMessage *dbus_message
     cdef Message message
-    cdef PyGILState_STATE gil
-   
+  
     (reply_handler, error_handler) = <object>user_data
    
     dbus_message = dbus_pending_call_steal_reply(pending_call)
@@ -500,25 +572,30 @@ cdef void _pending_call_notification(DBusPendingCall *pending_call, void *user_d
 
     type = message.get_type()
 
+    if type == MESSAGE_TYPE_METHOD_RETURN:
+        args = message.get_args_list()
+        reply_handler(*args)
+    elif type == MESSAGE_TYPE_ERROR:
+        args = message.get_args_list()
+        if len(args) > 0:
+            error_handler(DBusException(args[0]))
+        else:
+            error_handler(DBusException(""))
+    else:
+        error_handler(DBusException('Unexpected Message Type: ' + message.type_to_name(type)))
+
+    dbus_pending_call_unref(pending_call)
+    Py_XDECREF(<object>user_data)
+
+cdef void _pending_call_notification(DBusPendingCall *pending_call, 
+                                     void *user_data):
+    cdef PyGILState_STATE gil
     gil = PyGILState_Ensure()
     try:
-        if type == MESSAGE_TYPE_METHOD_RETURN:
-            args = message.get_args_list()
-            reply_handler(*args)
-        elif type == MESSAGE_TYPE_ERROR:
-            args = message.get_args_list()
-            if len(args) > 0:
-                error_handler(DBusException(args[0]))
-            else:
-                error_handler(DBusException(""))
-        else:
-            error_handler(DBusException('Unexpected Message Type: ' + message.type_to_name(type)))
+        _GIL_safe_pending_call_notification (pending_call, user_data);
     finally:
         PyGILState_Release(gil)
 
-    dbus_message_unref(dbus_message)
-    dbus_pending_call_unref(pending_call)
-
 cdef void _pending_call_free_user_data(void *data):
     call_tuple = <object>data
     Py_XDECREF(call_tuple)
@@ -535,7 +612,7 @@ cdef class PendingCall:
         self.pending_call = _pending_call
         dbus_pending_call_ref(self.pending_call)
 
-    def __del__(self):
+    def __dealloc__(self):
         if self.pending_call != NULL:
             dbus_pending_call_unref(self.pending_call)
 
@@ -560,6 +637,7 @@ cdef class PendingCall:
     def set_notify(self, reply_handler, error_handler):
         user_data = (reply_handler, error_handler)
         Py_XINCREF(user_data)
+        dbus_pending_call_ref(self.pending_call)
         dbus_pending_call_set_notify(self.pending_call, _pending_call_notification, 
                                      <void *>user_data, _pending_call_free_user_data)
         
@@ -719,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()
@@ -814,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
@@ -822,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:
@@ -858,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
@@ -922,8 +1001,66 @@ cdef class MessageIter:
 
         return ret
 
+    def append_strict(self, value, sig):
     
-    #FIXME: handle all the different types?
+        if sig == TYPE_INVALID or sig == None:
+            raise TypeError, 'Invalid arg type sent to append_strict'
+
+        sig_type = ord(sig[0])
+           
+        if sig_type == TYPE_STRING:
+            retval = self.append_string(value)
+        elif sig_type == TYPE_INT16:
+            retval = self.append_int16(value)
+        elif sig_type == TYPE_UINT16:
+            retval = self.append_uint16(value)
+        elif sig_type == TYPE_INT32:
+            retval = self.append_int32(value)
+        elif sig_type == TYPE_UINT32:
+            retval = self.append_uint32(value)
+        elif sig_type == TYPE_INT64:
+            retval = self.append_int64(value)
+        elif sig_type == TYPE_UINT64:
+            retval = self.append_uint64(value)
+        elif sig_type == TYPE_DOUBLE:
+            retval = self.append_double(value)
+        elif sig_type == TYPE_BYTE:
+            retval = self.append_byte(value)
+        elif sig_type == TYPE_BOOLEAN:
+            retval = self.append_boolean(value)
+        elif sig_type == TYPE_SIGNATURE:
+            retval = self.append_signature(value)
+        elif sig_type == TYPE_ARRAY:
+            if len(sig) < 2:
+                raise TypeError, "Invalid array signature in append_strict.  Arrays must be followed by a type."
+
+            array_type = ord(sig[1])            
+            if array_type == DICT_ENTRY_BEGIN:
+                if ord(sig[-1]) != DICT_ENTRY_END:
+                    raise TypeError, "Invalid dict entry in append_strict.  No termination in signature %s."%(sig)
+
+                tmp_sig = sig[2:-1]
+                retval = self.append_dict(Dictionary(value, signature=tmp_sig))
+            else:
+                tmp_sig = sig[1:]
+                retval = self.append_array(Array(value, signature=tmp_sig))
+        elif sig_type == TYPE_OBJECT_PATH:
+            retval = self.append_object_path(value)
+        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:
+            retval = self.append_variant(Variant(value))
+        elif sig_type == DICT_ENTRY_BEGIN:
+            raise TypeError, "Signiture is invalid in append_strict. A dict entry must be part of an array." 
+        else:
+            raise TypeError, "Argument of unknown type '%s' in append_strict" % (sig)
+
+        return retval
+
     def append(self, value):
         value_type = type(value)
         if value_type == bool:
@@ -932,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)
@@ -1036,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
@@ -1088,15 +1226,30 @@ cdef class MessageIter:
             dict_entry_iter = MessageIter(level)
             dict_entry_iter.__cinit__(&c_dict_entry_iter)
 
-            if not dict_entry_iter.append(key):
-                dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
-                dbus_message_iter_close_container(self.iter, dict_iter.iter)
-                return False
+            if 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 = 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)
+                    return False
+
+            else:
+                if not dict_entry_iter.append(key):
+                    dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
+                    dbus_message_iter_close_container(self.iter, dict_iter.iter)
+                    return False
                 
-            if not dict_entry_iter.append(value):
-                dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
-                dbus_message_iter_close_container(self.iter, dict_iter.iter)
-                return False
+                if not dict_entry_iter.append(value):
+                    dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
+                    dbus_message_iter_close_container(self.iter, dict_iter.iter)
+                    return False
 
             dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
 
@@ -1104,7 +1257,7 @@ cdef class MessageIter:
 
         return True
 
-    def append_struct(self, python_struct):
+    def append_struct(self, python_struct, signature = None):
         cdef DBusMessageIter c_struct_iter
         cdef MessageIter struct_iter
 
@@ -1112,11 +1265,23 @@ cdef class MessageIter:
         dbus_message_iter_open_container(self.iter, TYPE_STRUCT, NULL, <DBusMessageIter *>&c_struct_iter)
         struct_iter = MessageIter(level)
         struct_iter.__cinit__(&c_struct_iter)
-        
+
+        signature_iter = iter(Signature(signature))
         for item in python_struct:
-            if not struct_iter.append(item):
-                dbus_message_iter_close_container(self.iter, struct_iter.iter)
-                return False
+            if signature:
+                sig = signature_iter.next()
+
+                if sig == '':
+                    dbus_message_iter_close_container(self.iter, struct_iter.iter)
+                    return False
+
+                if not struct_iter.append_strict(item, sig):
+                    dbus_message_iter_close_container(self.iter, struct_iter.iter)
+                    return False
+            else:
+                if not struct_iter.append(item):
+                    dbus_message_iter_close_container(self.iter, struct_iter.iter)
+                    return False
 
         dbus_message_iter_close_container(self.iter, struct_iter.iter)
 
@@ -1145,7 +1310,7 @@ cdef class MessageIter:
 
         length = len(python_list)
         for item in python_list:
-            if not array_iter.append(item):
+            if not array_iter.append_strict(item, sig):
                 dbus_message_iter_close_container(self.iter, array_iter.iter)
                 return False
 
@@ -1277,7 +1442,7 @@ cdef class Message:
                 self.msg = dbus_message_new_error(cmsg, error_name, error_message)
  
 
-    def __del__(self):
+    def __dealloc__(self):
         if self.msg != NULL:
             dbus_message_unref(self.msg)
             
@@ -1471,7 +1636,9 @@ cdef class Server:
         self.server = dbus_server_listen(address,
                                          &error)
         if dbus_error_is_set(&error):
-            raise DBusException, error.message
+            errormsg = error.message
+            dbus_error_free (&error)
+            raise DBusException, errormsg
 
     def disconnect(self):
         dbus_server_disconnect(self.server)
@@ -1500,17 +1667,23 @@ 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):
-        raise DBusException, error.message
+        errormsg = error.message
+        dbus_error_free(&error)
+        raise DBusException, errormsg 
 
     conn = Connection()
     conn.__cinit__(None, connection)
@@ -1531,13 +1704,16 @@ def bus_get_unix_user(Connection connection, service_name):
     retval = dbus_bus_get_unix_user(conn, service_name, &error)
 
     if dbus_error_is_set(&error):
-        raise DBusException, error.message
+        errormsg = error.message
+        dbus_error_free(&error)
+        raise DBusException, errormsg 
+
     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)
@@ -1549,6 +1725,11 @@ def bus_start_service_by_name(Connection connection, service_name, flags=0):
 
     retval = dbus_bus_start_service_by_name(conn, service_name, flags, &results, &error)
 
+    if dbus_error_is_set(&error):
+        errormsg = error.message
+        dbus_error_free(&error)
+        raise DBusException, errormsg
+
     return (retval, results) 
 
 def bus_register(Connection connection):
@@ -1561,12 +1742,19 @@ def bus_register(Connection connection):
     retval = dbus_bus_register(conn,
                                &error)
     if dbus_error_is_set(&error):
-        raise DBusException, error.message
+        msg = error.message
+        dbus_error_free(&error)
+        raise DBusException, errormsg 
 
     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
@@ -1580,9 +1768,33 @@ def bus_request_name(Connection connection, service_name, flags=0):
                                    flags,
                                    &error)
     if dbus_error_is_set(&error):
-        raise DBusException, error.message
+        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)
@@ -1594,7 +1806,10 @@ def bus_name_has_owner(Connection connection, service_name):
                                      service_name,
                                      &error)
     if dbus_error_is_set(&error):
-        raise DBusException, error.message
+        errormsg = error.message
+        dbus_error_free(&error)
+        raise DBusException, errormsg
+        
     return retval
 
 def bus_add_match(Connection connection, rule):
@@ -1607,7 +1822,9 @@ def bus_add_match(Connection connection, rule):
     dbus_bus_add_match (conn, rule, &error)
     
     if dbus_error_is_set(&error):
-        raise DBusException, error.message
+        errormsg = error.message
+        dbus_error_free(&error)
+        raise DBusException, errormsg
 
 def bus_remove_match(Connection connection, rule):
     cdef DBusError error
@@ -1619,5 +1836,7 @@ def bus_remove_match(Connection connection, rule):
     dbus_bus_remove_match (conn, rule, &error)
     
     if dbus_error_is_set(&error):
-        raise DBusException, error.message
+        errormsg = error.message
+        dbus_error_free(&error)
+        raise DBusException, errormsg