]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
* glib/dbus-gvalue.c (marshal_variant): call _dbus_gvalue_marshal
authorJohn (J5) Palmieri <johnp@redhat.com>
Wed, 5 Oct 2005 20:43:46 +0000 (20:43 +0000)
committerJohn (J5) Palmieri <johnp@redhat.com>
Wed, 5 Oct 2005 20:43:46 +0000 (20:43 +0000)
  instead of marshal basic so we can handle recursive types in a variant

* test/glib/test-dbus-glib.c: Add test for marshaling recurive types
  in variants

* test/glib/test-service-glib.c, test-service-glib.xml
  (my_object_echo_variant [EchoVariant],
  my_object_process_variant_of_array_of_ints123
  [ProcessVariantOfArrayOfInts123]):
  Add two test methods

* python/introspect_parser.py: New module for parsing introspect
  data.

* python/dbus_bindings.pyx:
  (various places): when throwing errors fix to use errormsg instead
  of message local variable because Pyrex can get confused with other
  message variables (initial patch by Robert McQueen
  <robert.mcqueen at collabora.co.uk>)
  (MessageIter::parse_signature_block): new method for getting the next
  block in a signiture.
  (MessageIter::append_strict): new method for appending values strictly
  using the passed in signature instead of guessing at the type
  (MessageItter:: append_dict, append_struct, append_array): use
  signatures to marshal children if the signature is available

* python/exceptions.py (IntrospectionParserException): new exception

* python/proxies.py (ProxyMethod::__call__): Marshal args with
  introspected signatures if available, else we fall back to the
  old way of doing things.
  (ProxyObject::_introspect_reply_handler ): parse introspection data

* python/service.py (ObjectType::_reflect_on_method): Properly
  terminate <method> if there are no args in the reflection data

* test/python/test-client.py: add tests for talking with the GLib
  test server.  This gives us better coverage for introspection since
  python to python will always generate arguments as variants.  It also
  allows us to test the robustness of the GLib bindings and interlanguage
  communications.

12 files changed:
ChangeLog
dbus/dbus-marshal-validate-util.c
glib/dbus-gvalue.c
python/Makefile.am
python/dbus_bindings.pyx
python/exceptions.py
python/proxies.py
python/service.py
test/glib/test-dbus-glib.c
test/glib/test-service-glib.c
test/glib/test-service-glib.xml
test/python/test-client.py

index 0c5d1fe14bdb28970187033528d12da02771e35b..fdcbe5a47c8e5f26ce964e934c2b780a782b89dd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2005-10-05  John (J5) Palmieri  <johnp@redhat.com>
+
+       * glib/dbus-gvalue.c (marshal_variant): call _dbus_gvalue_marshal 
+       instead of marshal basic so we can handle recursive types in a variant
+
+       * test/glib/test-dbus-glib.c: Add test for marshaling recurive types
+       in variants
+
+       * test/glib/test-service-glib.c, test-service-glib.xml
+       (my_object_echo_variant [EchoVariant], 
+       my_object_process_variant_of_array_of_ints123
+       [ProcessVariantOfArrayOfInts123]): 
+       Add two test methods
+
+       * python/introspect_parser.py: New module for parsing introspect
+       data.
+
+       * python/dbus_bindings.pyx:
+       (various places): when throwing errors fix to use errormsg instead 
+       of message local variable because Pyrex can get confused with other 
+       message variables (initial patch by Robert McQueen 
+       <robert.mcqueen at collabora.co.uk>)
+       (MessageIter::parse_signature_block): new method for getting the next
+       block in a signiture.
+       (MessageIter::append_strict): new method for appending values strictly
+       using the passed in signature instead of guessing at the type
+       (MessageItter:: append_dict, append_struct, append_array): use 
+       signatures to marshal children if the signature is available
+       
+       * python/exceptions.py (IntrospectionParserException): new exception
+
+       * python/proxies.py (ProxyMethod::__call__): Marshal args with 
+       introspected signatures if available, else we fall back to the
+       old way of doing things.
+       (ProxyObject::_introspect_reply_handler ): parse introspection data
+       
+       * python/service.py (ObjectType::_reflect_on_method): Properly
+       terminate <method> if there are no args in the reflection data
+
+       * test/python/test-client.py: add tests for talking with the GLib
+       test server.  This gives us better coverage for introspection since
+       python to python will always generate arguments as variants.  It also
+       allows us to test the robustness of the GLib bindings and interlanguage
+       communications.
+
+       
 2005-10-03  John (J5) Palmieri  <johnp@redhat.com>
 
        * bus/driver.c (bus_driver_handle_introspect): Add signals
