[pygobject] Add support for GVariant properties defined in Python



commit 78f49e6253500bfa382ce6c07412613d8f7f9d7f
Author: Martin Pitt <martinpitt gnome org>
Date:   Wed Nov 14 10:14:36 2012 +0100

    Add support for GVariant properties defined in Python

 gi/_gobject/gobjectmodule.c   |   13 +++++++
 gi/_gobject/propertyhelper.py |   11 ++++--
 tests/test_properties.py      |   81 +++++++++++++++++++++++++++++++++++------
 3 files changed, 91 insertions(+), 14 deletions(-)
---
diff --git a/gi/_gobject/gobjectmodule.c b/gi/_gobject/gobjectmodule.c
index 89c3285..479eb93 100644
--- a/gi/_gobject/gobjectmodule.c
+++ b/gi/_gobject/gobjectmodule.c
@@ -639,6 +639,19 @@ create_property (const gchar  *prop_name,
 	    return NULL;
 	pspec = g_param_spec_object (prop_name, nick, blurb, prop_type, flags);
 	break;
+    case G_TYPE_VARIANT:
+	{
+	    PyObject *pydefault;
+            GVariant *default_value = NULL;
+
+	    if (!PyArg_ParseTuple(args, "O", &pydefault))
+		return NULL;
+            if (pydefault != Py_None)
+                default_value = pyg_boxed_get (pydefault, GVariant);
+            Py_DECREF(pydefault);
+	    pspec = g_param_spec_variant (prop_name, nick, blurb, G_VARIANT_TYPE_ANY, default_value, flags);
+	}
+	break;
     default:
 	/* unhandled pspec type ... */
 	break;
diff --git a/gi/_gobject/propertyhelper.py b/gi/_gobject/propertyhelper.py
index 9e44af4..a951ff3 100644
--- a/gi/_gobject/propertyhelper.py
+++ b/gi/_gobject/propertyhelper.py
@@ -29,7 +29,7 @@ from .constants import \
     TYPE_ULONG, TYPE_INT64, TYPE_UINT64, TYPE_ENUM, TYPE_FLAGS, \
     TYPE_FLOAT, TYPE_DOUBLE, TYPE_STRING, \
     TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, \
-    TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV
+    TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV, TYPE_VARIANT
 from ._gobject import \
     G_MAXFLOAT, G_MAXDOUBLE, \
     G_MININT, G_MAXINT, G_MAXUINT, G_MINLONG, G_MAXLONG, \
@@ -264,7 +264,7 @@ class Property(object):
                        TYPE_ULONG, TYPE_INT64, TYPE_UINT64,
                        TYPE_FLOAT, TYPE_DOUBLE, TYPE_POINTER,
                        TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, TYPE_STRING,
-                       TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV):
+                       TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV, TYPE_VARIANT):
             return type_
         else:
             raise TypeError("Unsupported type: %r" % (type_,))
@@ -302,6 +302,10 @@ class Property(object):
             for val in default:
                 if type(val) not in (str, bytes):
                     raise TypeError("Strv value %s must contain only strings" % str(default))
+        elif _gobject.type_is_a(ptype, TYPE_VARIANT) and default is not None:
+            if not hasattr(default, '__gtype__') or not _gobject.type_is_a(default, TYPE_VARIANT):
+                raise TypeError("variant value %s must be an instance of %r" %
+                                (default, ptype))
 
     def _get_minimum(self):
         return self._min_value_lookup.get(self.type, None)
@@ -337,7 +341,8 @@ class Property(object):
                      TYPE_INT64, TYPE_UINT64, TYPE_FLOAT, TYPE_DOUBLE):
             args = self.minimum, self.maximum, self.default
         elif (ptype == TYPE_STRING or ptype == TYPE_BOOLEAN or
-              ptype.is_a(TYPE_ENUM) or ptype.is_a(TYPE_FLAGS)):
+              ptype.is_a(TYPE_ENUM) or ptype.is_a(TYPE_FLAGS) or
+              ptype.is_a(TYPE_VARIANT)):
             args = (self.default,)
         elif ptype in (TYPE_PYOBJECT, TYPE_GTYPE):
             args = ()
