summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStian Selnes <stian@pexip.com>2017-04-11 11:17:31 +0200
committerChristoph Reiter <reiter.christoph@gmail.com>2018-05-04 18:56:04 +0200
commitb5eab39ebcae061a46c186beac47f7e936ce57c2 (patch)
tree88fb47c789cc6a3c1596e568e29d9ec5ecb2209a
parent9c671606cc93a06e6db3ee5ee5f0862a7bfc21f9 (diff)
downloadpygobject-b5eab39ebcae061a46c186beac47f7e936ce57c2.tar.gz
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
-rw-r--r--gi/pygi-value.c31
-rw-r--r--tests/test_gobject.py18
-rw-r--r--tests/testhelpermodule.c38
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 },