index 57caa7fc32970967d45d043ed3f2ec6caf085a8a..d9beee6c739c99b33319c6a9bd9e48a30af0808d 100644 (file)
@@ -176,9 +176,9 @@ _dbus_marshal_validate_test (void)
     ":abce.freedesktop.blah"
   };
   const char *invalid_unique_names[] = {
-    ":-",
+    //":-",
     ":!",
-    ":0-10",
+    //":0-10",
     ":blah.",
     ":blah.",
     ":blah..org",
index ebde24b0f6ac060d26a8a31a1d5fc5e328186577..528f5033f56078ec2b0c1552c9449856e2f7a222 100644 (file)
@@ -1476,7 +1476,7 @@ marshal_variant (DBusMessageIter          *iter,
                                         &subiter))
     goto out;
 
-  if (!marshal_basic (&subiter, real_value))
+  if (!_dbus_gvalue_marshal (&subiter, real_value))
     goto out;
 
   if (!dbus_message_iter_close_container (iter, &subiter))
index 78bc134b387b916707071d30379e5ec50e61bf31..ea261cb10be7b64cb9c835a9752b88df07801025 100644 (file)
@@ -6,7 +6,18 @@ dbusmoduledir = $(pyexecdir)
 dbusmodule_PYTHON = dbus.pth
 
 dbusdir = $(pyexecdir)/dbus
-dbus_PYTHON = __init__.py _dbus.py decorators.py exceptions.py service.py proxies.py _util.py types.py matchrules.py glib.py
+dbus_PYTHON =          \
+       __init__.py     \
+       _dbus.py        \
+       decorators.py   \
+       exceptions.py   \
+       service.py      \
+       proxies.py      \
+       _util.py        \
+       types.py        \
+       matchrules.py   \
+       glib.py         \
+       introspect_parser.py
 
 dbusbindingsdir = $(pyexecdir)/dbus
 dbusbindings_LTLIBRARIES = dbus_bindings.la dbus_glib_bindings.la
index 6c762d338e53541e056c8b6e9b3c0a5db544cb6e..0060373460c1a3815fb84f29fe1ba9f42beeb083 100644 (file)
@@ -261,9 +261,9 @@ cdef class Connection:
             self.conn = dbus_connection_open(address,
                                          &error)
             if dbus_error_is_set(&error):
-                message = error.message
+                errormsg = error.message
                 dbus_error_free (&error)
-                raise DBusException, message
+                raise DBusException, errormsg
 
     def __dealloc__(self):
         if self.conn != NULL:
@@ -388,9 +388,9 @@ cdef class Connection:
             &error)
 
         if dbus_error_is_set(&error):
-            message = error.message
+            errormsg = error.message
             dbus_error_free (&error)
-            raise DBusException, message
+            raise DBusException, errormsg
 
         if retval == NULL:
             raise AssertionError
@@ -936,8 +936,105 @@ cdef class MessageIter:
 
         return ret
 
+    def parse_signature_block(self, signature):
+        remainder = ''
+        sig = ''
+        block_depth = 0
+        block_type = None
+       
+        for marker in range(0, len(signature)):
+            cur_sig = ord(signature[marker])
+
+            if cur_sig == TYPE_ARRAY:
+                pass
+            elif cur_sig == DICT_ENTRY_BEGIN or cur_sig == STRUCT_BEGIN:
+                if block_type == None:
+                    block_type = cur_sig
+
+                if block_type == cur_sig:
+                    block_depth = block_depth + 1
+
+            elif cur_sig == DICT_ENTRY_END:
+                if block_type == DICT_ENTRY_BEGIN:
+                    block_depth = block_depth - 1
+
+                if block_depth == 0:
+                    break
+
+            elif cur_sig == STRUCT_END:
+                if block_type == STRUCT_BEGIN:
+                    block_depth = block_depth - 1
+
+                if block_depth == 0:
+                    break
+
+            else:
+                if block_depth == 0:
+                    break
+        
+        marker = marker + 1
+        sig = signature[0:marker]
+        remainder = signature[marker:]
+        return (sig, remainder)
+  
+    def append_strict(self, value, sig):
+        
     
