]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
* python/__init__.py: Version updated (0, 43, 0)
authorJohn (J5) Palmieri <johnp@redhat.com>
Tue, 16 Aug 2005 22:54:04 +0000 (22:54 +0000)
committerJohn (J5) Palmieri <johnp@redhat.com>
Tue, 16 Aug 2005 22:54:04 +0000 (22:54 +0000)
* 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

ChangeLog
python/__init__.py
python/_dbus.py
python/dbus_bindings.pyx
python/examples/example-client.py
python/examples/list-system-services.py
python/proxies.py
python/service.py
python/types.py

index c7fc00f1bb50202a7385b5b30c52d88c2bec905a..dfceda3229dbb07841ea1156a03ab3d36989eb53 100644 (file)
--- 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
index 945ef67edd3420d104ab5444135cf22abd214956..a1ff407ae59a2b0f070ac0b315025929a3a3481b 100644 (file)
@@ -1,5 +1,5 @@
 from _dbus import *
 from types import *
 
-version = (0, 42, 0)
+version = (0, 43, 0)
 _dbus_main_loop_setup_function = None
index f0c7b0695e32db0e1a61f01f4bf8e0d177bdd99c..6074be16634e6b3ec5a1affce3264076db3d96f4 100644 (file)
@@ -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))
index 608ef544d4aa5ede9645dc69909b1db5d0acda77..a083f504bdc4494118798f146d77a487d6917cec 100644 (file)
@@ -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
index 7439e6bdd9ec5fdacc0be17e09f2b8370ac83365..3d170bd406b536ad6e1a1d0ac45069e4a142a703 100644 (file)
@@ -19,3 +19,4 @@ print str(hello_reply_tuple)
 print str(hello_reply_dict)
 
 print remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")
+
index d42805515fdba8916711550a26d4e97560342477..4cad8717ad7a4f121d046e3508b213ec3da15355 100644 (file)
@@ -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()
index 95c98a9c1ddaf24ac01b994a6b3addf33d8363d6..c7dc02beea3f2dbe9072a64fb66dbff8ca31686c 100644 (file)
@@ -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>'%( 
index edaef63ff6d787ad03ff52fe199a93e0a3a62535..bfe8fa5fa4f0f9fc2444e8add7f6b61f0da80094 100644 (file)
@@ -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
index 1a01d8e41f98c9ca7e42d13c8b233d4af858086a..f3d348c60d0dbf64f45c2e2e246711635263595b 100644 (file)
@@ -16,3 +16,4 @@ String = dbus_bindings.String
 Array = dbus_bindings.Array
 Struct = dbus_bindings.Struct
 Dictionary = dbus_bindings.Dictionary
+Variant = dbus_bindings.Variant