summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn (J5) Palmieri <johnp@redhat.com>2005-08-16 22:54:04 +0000
committerJohn (J5) Palmieri <johnp@redhat.com>2005-08-16 22:54:04 +0000
commitce84a7761a567f5afaca03d0fb5c0378f293da80 (patch)
tree7f00e7193fb6e6f07df88fa70650174916231820
parent9746c7a97871508c7298a8cad88dc7daff1c2bb3 (diff)
* python/__init__.py: Version updated (0, 43, 0)
* python/dbus_bindings.pyx: - Fixed type objects to have self passed into __init__ - Added the Variant type - Add the ability to specify types or signatures for Array, Variant and Dictionary - (Connection::send_with_reply_handlers): return a PendingCall object - (_pending_call_notification): handle the case when an error is returned without an error message in the body - (MessageIter::get_boolean): return True or False instead of an integer - (MessageIter::python_value_to_dbus_sig): add direct checking of types and add checks for objects with embeded signatures or types (Array, Variant and Dictionary) - (MessageIter::append_byte): handle case when the value is a dbus.Byte - (MessageIter::append_dict): handle embeded types or signatures - (MessageIter::append_array): handle embeded types or signatures - (MessageIter::append_variant): new method * python/proxies.py: - (DeferedMethod): New. Dummy executable object used when queuing calls blocking on introspection data - (ProxyMethod::__call__): add the timeout keyword for specifying longer or shorter timeouts for method calls - (ProxyObject): Add first pass at an introspection state machine - (ProxyObject::__init__): Add introspect keyword for turing off an on introspection. - (ProxyObject::_Introspect): Internal Introspect call that bypasses the usual mechanisms for sending messages. This is to avoid a deadlock where the Intospect call would be queued waiting for the Introspect call to finish ;-) - (ProxyObject::_introspect_reply_handler): New. This method is called when introspection returns with no error - (ProxyObject::_introspect_error_handler): New. This method is called when introspection encounters an error - (ProxyObject::__getattr__): Code to handle different introspection states. Queue async calls or block blocking calls if we are introspecting. Pass through as normal if we are not or are done with introspecting. * python/service.py: Import signal and method from decorators.py * python/types.py: Add Variant type
-rw-r--r--ChangeLog43
-rw-r--r--python/__init__.py2
-rw-r--r--python/_dbus.py5
-rw-r--r--python/dbus_bindings.pyx223
-rw-r--r--python/examples/example-client.py1
-rw-r--r--python/examples/list-system-services.py4
-rw-r--r--python/proxies.py97
-rw-r--r--python/service.py2
-rw-r--r--python/types.py1
9 files changed, 312 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index c7fc00f1..dfceda32 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2005-08-16 John (J5) Palmieri <johnp@redhat.com>
+
+ * python/__init__.py: Version updated (0, 43, 0)
+
+ * python/dbus_bindings.pyx:
+ - Fixed type objects to have self passed into __init__
+ - Added the Variant type
+ - Add the ability to specify types or signatures for Array, Variant and Dictionary
+ - (Connection::send_with_reply_handlers): return a PendingCall object
+ - (_pending_call_notification): handle the case when an error is returned
+ without an error message in the body
+ - (MessageIter::get_boolean): return True or False instead of an integer
+ - (MessageIter::python_value_to_dbus_sig): add direct checking of types and
+ add checks for objects with embeded signatures or types (Array, Variant and
+ Dictionary)
+ - (MessageIter::append_byte): handle case when the value is a dbus.Byte
+ - (MessageIter::append_dict): handle embeded types or signatures
+ - (MessageIter::append_array): handle embeded types or signatures
+ - (MessageIter::append_variant): new method
+
+ * python/proxies.py:
+ - (DeferedMethod): New. Dummy executable object used when queuing calls blocking on
+ introspection data
+ - (ProxyMethod::__call__): add the timeout keyword for specifying longer or
+ shorter timeouts for method calls
+ - (ProxyObject): Add first pass at an introspection state machine
+ - (ProxyObject::__init__): Add introspect keyword for turing off an on
+ introspection.
+ - (ProxyObject::_Introspect): Internal Introspect call that bypasses the usual
+ mechanisms for sending messages. This is to avoid a deadlock where the Intospect
+ call would be queued waiting for the Introspect call to finish ;-)
+ - (ProxyObject::_introspect_reply_handler): New. This method is called when
+ introspection returns with no error
+ - (ProxyObject::_introspect_error_handler): New. This method is called when
+ introspection encounters an error
+ - (ProxyObject::__getattr__): Code to handle different introspection states.
+ Queue async calls or block blocking calls if we are introspecting. Pass through
+ as normal if we are not or are done with introspecting.
+
+ * python/service.py: Import signal and method from decorators.py
+
+ * python/types.py: Add Variant type
+
2005-08-16 Colin Walters <walters@verbum.org>
* glib/dbus-gobject.c (dbus_set_g_error): Don't lose if the
diff --git a/python/__init__.py b/python/__init__.py
index 945ef67e..a1ff407a 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -1,5 +1,5 @@
from _dbus import *
from types import *
-version = (0, 42, 0)
+version = (0, 43, 0)
_dbus_main_loop_setup_function = None
diff --git a/python/_dbus.py b/python/_dbus.py
index f0c7b069..6074be16 100644
--- a/python/_dbus.py
+++ b/python/_dbus.py
@@ -196,8 +196,9 @@ class Interface:
if member == '__call__':
return object.__call__
else:
- return self._obj.__getattr__(member, dbus_interface=_dbus_interface)
-
+ ret = self._obj.__getattr__(member, dbus_interface=_dbus_interface)
+ return ret
+
def __repr__(self):
return '<Interface %r implementing %r at %x>'%(
self._obj, self._dbus_interface, id(self))
diff --git a/python/dbus_bindings.pyx b/python/dbus_bindings.pyx
index 608ef544..a083f504 100644
--- a/python/dbus_bindings.pyx
+++ b/python/dbus_bindings.pyx
@@ -74,53 +74,53 @@ class ConnectionError(Exception):
class ObjectPath(str):
def __init__(self, value):
- str.__init__(value)
+ str.__init__(self, value)
class ByteArray(str):
def __init__(self, value):
- str.__init__(value)
+ str.__init__(self, value)
class Signature(str):
def __init__(self, value):
- str.__init__(value)
+ str.__init__(self, value)
class Byte(int):
def __init__(self, value):
- int.__init__(value)
+ int.__init__(self, value)
class Boolean(int):
def __init__(self, value):
- int.__init__(value)
+ int.__init__(self, value)
class Int16(int):
def __init__(self, value):
- int.__init__(value)
+ int.__init__(self, value)
class UInt16(int):
def __init__(self, value):
if value < 0:
raise TypeError('Unsigned integers must not have a negitive value')
- int.__init__(value)
+ int.__init__(self, value)
class Int32(int):
def __init__(self, value):
- int.__init__(value)
+ int.__init__(self, value)
class UInt32(long):
def __init__(self, value):
if value < 0:
raise TypeError('Unsigned integers must not have a negitive value')
- long.__init__(value)
+ long.__init__(self, value)
class Int64(long):
def __init__(self, value):
- long.__init__(value)
+ long.__init__(self, value)
class UInt64(long):
def __init__(self, value):
if value < 0:
raise TypeError('Unsigned integers must not have a negitive value')
- long.__init__(value)
+ long.__init__(self, value)
class Double(float):
def __init__(self, value):
@@ -128,19 +128,49 @@ class Double(float):
class String(str):
def __init__(self, value):
- str.__init__(value)
+ str.__init__(self, value)
class Array(list):
- def __init__(self, value):
- list.__init__(value)
+ def __init__(self, value, type=None, signature=None):
+ if signature and type:
+ raise TypeError('Can not mix type and signature arguments in a D-BUS Array')
+
+ self.type = type
+ self.signature = signature
+ list.__init__(self, value)
+
+class Variant:
+ def __init__(self, value, type=None, signature=None):
+ self.value = value
+ if signature and type:
+ raise TypeError('Can not mix type and signature arguments in a D-BUS Variant')
+
+ self.type = type
+ self.signature = signature
+
+ def __repr__(self):
+ return repr(self.value)
+
+ def __str__(self):
+ return str(self.value)
class Struct(tuple):
def __init__(self, value):
- tuple.__init__(value)
+ tuple.__init__(self, value)
class Dictionary(dict):
- def __init__(self, value):
- dict.__init__(value)
+ def __init__(self, value, key_type=None, value_type=None, signature=None):
+ if key_type and not value_type:
+ raise TypeError('When specifying a key_type you must also have a value_type in a D-BUS Dictionary')
+ elif value_type and not key_type:
+ raise TypeError('When specifying a value_type you must also have a key_type in a D-BUS Dictionary')
+ elif key_type and signature:
+ raise TypeError('Can not mix type arguments with signature arguments in a D-BUS Dictionary')
+
+ self.key_type = key_type
+ self.value_type = value_type
+ self.signature = signature
+ dict.__init__(self, value)
#forward delcerations
cdef class Message
@@ -190,7 +220,7 @@ cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
return retval
finally:
PyGILState_Release(gil)
-
+
cdef class Connection:
def __init__(self, address=None, Connection _conn=None):
cdef DBusConnection *c_conn
@@ -297,7 +327,7 @@ cdef class Connection:
except Exception, e:
error_handler(e)
- return retval
+ return (retval, pending_call)
def send_with_reply(self, Message message, timeout_milliseconds):
cdef dbus_bool_t retval
@@ -470,7 +500,10 @@ cdef void _pending_call_notification(DBusPendingCall *pending_call, void *user_d
reply_handler(*args)
elif type == MESSAGE_TYPE_ERROR:
args = message.get_args_list()
- error_handler(DBusException(args[0]))
+ 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)))
@@ -628,7 +661,11 @@ cdef class MessageIter:
def get_boolean(self):
cdef dbus_bool_t c_val
dbus_message_iter_get_basic(self.iter, <dbus_bool_t *>&c_val)
- return c_val
+
+ if c_val:
+ return True
+ else:
+ return False
def get_signature(self):
signature_string = self.get_string()
@@ -637,6 +674,7 @@ cdef class MessageIter:
def get_int16(self):
cdef dbus_int16_t c_val
dbus_message_iter_get_basic(self.iter, <dbus_int16_t *>&c_val)
+
return c_val
def get_uint16(self):
@@ -672,6 +710,7 @@ cdef class MessageIter:
def get_string(self):
cdef char *c_str
dbus_message_iter_get_basic(self.iter, <char **>&c_str)
+
return c_str
def get_object_path(self):
@@ -797,60 +836,78 @@ cdef class MessageIter:
elif ptype == list:
ret = str(chr(TYPE_ARRAY))
ret = ret + self.python_value_to_dbus_sig(value[0], level)
- elif isinstance(value, ObjectPath):
+ elif isinstance(value, ObjectPath) or value == ObjectPath:
+
ret = TYPE_OBJECT_PATH
ret = str(chr(ret))
- elif isinstance(ByteArray):
+ elif isinstance(value, ByteArray) or value == ByteArray:
ret = str(chr(TYPE_ARRAY)) + str(chr(TYPE_BYTE))
- elif isinstance(Signature):
+ elif isinstance(value, Signature) or value == Signature:
ret = TYPE_SIGNATURE
ret = str(chr(ret))
- elif isinstance(value, Byte):
+ elif isinstance(value, Byte) or value == Byte:
ret = TYPE_BYTE
ret = str(chr(ret))
- elif isinstance(value, Boolean):
+ elif isinstance(value, Boolean) or value == Boolean:
ret = TYPE_BOOL
ret = str(chr(ret))
- elif isinstance(value, Int16):
+ elif isinstance(value, Int16) or value == Int16:
ret = TYPE_INT16
ret = str(chr(ret))
- elif isinstance(value, UInt16):
+ elif isinstance(value, UInt16) or value == UInt16:
ret = TYPE_UINT16
ret = str(chr(ret))
- elif isinstance(value, Int32):
+ elif isinstance(value, Int32) or value == Int32:
ret = TYPE_INT32
ret = str(chr(ret))
- elif isinstance(value, UInt32):
+ elif isinstance(value, UInt32) or value == UInt32:
ret = TYPE_UINT32
ret = str(chr(ret))
- elif isinstance(value, Int64):
+ elif isinstance(value, Int64) or value == Int64:
ret = TYPE_INT64
ret = str(chr(ret))
- elif isinstance(value, UInt64):
+ elif isinstance(value, UInt64) or value == UInt64:
ret = TYPE_UINT64
ret = str(chr(ret))
- elif isinstance(value, Double):
+ elif isinstance(value, Double) or value == Double:
ret = TYPE_DOUBLE
ret = str(chr(ret))
- elif isinstance(value, String):
+ elif isinstance(value, String) or value == String:
ret = TYPE_STRING
ret = str(chr(ret))
elif isinstance(value, Array):
ret = str(chr(TYPE_ARRAY))
- ret = ret + self.python_value_to_dbus_sig(value[0], level)
- elif isinstance(value, Struct):
+ if value.type == None:
+ if value.signature:
+ ret = ret + value.signature
+ else:
+ ret = ret + self.python_value_to_dbus_sig(value[0], level)
+ else:
+ ret = ret + self.python_value_to_dbus_sig(value.type, level)
+
+ elif isinstance(value, Struct) or value == Struct:
ret = str(chr(STRUCT_BEGIN))
for item in value:
ret = ret + self.python_value_to_dbus_sig(item, level)
ret = ret + str(chr(STRUCT_END))
elif isinstance(value, Dictionary):
- dict_list = value.items()
- key, value = dict_list[0]
-
ret = str(chr(TYPE_ARRAY)) + str(chr(DICT_ENTRY_BEGIN))
- ret = ret + self.python_value_to_dbus_sig(key, level)
- ret = ret + self.python_value_to_dbus_sig(value, level)
+
+ if value.key_type and value.value_type:
+ ret = ret + self.python_value_to_dbus_sig(value.key_type, level)
+ ret = ret + self.python_value_to_dbus_sig(value.value_type, level)
+ elif value.signature:
+ ret = ret + value.signature
+ else:
+ dict_list = value.items()
+
+ key, val = dict_list[0]
+ ret = ret + self.python_value_to_dbus_sig(key, level)
+ ret = ret + self.python_value_to_dbus_sig(val, level)
+
ret = ret + str(chr(DICT_ENTRY_END))
+ elif isinstance(value, Variant) or value == Variant:
+ ret = ret + str(chr(TYPE_VARIANT))
else:
raise TypeError, "Argument of unknown type '%s'" % (ptype)
@@ -910,6 +967,8 @@ cdef class MessageIter:
retval = self.append_struct(value)
elif isinstance(value, Dictionary):
retval = self.append_dict(value)
+ elif isinstance(value, Variant):
+ retval = self.append_variant(value)
else:
raise TypeError, "Argument of unknown type '%s'" % (value_type)
@@ -922,10 +981,13 @@ cdef class MessageIter:
def append_byte(self, value):
cdef char b
- if type(value) != str or len(value) != 1:
+ if type(value) == str and len(value) == 1:
+ b = ord(value)
+ elif type(value) == Byte:
+ b = value
+ else:
raise TypeError
- b = ord(value)
return dbus_message_iter_append_basic(self.iter, TYPE_BYTE, <char *>&b)
def append_int16(self, value):
@@ -985,12 +1047,27 @@ cdef class MessageIter:
level = self.level + 1
- dict_list = python_dict.items()
- key, value = dict_list[0]
+ key = None
+ value = None
sig = str(chr(DICT_ENTRY_BEGIN))
- sig = sig + self.python_value_to_dbus_sig(key)
- sig = sig + self.python_value_to_dbus_sig(value)
+
+ if isinstance(python_dict, Dictionary):
+ key = python_dict.key_type
+ value = python_dict.value_type
+ signature = python_dict.signature
+
+ dict_list = python_dict.items()
+
+ if signature:
+ sig = sig + signature
+ else:
+ if not (key and value):
+ key, value = dict_list[0]
+
+ sig = sig + self.python_value_to_dbus_sig(key)
+ sig = sig + self.python_value_to_dbus_sig(value)
+
sig = sig + str(chr(DICT_ENTRY_END))
dbus_message_iter_open_container(self.iter, TYPE_ARRAY, sig, <DBusMessageIter *>&c_dict_iter)
@@ -1002,13 +1079,22 @@ cdef class MessageIter:
dict_entry_iter = MessageIter(level)
dict_entry_iter.__cinit__(&c_dict_entry_iter)
- dict_entry_iter.append(key)
- dict_entry_iter.append(value)
+ 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
dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
dbus_message_iter_close_container(self.iter, dict_iter.iter)
+ return True
+
def append_struct(self, python_struct):
cdef DBusMessageIter c_struct_iter
cdef MessageIter struct_iter
@@ -1025,12 +1111,24 @@ cdef class MessageIter:
dbus_message_iter_close_container(self.iter, struct_iter.iter)
+ return True
+
def append_array(self, python_list):
cdef DBusMessageIter c_array_iter
cdef MessageIter array_iter
level = self.level + 1
- sig = self.python_value_to_dbus_sig(python_list[0])
+
+ sig = None
+ if isinstance(python_list, Array):
+ if python_list.type:
+ sig = self.python_value_to_dbus_sig(python_list.type)
+ elif python_list.signature:
+ sig = python_list.signature
+ else:
+ sig = self.python_value_to_dbus_sig(python_list[0])
+ else:
+ sig = self.python_value_to_dbus_sig(python_list[0])
dbus_message_iter_open_container(self.iter, TYPE_ARRAY, sig, <DBusMessageIter *>&c_array_iter)
array_iter = MessageIter(level)
@@ -1046,6 +1144,31 @@ cdef class MessageIter:
return True
+ def append_variant(self, value):
+ cdef DBusMessageIter c_variant_iter
+ cdef MessageIter variant_iter
+
+ level = self.level + 1
+
+ if value.signature:
+ sig = value.signature
+ elif value.type:
+ sig = self.python_value_to_dbus_sig(value.type)
+ else:
+ sig = self.python_value_to_dbus_sig(value.value)
+
+ dbus_message_iter_open_container(self.iter, TYPE_VARIANT, sig, <DBusMessageIter *>&c_variant_iter)
+
+ variant_iter = MessageIter(level)
+ variant_iter.__cinit__(&c_variant_iter)
+
+ if not variant_iter.append(value.value):
+ dbus_message_iter_close_container(self.iter, variant_iter.iter)
+ return False
+
+ dbus_message_iter_close_container(self.iter, variant_iter.iter)
+ return True
+
def __str__(self):
cdef DBusMessageIter c_array_iter
cdef MessageIter array_iter
diff --git a/python/examples/example-client.py b/python/examples/example-client.py
index 7439e6bd..3d170bd4 100644
--- a/python/examples/example-client.py
+++ b/python/examples/example-client.py
@@ -19,3 +19,4 @@ print str(hello_reply_tuple)
print str(hello_reply_dict)
print remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")
+
diff --git a/python/examples/list-system-services.py b/python/examples/list-system-services.py
index d4280551..4cad8717 100644
--- a/python/examples/list-system-services.py
+++ b/python/examples/list-system-services.py
@@ -2,6 +2,7 @@
"""Lists services on the system bus
"""
+
import dbus
# Get a connection to the SYSTEM bus
@@ -18,5 +19,4 @@ dbus_iface = dbus.Interface(dbus_object, 'org.freedesktop.DBus')
# One of the member functions in the org.freedesktop.DBus interface
# is ListServices(), which provides a list of all the other services
# registered on this bus. Call it, and print the list.
-system_service_list = dbus_object.ListNames()
-print str(system_service_list)
+print dbus_object.ListNames()
diff --git a/python/proxies.py b/python/proxies.py
index 95c98a9c..c7dc02be 100644
--- a/python/proxies.py
+++ b/python/proxies.py
@@ -1,6 +1,17 @@
import dbus_bindings
from exceptions import MissingReplyHandlerException, MissingErrorHandlerException
+class DeferedMethod:
+ """A DeferedMethod
+
+ This is returned instead of ProxyMethod when we are defering DBus calls
+ while waiting for introspection data to be returned
+
+ This class can be used for debugging purposes
+ """
+ def __call__(self, *args, **keywords):
+ return None
+
class ProxyMethod:
"""A proxy Method.
@@ -17,15 +28,19 @@ class ProxyMethod:
def __call__(self, *args, **keywords):
dbus_interface = self._dbus_interface
- if (keywords.has_key('dbus_interface')):
+ if keywords.has_key('dbus_interface'):
dbus_interface = keywords['dbus_interface']
+ timeout = -1
+ if keywords.has_key('timeout'):
+ timeout = keywords['timeout']
+
reply_handler = None
- if (keywords.has_key('reply_handler')):
+ if keywords.has_key('reply_handler'):
reply_handler = keywords['reply_handler']
error_handler = None
- if (keywords.has_key('error_handler')):
+ if keywords.has_key('error_handler'):
error_handler = keywords['error_handler']
if not(reply_handler and error_handler):
@@ -43,10 +58,10 @@ class ProxyMethod:
iter.append(arg)
if reply_handler:
- result = self._connection.send_with_reply_handlers(message, -1, reply_handler, error_handler)
- args_tuple = (result,)
+ result = self._connection.send_with_reply_handlers(message, timeout, reply_handler, error_handler)
+ args_tuple = result
else:
- reply_message = self._connection.send_with_reply_and_block(message, -1)
+ reply_message = self._connection.send_with_reply_and_block(message, timeout)
args_tuple = reply_message.get_args_list()
if len(args_tuple) == 0:
@@ -64,11 +79,31 @@ class ProxyObject:
have member functions, and can be called like normal Python objects.
"""
ProxyMethodClass = ProxyMethod
+ DeferedMethodClass = DeferedMethod
- def __init__(self, bus, named_service, object_path):
- self._bus = bus
+ INTROSPECT_STATE_DONT_INTROSPECT = 0
+ INTROSPECT_STATE_INTROSPECT_IN_PROGRESS = 1
+ INTROSPECT_STATE_INTROSPECT_DONE = 2
+
+ #TODO: default introspect to False right now because it is not done yet
+ # make sure to default to True later
+ def __init__(self, bus, named_service, object_path, introspect=False):
+ self._bus = bus
self._named_service = named_service
- self._object_path = object_path
+ self._object_path = object_path
+
+ #PendingCall object for Introspect call
+ self._pending_introspect = None
+ #queue of async calls waiting on the Introspect to return
+ self._pending_introspect_queue = []
+
+ if not introspect:
+ self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT
+ else:
+ self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
+
+ (result, self._pending_introspect) = self._Introspect()
+
def connect_to_signal(self, signal_name, handler_function, dbus_interface=None):
self._bus.add_signal_receiver(handler_function,
@@ -77,7 +112,28 @@ class ProxyObject:
named_service=self._named_service,
path=self._object_path)
+ def _Introspect(self):
+ message = dbus_bindings.MethodCall(self._object_path, 'org.freedesktop.DBus.Introspectable', 'Introspect')
+ message.set_destination(self._named_service)
+
+ result = self._bus.get_connection().send_with_reply_handlers(message, -1,
+ self._introspect_reply_handler,
+ self._introspect_error_handler)
+ return result
+
+ def _introspect_reply_handler(self, data):
+ self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_DONE
+
+ for call in self._pending_introspect_queue:
+ (member, iface, args, keywords) = call
+ call_object = self.ProxyMethodClass(self._bus.get_connection(),
+ self._named_service,
+ self._object_path, iface, member)
+
+ call_object(args, keywords)
+ def _introspect_error_handler(self, error):
+ self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT
def __getattr__(self, member, **keywords):
if member == '__call__':
@@ -86,12 +142,31 @@ class ProxyObject:
raise AttributeError(member)
else:
iface = None
- if (keywords.has_key('dbus_interface')):
+ if keywords.has_key('dbus_interface'):
iface = keywords['dbus_interface']
- return self.ProxyMethodClass(self._bus.get_connection(),
+ if self._introspect_state == self.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS:
+ reply_handler = None
+ if keywords.has_key('reply_handler'):
+ reply_handler = keywords['reply_handler']
+
+ error_handler = None
+ if keywords.has_key('error_handler'):
+ error_handler = keywords['error_handler']
+
+ if not reply_handler:
+ self._pending_introspect.block()
+ else:
+ call = (memeber, iface, args, keywords)
+ self._pending_introspect_queue.append(call)
+
+ ret = self.DeferedMethodClass()
+ return ret
+
+ ret = self.ProxyMethodClass(self._bus.get_connection(),
self._named_service,
self._object_path, iface, member)
+ return ret
def __repr__(self):
return '<ProxyObject wrapping %s %s %s at %x>'%(
diff --git a/python/service.py b/python/service.py
index edaef63f..bfe8fa5f 100644
--- a/python/service.py
+++ b/python/service.py
@@ -2,6 +2,8 @@
import dbus_bindings
import _dbus
from exceptions import UnknownMethodException
+from decorators import method
+from decorators import signal
class BusName:
"""A base class for exporting your own Named Services across the Bus
diff --git a/python/types.py b/python/types.py
index 1a01d8e4..f3d348c6 100644
--- a/python/types.py
+++ b/python/types.py
@@ -16,3 +16,4 @@ String = dbus_bindings.String
Array = dbus_bindings.Array
Struct = dbus_bindings.Struct
Dictionary = dbus_bindings.Dictionary
+Variant = dbus_bindings.Variant