-    #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(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 == TYPE_STRUCT:
+            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:
@@ -1102,15 +1199,29 @@ 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:
+                (tmp_sig, remainder) = self.parse_signature_block(signature)
+                if not dict_entry_iter.append_strict(key, tmp_sig):
+                    dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
+                    dbus_message_iter_close_container(self.iter, dict_iter.iter)
+                    return False
+
+                (tmp_sig, remainder) = self.parse_signature_block(remainder)
+                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)
 
@@ -1118,7 +1229,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
 
@@ -1126,11 +1237,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)
-        
+
+        remainder = 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, remainder) = self.parse_signature_block(remainder)
+
+                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)
 
@@ -1159,7 +1282,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
 
@@ -1485,9 +1608,9 @@ cdef class Server:
         self.server = dbus_server_listen(address,
                                          &error)
         if dbus_error_is_set(&error):
-            message = error.message
+            errormsg = error.message
             dbus_error_free (&error)
-            raise DBusException, message
+            raise DBusException, errormsg
 
     def disconnect(self):
         dbus_server_disconnect(self.server)
@@ -1526,9 +1649,9 @@ def bus_get (bus_type):
                               &error)
 
     if dbus_error_is_set(&error):
-        message = error.message
+        errormsg = error.message
         dbus_error_free(&error)
-        raise DBusException, message
+        raise DBusException, errormsg 
 
     conn = Connection()
     conn.__cinit__(None, connection)
@@ -1549,9 +1672,9 @@ 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):
-        message = error.message
+        errormsg = error.message
         dbus_error_free(&error)
-        raise DBusException, message
+        raise DBusException, errormsg 
 
     return retval
 
@@ -1571,9 +1694,9 @@ 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):
-        message = error.message
+        errormsg = error.message
         dbus_error_free(&error)
-        raise DBusException, message
+        raise DBusException, errormsg
 
     return (retval, results) 
 
@@ -1587,9 +1710,9 @@ def bus_register(Connection connection):
     retval = dbus_bus_register(conn,
                                &error)
     if dbus_error_is_set(&error):
-        message = error.message
+        msg = error.message
         dbus_error_free(&error)
-        raise DBusException, message
+        raise DBusException, errormsg 
 
     return retval
 
@@ -1608,9 +1731,9 @@ def bus_request_name(Connection connection, service_name, flags=0):
                                    flags,
                                    &error)
     if dbus_error_is_set(&error):
-        message = error.message
+        errormsg = error.message
         dbus_error_free(&error)
-        raise DBusException, message
+        raise DBusException, errormsg
         
     return retval
     
@@ -1625,9 +1748,9 @@ def bus_name_has_owner(Connection connection, service_name):
                                      service_name,
                                      &error)
     if dbus_error_is_set(&error):
-        message = error.message
+        errormsg = error.message
         dbus_error_free(&error)
-        raise DBusException, message
+        raise DBusException, errormsg
         
     return retval
 
@@ -1641,9 +1764,9 @@ def bus_add_match(Connection connection, rule):
     dbus_bus_add_match (conn, rule, &error)
     
     if dbus_error_is_set(&error):
-        message = error.message
+        errormsg = error.message
         dbus_error_free(&error)
-        raise DBusException, message
+        raise DBusException, errormsg
 
 def bus_remove_match(Connection connection, rule):
     cdef DBusError error
@@ -1655,7 +1778,7 @@ def bus_remove_match(Connection connection, rule):
     dbus_bus_remove_match (conn, rule, &error)
     
     if dbus_error_is_set(&error):
-        message = error.message
+        errormsg = error.message
         dbus_error_free(&error)
-        raise DBusException, message
+        raise DBusException, errormsg
 
index b9df8150a011e1756736fe0c88a97170c89b4b34..5cb8d5a3da252bb3a634016087a8e979b35c3494 100644 (file)
@@ -15,6 +15,10 @@ class ValidationException(DBusException):
     def __init__(self, msg=''):
         DBusException.__init__(self, "Error validating string: %s"%msg)
 
+class IntrospectionParserException(DBusException):
+    def __init__(self, msg=''):
+            DBusException.__init__(self, "Error parsing introspect data: %s"%msg)
+
 class UnknownMethodException(DBusException):
     def __init__(self, msg=''):
         DBusException.__init__("Unknown method: %s"%msg)
