[pygobject] GVariant overrides: Support empty tuple arrays



commit bfd9c8fac1ea240b29fbcd4185dc1702539c1e96
Author: Martin Pitt <martinpitt gnome org>
Date:   Thu Sep 27 08:18:34 2012 +0200

    GVariant overrides: Support empty tuple arrays
    
    Implement the "empty value" branch in _create_tuple(), so that _create_array()
    can call it for parsing the element type for an empty array.
    
    This fixes creating variants such as GLib.Variant('a(ii)', []).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=684928

 gi/overrides/GLib.py         |   30 +++++++++++++++++++++++-------
 tests/test_overrides_glib.py |   31 +++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 7 deletions(-)
---
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index c41f523..b6f2ce2e 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -85,11 +85,23 @@ class _VariantCreator(object):
         '''Handle the case where the outermost type of format is a tuple.'''
 
         format = format[1:]  # eat the '('
-        builder = GLib.VariantBuilder.new(variant_type_from_string('r'))
-        if args is not None:
+        if args is None:
+            # empty value: we need to call _create() to parse the subtype
+            rest_format = format
+            while rest_format:
+                if rest_format.startswith(')'):
+                    break
+                rest_format = self._create(rest_format, None)[1]
+            else:
+                raise TypeError('tuple type string not closed with )')
+
+            rest_format = rest_format[1:]  # eat the )
+            return (None, rest_format, None)
+        else:
             if not args or not isinstance(args[0], tuple):
                 raise TypeError('expected tuple argument')
 
+            builder = GLib.VariantBuilder.new(variant_type_from_string('r'))
             for i in range(len(args[0])):
                 if format.startswith(')'):
                     raise TypeError('too many arguments for tuple signature')
@@ -97,7 +109,11 @@ class _VariantCreator(object):
                 (v, format, _) = self._create(format, args[0][i:])
                 builder.add_value(v)
             args = args[1:]
-        return (builder.end(), format[1:], args)
+            if not format.startswith(')'):
+                raise TypeError('tuple type string not closed with )')
+
+            rest_format = format[1:]  # eat the )
+            return (builder.end(), rest_format, args)
 
     def _create_dict(self, format, args):
         '''Handle the case where the outermost type of format is a dict.'''
@@ -109,8 +125,8 @@ class _VariantCreator(object):
             rest_format = self._create(format[2:], None)[1]
             rest_format = self._create(rest_format, None)[1]
             if not rest_format.startswith('}'):
-                raise ValueError('dictionary type string not closed with }')
-            rest_format = rest_format[1:]  # eat the}
+                raise TypeError('dictionary type string not closed with }')
+            rest_format = rest_format[1:]  # eat the }
             element_type = format[:len(format) - len(rest_format)]
             builder = GLib.VariantBuilder.new(variant_type_from_string(element_type))
         else:
@@ -120,8 +136,8 @@ class _VariantCreator(object):
                 (val_v, rest_format, _) = self._create(rest_format, [v])
 
                 if not rest_format.startswith('}'):
-                    raise ValueError('dictionary type string not closed with }')
-                rest_format = rest_format[1:]  # eat the}
+                    raise TypeError('dictionary type string not closed with }')
+                rest_format = rest_format[1:]  # eat the }
 
                 entry = GLib.VariantBuilder.new(variant_type_from_string('{?*}'))
                 entry.add_value(key_v)
diff --git a/tests/test_overrides_glib.py b/tests/test_overrides_glib.py
index 4c77011..3799454 100644
--- a/tests/test_overrides_glib.py
+++ b/tests/test_overrides_glib.py
@@ -151,6 +151,30 @@ class TestGVariant(unittest.TestCase):
         self.assertEqual(variant.get_child_value(0).n_children(), 1)
         self.assertEqual(variant.get_child_value(0).get_child_value(0).get_string(), 'hello')
 
+        variant = GLib.Variant('a(ii)', [])
+        self.assertEqual(variant.get_type_string(), 'a(ii)')
+        self.assertEqual(variant.n_children(), 0)
+
+        variant = GLib.Variant('a(ii)', [(5, 6)])
+        self.assertEqual(variant.get_type_string(), 'a(ii)')
+        self.assertEqual(variant.n_children(), 1)
+        self.assertEqual(variant.get_child_value(0).n_children(), 2)
+        self.assertEqual(variant.get_child_value(0).get_child_value(0).get_int32(), 5)
+        self.assertEqual(variant.get_child_value(0).get_child_value(1).get_int32(), 6)
+
+        variant = GLib.Variant('(a(ii))', ([],))
+        self.assertEqual(variant.get_type_string(), '(a(ii))')
+        self.assertEqual(variant.n_children(), 1)
+        self.assertEqual(variant.get_child_value(0).n_children(), 0)
+
+        variant = GLib.Variant('(a(ii))', ([(5, 6)],))
+        self.assertEqual(variant.get_type_string(), '(a(ii))')
+        self.assertEqual(variant.n_children(), 1)
+        self.assertEqual(variant.get_child_value(0).n_children(), 1)
+        self.assertEqual(variant.get_child_value(0).get_child_value(0).n_children(), 2)
+        self.assertEqual(variant.get_child_value(0).get_child_value(0).get_child_value(0).get_int32(), 5)
+        self.assertEqual(variant.get_child_value(0).get_child_value(0).get_child_value(1).get_int32(), 6)
+
         obj = {'a1': (1, True), 'a2': (2, False)}
         variant = GLib.Variant('a{s(ib)}', obj)
         self.assertEqual(variant.get_type_string(), 'a{s(ib)}')
@@ -204,6 +228,13 @@ class TestGVariant(unittest.TestCase):
         # unimplemented data type
         self.assertRaises(NotImplementedError, GLib.Variant, 'Q', 1)
 
+        # invalid types
+        self.assertRaises(TypeError, GLib.Variant, '(ii', (42, 3))
+        self.assertRaises(TypeError, GLib.Variant, '(ii))', (42, 3))
+        self.assertRaises(TypeError, GLib.Variant, 'a{si', {})
+        self.assertRaises(TypeError, GLib.Variant, 'a{si}}', {})
+        self.assertRaises(TypeError, GLib.Variant, 'a{iii}', {})
+
     def test_unpack(self):
         # simple values
         res = GLib.Variant.new_int32(-42).unpack()



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]