[pygobject] gi/pygi-value: Don't wrap GValue in GValue when creating GValueArray



commit b5eab39ebcae061a46c186beac47f7e936ce57c2
Author: Stian Selnes <stian pexip com>
Date:   Tue Apr 11 11:17:31 2017 +0200

    gi/pygi-value: Don't wrap GValue in GValue when creating GValueArray
    
    If a GValueArray is created from a list of GValues, it should not wrap
    these GValues in a second layer of GValues before appending to the
    array. The end result should be a GValueArray of GValues, not a
    GValueArray of GValues holding another GValue (unless the user
    explicitly creates such a value).
    
    With this patch the behavior is now consistent when creating a
    GValueArray and appending GValues directly, and creating a GValueArray
    within a GValue based on a list of GValues.
    
    For instance, to create a GValueArray of G_TYPE_UINT the user must
    create GValues manually and create a GValueArray from these. The result
    should be a GValueArray of GValues that hold G_TYPE_UINT, not a
    GValueArray that contain GValues that hold a GValue that holds
    G_TYPE_UINT.
    
    See !66

 gi/pygi-value.c          | 31 ++++++++++++++++++-------------
 tests/test_gobject.py    | 18 ++++++++++++++++++
 tests/testhelpermodule.c | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 13 deletions(-)