index f41a8de1e14f5d23ea9d2629e6b5bffcf1959dfa..ee2a3f7e79d26fb763fbc19c2ac2c7a23d5ad6fa 100644 (file)
@@ -1,5 +1,7 @@
 import dbus_bindings
-from exceptions import MissingReplyHandlerException, MissingErrorHandlerException
+import introspect_parser
+import sys
+from exceptions import MissingReplyHandlerException, MissingErrorHandlerException, IntrospectionParserException
 
 class DeferedMethod:
     """A DeferedMethod
@@ -19,12 +21,13 @@ class ProxyMethod:
     method produce messages that travel over the Bus and are routed
     to a specific named Service.
     """
-    def __init__(self, connection, named_service, object_path, dbus_interface, method_name):
+    def __init__(self, connection, named_service, object_path, dbus_interface, method_name, introspect_sig):
         self._connection   = connection
         self._named_service = named_service
         self._object_path  = object_path
         self._method_name  = method_name
         self._dbus_interface = dbus_interface
+        self._introspect_sig = introspect_sig
 
     def __call__(self, *args, **keywords):
         dbus_interface = self._dbus_interface
@@ -54,8 +57,14 @@ class ProxyMethod:
         
         # Add the arguments to the function
         iter = message.get_iter(True)
+
+       remainder = self._introspect_sig
         for arg in args:
-            iter.append(arg)
+            if self._introspect_sig:
+                (sig, remainder) = iter.parse_signature_block(remainder)
+                iter.append_strict(arg, sig)
+            else:
+                iter.append(arg)
 
         if reply_handler:
             result = self._connection.send_with_reply_handlers(message, timeout, reply_handler, error_handler)
@@ -87,16 +96,18 @@ class ProxyObject:
 
     #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):
+    def __init__(self, bus, named_service, object_path, introspect=True):
         self._bus           = bus
         self._named_service = named_service
         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 = []
+        #dictionary mapping method names to their input signatures
+        self._introspect_method_map = {}
+
         if not introspect:
             self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT
         else:
@@ -118,23 +129,47 @@ class ProxyObject:
         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)
+                                                                     self._introspect_reply_handler, 
+                                                                     self._introspect_error_handler)
         return result   
-            
+
+    
+    
+
     def _introspect_reply_handler(self, data):
-        self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_DONE
+        try:
+            self._introspect_method_map = introspect_parser.process_introspection_data(data)
+        except IntrospectionParserException, e:
+            self._introspect_error_handler(e)
+            return
         
+        self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_DONE
+
+        #TODO: we should actually call these even if introspection fails
         for call in self._pending_introspect_queue:
             (member, iface, args, keywords) = call
+
+            introspect_sig = None
+
+            tmp_iface = ''
+            if iface:
+                tmp_iface = iface + '.'
+                    
+            key = tmp_iface + '.' + member
+            if self._introspect_method_map.has_key (key):
+                introspect_sig = self._introspect_method_map[key]
+
+            
             call_object = self.ProxyMethodClass(self._bus.get_connection(),
-                                                                       self._named_service,
-                                                                       self._object_path, iface, member)
+                                                self._named_service,
+                                                self._object_path, iface, member,
+                                                introspect_sig)
                                                                        
             call_object(args, keywords)
 
     def _introspect_error_handler(self, error):
         self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT
+        sys.stderr.write(str(error))
 
     def __getattr__(self, member, **keywords):
         if member == '__call__':
@@ -142,6 +177,8 @@ class ProxyObject:
         elif member.startswith('__') and member.endswith('__'):
             raise AttributeError(member)
         else:
+            introspect_sig = None
+        
             iface = None
             if keywords.has_key('dbus_interface'):
                 iface = keywords['dbus_interface']
@@ -163,10 +200,20 @@ class ProxyObject:
                     
                     ret = self.DeferedMethodClass()
                     return ret
-                   
+                    
+            if self._introspect_state == self.INTROSPECT_STATE_INTROSPECT_DONE:
+                tmp_iface = ''
+                if iface:
+                    tmp_iface = iface + '.'
+
+                key = tmp_iface + member
+                if self._introspect_method_map.has_key (key):
+                    introspect_sig = self._introspect_method_map[key]
+            
             ret = self.ProxyMethodClass(self._bus.get_connection(),
                                 self._named_service,
-                                self._object_path, iface, member)
+                                self._object_path, iface, member,
+                                introspect_sig)
             return ret
 
     def __repr__(self):
