void (* dbus_internal_pad3) (void *)
void (* dbus_internal_pad4) (void *)
-
-_user_data_references = [ ]
-
class DBusException(Exception):
pass
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):
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):
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
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)
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)
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()
&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)
&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
# 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,
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)
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)
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)
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)
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)
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)
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()
ptype = type(value)
ret = ""
if ptype == bool:
- ret = TYPE_BOOL
+ ret = TYPE_BOOLEAN
ret = str(chr(ret))
elif ptype == int:
ret = TYPE_INT32
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:
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
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:
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)
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
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)
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
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)
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
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)
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)
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)
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)
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):
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
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)
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):
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
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