---
diff --git a/gi/pygi-value.c b/gi/pygi-value.c
index fadebdc2..93669345 100644
--- a/gi/pygi-value.c
+++ b/gi/pygi-value.c
@@ -196,8 +196,6 @@ pyg_value_array_from_pyobject(GValue *value,
     for (i = 0; i < len; ++i) {
         PyObject *item = PySequence_GetItem(obj, i);
         GType type;
-        GValue item_value = { 0, };
-        int status;
 
         if (! item) {
             PyErr_Clear();
@@ -219,20 +217,27 @@ pyg_value_array_from_pyobject(GValue *value,
             }
         }
 
-        g_value_init(&item_value, type);
-        status = (pspec && pspec->element_spec)
-                 ? pyg_param_gvalue_from_pyobject(&item_value, item, pspec->element_spec)
-                 : pyg_value_from_pyobject(&item_value, item);
-        Py_DECREF(item);
+        if (type == G_TYPE_VALUE) {
+            const GValue * item_value = pyg_boxed_get(item, GValue);
+            g_value_array_append(value_array, item_value);
+        } else {
+            GValue item_value = { 0, };
+            int status;
 
-        if (status == -1) {
-            g_value_array_free(value_array);
+            g_value_init(&item_value, type);
+            status = (pspec && pspec->element_spec)
+                ? pyg_param_gvalue_from_pyobject(&item_value, item, pspec->element_spec)
+                : pyg_value_from_pyobject(&item_value, item);
+            Py_DECREF(item);
+
+            if (status == -1) {
+                g_value_array_free(value_array);
+                g_value_unset(&item_value);
+                return -1;
+            }
+            g_value_array_append(value_array, &item_value);
             g_value_unset(&item_value);
-            return -1;
         }
-
-        g_value_array_append(value_array, &item_value);
-        g_value_unset(&item_value);
     }
 
     g_value_take_boxed(value, value_array);
diff --git a/tests/test_gobject.py b/tests/test_gobject.py
index cf3d8b54..5d817601 100644
--- a/tests/test_gobject.py
+++ b/tests/test_gobject.py
@@ -698,6 +698,24 @@ class TestGValue(unittest.TestCase):
         value.set_value([32, 'foo_bar', 0.3])
         self.assertEqual(value.get_value(), [32, 'foo_bar', 0.3])
 
+    def test_value_array_from_gvalue_list(self):
+        value = GObject.Value(GObject.ValueArray, [
+            GObject.Value(GObject.TYPE_UINT, 0xffffffff),
+            GObject.Value(GObject.TYPE_STRING, 'foo_bar')])
+        self.assertEqual(value.g_type, GObject.type_from_name('GValueArray'))
+        self.assertEqual(value.get_value(), [0xffffffff, 'foo_bar'])
+        self.assertEqual(testhelper.value_array_get_nth_type(value, 0), GObject.TYPE_UINT)
+        self.assertEqual(testhelper.value_array_get_nth_type(value, 1), GObject.TYPE_STRING)
+
+    def test_value_array_append_gvalue(self):
+        arr = GObject.ValueArray.new(0)
+        arr.append(GObject.Value(GObject.TYPE_UINT, 0xffffffff))
+        arr.append(GObject.Value(GObject.TYPE_STRING, 'foo_bar'))
+        self.assertEqual(arr.get_nth(0), 0xffffffff)
+        self.assertEqual(arr.get_nth(1), 'foo_bar')
+        self.assertEqual(testhelper.value_array_get_nth_type(arr, 0), GObject.TYPE_UINT)
+        self.assertEqual(testhelper.value_array_get_nth_type(arr, 1), GObject.TYPE_STRING)
+
     def test_gerror_boxing(self):
         error = GLib.Error('test message', domain='mydomain', code=42)
         value = GObject.Value(GLib.Error, error)
diff --git a/tests/testhelpermodule.c b/tests/testhelpermodule.c
index 3973a503..e26a004b 100644
--- a/tests/testhelpermodule.c
+++ b/tests/testhelpermodule.c
@@ -534,6 +534,43 @@ _wrap_test_value_array(PyObject *self, PyObject *args)
   return pyg_value_as_pyobject(value, FALSE);
 }
 
+
+static PyObject *
+_wrap_value_array_get_nth_type(PyObject *self, PyObject *args)
+{
+  guint n;
+  GType type;
+  GValue *nth;
+  GValueArray *arr;
+  PyObject *obj;
+
+  if (!PyArg_ParseTuple(args, "OI", &obj, &n))
+    return NULL;
+
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+  if (pyg_boxed_check(obj, G_TYPE_VALUE) &&
+      G_VALUE_HOLDS(pyg_boxed_get(obj, GValue), G_TYPE_VALUE_ARRAY)) {
+    arr = g_value_get_boxed(pyg_boxed_get(obj, GValue));
+  } else if (pyg_boxed_check(obj, G_TYPE_VALUE_ARRAY)) {
+    arr = pyg_boxed_get(obj, GValueArray);
+  } else {
+    PyErr_SetString(PyExc_TypeError, "First argument is not GValueArray");
+    return NULL;
+  }
+
+  if (n >= arr->n_values) {
+    PyErr_SetString(PyExc_TypeError, "Index is out of bounds");
+    return NULL;
+  }
+  nth = g_value_array_get_nth(arr, n);
+  type = G_VALUE_TYPE(nth);
+
+  G_GNUC_END_IGNORE_DEPRECATIONS
+
+  return pyg_type_wrapper_new(type);
+}
+
 static PyObject *
 _wrap_constant_strip_prefix(PyObject *self, PyObject *args)
 {
@@ -665,6 +702,7 @@ static PyMethodDef testhelper_functions[] = {
     { "connectcallbacks", (PyCFunction)_wrap_connectcallbacks, METH_VARARGS },
     { "test_value", (PyCFunction)_wrap_test_value, METH_VARARGS },      
     { "test_value_array", (PyCFunction)_wrap_test_value_array, METH_VARARGS },
+    { "value_array_get_nth_type", (PyCFunction)_wrap_value_array_get_nth_type, METH_VARARGS },
     { "constant_strip_prefix", (PyCFunction)_wrap_constant_strip_prefix, METH_VARARGS },
     { "test_gerror_exception", (PyCFunction)_wrap_test_gerror_exception, METH_VARARGS },
     { "owned_by_library_get_instance_list", (PyCFunction)_wrap_test_owned_by_library_get_instance_list, 
METH_NOARGS },


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