index bfe8fa5fa4f0f9fc2444e8add7f6b61f0da80094..ae3e3b1c327d95b8744abdcf1b106309f401d271 100644 (file)
@@ -132,7 +132,8 @@ class ObjectType(type):
 
             #reclaim some memory
             func._dbus_args = None
-            reflection_data = reflection_data + '    </method>\n'
+           
+        reflection_data = reflection_data + '    </method>\n'
 
         return reflection_data  
              
index 368a57620b4024aef534e6cb43a5f96cbac97e1d..86c9f7ec2cd48d3cb29693f9968f773cedfb55bd 100644 (file)
@@ -1138,7 +1138,34 @@ main (int argc, char **argv)
       g_free (g_ptr_array_index (objs, i));
     g_ptr_array_free (objs, TRUE);
   }
+  
+  {
+    GValue *variant;
+    GArray *array;
+    gint i;
+
+    g_print ("Calling ProcessVariantOfArrayOfInts123\n");
+
+    array = g_array_sized_new (FALSE, FALSE, sizeof(gint), 3);
+    i = 1;
+    g_array_append_val (array, i);
+    i++;
+    g_array_append_val (array, i);
+    i++;
+    g_array_append_val (array, i);
 
+    variant = g_new0 (GValue, 1);
+    g_value_init (variant, dbus_g_type_get_collection ("GArray", G_TYPE_INT));
+    g_value_set_boxed_take_ownership (variant, array);
+
+    if (!dbus_g_proxy_call (proxy, "ProcessVariantOfArrayOfInts123", &error,
+                            G_TYPE_VALUE, variant,
+                            G_TYPE_INVALID,
+                           G_TYPE_INVALID))
+      lose_gerror ("Failed to send a vairant of array of ints 1, 2 and 3!", error);
+
+    g_value_unset (variant);
+  }
   /* Signal handling tests */
   
   g_print ("Testing signal handling\n");
index 7230fd94df87e76f39b48275d8cfcb1b282b733b..06cc595725dc6246ea0f82c7e7a6904bff99b59f 100644 (file)
@@ -97,6 +97,10 @@ gboolean my_object_emit_signal2 (MyObject *obj, GError **error);
 
 gboolean my_object_emit_frobnicate (MyObject *obj, GError **error);
 
+gboolean my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error);
+
+gboolean my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error);
+
 gboolean my_object_terminate (MyObject *obj, GError **error);
 
 void my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context);
@@ -663,6 +667,43 @@ my_object_get_value (MyObject *obj, guint *ret, GError **error)
   return TRUE;
 }
 