diff --git a/tests/test_properties.py b/tests/test_properties.py
index fb29045..6a6790b 100644
--- a/tests/test_properties.py
+++ b/tests/test_properties.py
@@ -13,7 +13,7 @@ from gi.repository.GObject import \
     TYPE_UINT64, TYPE_GTYPE, TYPE_INVALID, TYPE_NONE, TYPE_STRV, \
     TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_BOOLEAN, TYPE_FLOAT, \
     TYPE_DOUBLE, TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, \
-    TYPE_STRING, TYPE_PYOBJECT
+    TYPE_STRING, TYPE_PYOBJECT, TYPE_VARIANT
 
 from gi.repository.GObject import \
     G_MININT, G_MAXINT, G_MAXUINT, G_MINLONG, G_MAXLONG, G_MAXULONG
@@ -61,6 +61,12 @@ class PropertyObject(GObject.GObject):
     strings = GObject.Property(
         type=TYPE_STRV, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
 
+    variant = GObject.Property(
+        type=TYPE_VARIANT, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
+
+    variant_def = GObject.Property(
+        type=TYPE_VARIANT, flags=PARAM_READWRITE | PARAM_CONSTRUCT,
+        default=GLib.Variant('i', 42))
 
 class PropertyInheritanceObject(Regress.TestObj):
     # override property from the base class, with a different type
@@ -112,19 +118,24 @@ class TestPropertyObject(unittest.TestCase):
 
     def test_iteration(self):
         for obj in (PropertyObject.props, PropertyObject().props):
+            names = []
             for pspec in obj:
                 gtype = GType(pspec)
                 self.assertEqual(gtype.parent.name, 'GParam')
-                self.assertTrue(pspec.name in ['normal',
-                                               'construct',
-                                               'construct-only',
-                                               'uint64',
-                                               'enum',
-                                               'flags',
-                                               'gtype',
-                                               'strings',
-                                               'boxed'])
-            self.assertEqual(len(obj), 9)
+                names.append(pspec.name)
+
+            names.sort()
+            self.assertEqual(names, ['boxed',
+                                     'construct',
+                                     'construct-only',
+                                     'enum',
+                                     'flags',
+                                     'gtype',
+                                     'normal',
+                                     'strings',
+                                     'uint64',
+                                     'variant',
+                                     'variant-def'])
 
     def test_normal(self):
         obj = new(PropertyObject, normal="123")
@@ -330,6 +341,54 @@ class TestPropertyObject(unittest.TestCase):
         self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
                           default=['hello', 1])
 
+    def test_variant(self):
+        obj = new(PropertyObject)
+
+        self.assertEqual(obj.props.variant, None)
+        self.assertEqual(obj.variant, None)
+
+        obj.variant = GLib.Variant('s', 'hello')
+        self.assertEqual(obj.variant.print_(True), "'hello'")
+
+        obj.variant = GLib.Variant('b', True)
+        self.assertEqual(obj.variant.print_(True), "true")
+
+        obj.props.variant = GLib.Variant('y', 2)
+        self.assertEqual(obj.variant.print_(True), "byte 0x02")
+
+        obj.variant = None
+        self.assertEqual(obj.variant, None)
+
+        # set in constructor
+        obj = new(PropertyObject, variant=GLib.Variant('u', 5))
+        self.assertEqual(obj.props.variant.print_(True), 'uint32 5')
+
+        GObject.Property(type=TYPE_VARIANT, default=GLib.Variant('i', 1))
+
+        # incompatible types
+        self.assertRaises(TypeError, setattr, obj, 'variant', 'foo')
+        self.assertRaises(TypeError, setattr, obj, 'variant', 42)
+
+        self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT,
+                          default='foo')
+        self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT,
+                          default=object())
+
+
+    def test_variant_default(self):
+        obj = new(PropertyObject)
+
+        self.assertEqual(obj.props.variant_def.print_(True), '42')
+        self.assertEqual(obj.variant_def.print_(True), '42')
+
+        obj.props.variant_def = GLib.Variant('y', 2)
+        self.assertEqual(obj.variant_def.print_(True), "byte 0x02")
+
+        # set in constructor
+        obj = new(PropertyObject, variant_def=GLib.Variant('u', 5))
+        self.assertEqual(obj.props.variant_def.print_(True), 'uint32 5')
+
+
     def test_range(self):
         # kiwi code
         def max(c):



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