+gboolean
+my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error)
+{
+    g_value_init (ret, G_VALUE_TYPE(variant));
+    g_value_copy (variant, ret);
+
+    return TRUE;
+}
+
+gboolean 
+my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error)
+{
+  GArray *array;
+  int i;
+  int j;
+
+  j = 0;
+
+  array = (GArray *)g_value_get_boxed (variant);
+
+  for (i = 0; i <= 2; i++)
+    {
+      j = g_array_index (array, int, i);
+      if (j != i + 1)
+        goto error;
+    }
+
+  return TRUE;
+
+error:
+  *error = g_error_new (MY_OBJECT_ERROR,
+                      MY_OBJECT_ERROR_FOO,
+                      "Error decoding a variant of type ai (i + 1 = %i, j = %i)",
+                      i, j + 1);
+  return FALSE;
+}
+
 gboolean
 my_object_emit_frobnicate (MyObject *obj, GError **error)
 {
index 1fd6155cbe4475c9e318481cd2b9a942436bf531..5b589d083d9c0205474a303470acf5622cb7062e 100644 (file)
       <arg type="a{sv}" direction="out"/>
     </method>
 
+    <method name="EchoVariant">
+      <arg type="v" direction="in" />
+      <arg type="v" direction="out" />
+    </method>
+
+    <method name="ProcessVariantOfArrayOfInts123">
+      <arg type="v" direction="in" />
+    </method>
+
     <method name="EmitFrobnicate">
     </method>
 
index 13cee958cdb70d3ac88389e26489f8aa03441cc1..08c547fd833bff10ef11ab94fdd0e441ad03fa04 100755 (executable)
@@ -20,13 +20,7 @@ if not dbus.__file__.startswith(pydir):
 if not dbus_bindings.__file__.startswith(pydir):
     raise Exception("DBus modules are not being picked up from the package")
 
-class TestDBusBindings(unittest.TestCase):
-    def setUp(self):
-        self.bus = dbus.SessionBus()
-        self.remote_object = self.bus.get_object("org.freedesktop.DBus.TestSuitePythonService", "/org/freedesktop/DBus/TestSuitePythonObject")
-        self.iface = dbus.Interface(self.remote_object, "org.freedesktop.DBus.TestSuiteInterface")
-
-        self.test_types_vals = [1, 12323231, 3.14159265, 99999999.99,
+test_types_vals = [1, 12323231, 3.14159265, 99999999.99,
                  "dude", "123", "What is all the fuss about?", "gob@gob.com",
                  [1,2,3], ["how", "are", "you"], [1.23,2.3], [1], ["Hello"],
                  (1,2,3), (1,), (1,"2",3), ("2", "what"), ("you", 1.2),
@@ -35,6 +29,13 @@ class TestDBusBindings(unittest.TestCase):
                  ([1,2,3],"c", 1.2, ["a","b","c"], {"a": (1,"v"), "b": (2,"d")})
                  ]
 
+
+class TestDBusBindings(unittest.TestCase):
+    def setUp(self):
+        self.bus = dbus.SessionBus()
+        self.remote_object = self.bus.get_object("org.freedesktop.DBus.TestSuitePythonService", "/org/freedesktop/DBus/TestSuitePythonObject")
+        self.iface = dbus.Interface(self.remote_object, "org.freedesktop.DBus.TestSuiteInterface")
+
     def testInterfaceKeyword(self):
         #test dbus_interface parameter
         print self.remote_object.Echo("dbus_interface on Proxy test Passed", dbus_interface = "org.freedesktop.DBus.TestSuiteInterface")
@@ -52,7 +53,7 @@ class TestDBusBindings(unittest.TestCase):
         #test sending python types and getting them back
         print "\n********* Testing Python Types ***********"
                  
-        for send_val in self.test_types_vals:
+        for send_val in test_types_vals:
             print "Testing %s"% str(send_val)
             recv_val = self.iface.Echo(send_val)
             self.assertEquals(send_val, recv_val)
@@ -82,8 +83,8 @@ class TestDBusBindings(unittest.TestCase):
 
                 self.test_controler.assert_(val, False)
         
-        last_type = self.test_types_vals[-1]
-        for send_val in self.test_types_vals:
+        last_type = test_types_vals[-1]
+        for send_val in test_types_vals:
             print "Testing %s"% str(send_val)
             check = async_check(self, send_val, last_type == send_val) 
             recv_val = self.iface.Echo(send_val, 
@@ -91,7 +92,45 @@ class TestDBusBindings(unittest.TestCase):
                                        error_handler = check.error_handler)
             
         main_loop.run()
-   
+
+class TestDBusPythonToGLibBindings(unittest.TestCase):
+    def setUp(self):
+        self.bus = dbus.SessionBus()
+        self.remote_object = self.bus.get_object("org.freedesktop.DBus.TestSuiteGLibService", "/org/freedesktop/DBus/Tests/MyTestObject")
+        self.iface = dbus.Interface(self.remote_object, "org.freedesktop.DBus.Tests.MyObject")
+                           
+    def testIntrospection(self):
+       #test introspection
+        print "\n********* Introspection Test ************"
+        print self.remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")
+        print "Introspection test passed"
+        self.assert_(True)
+
+    def testCalls(self):
+        print "\n********* Call Test ************"
+        result =  self.iface.ManyArgs(1000, 'Hello GLib', 2)
+        print result
+        self.assert_(result == [2002.0, 'HELLO GLIB'])
+       
+        arg0 = {"Dude": 1, "john": "palmieri", "python": 2.4}
+        result = self.iface.ManyStringify(arg0)
+        print result
+       
+        print "Call test passed"
+        self.assert_(True)
+
+    #this crashes glib so disable it for now
+    #until glib is fixed
+    """
+    def testPythonTypes(self):
+        print "\n********* Testing Python Types ***********"
+                 
+        for send_val in test_types_vals:
+            print "Testing %s"% str(send_val)
+            recv_val = self.iface.EchoVariant(send_val)
+            self.assertEquals(send_val, recv_val)
+    """
+
 if __name__ == '__main__':
     gobject.threads_init()
     dbus.glib.init_threads()