[pygobject] pyg_value_from_pyobject: support GArray
- From: Martin Pitt <martinpitt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] pyg_value_from_pyobject: support GArray
- Date: Fri, 4 Jan 2013 08:47:28 +0000 (UTC)
commit 23d1f14f553069740465c82eaa937b877c41e0cb
Author: Ray Strode <rstrode redhat com>
Date: Wed Dec 19 13:04:32 2012 -0500
pyg_value_from_pyobject: support GArray
This commit adds support for marshalling a python list (or other sequence)
returned from signal handlers to GArray, if necessary.
This parallels the implementation written to marshal to (the now deprecated)
GValueArray.
This fixes a crash in rhythmbox as seen downstream here:
https://bugzilla.redhat.com/show_bug.cgi?id=872851
https://bugzilla.gnome.org/show_bug.cgi?id=690514
Co-Authored-By: Martin Pitt <martinpitt gnome org>
gi/_gobject/pygtype.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++
tests/test_everything.py | 22 +++++++++++++++++
2 files changed, 82 insertions(+), 0 deletions(-)
---
diff --git a/gi/_gobject/pygtype.c b/gi/_gobject/pygtype.c
index 79c8387..921f75f 100644
--- a/gi/_gobject/pygtype.c
+++ b/gi/_gobject/pygtype.c
@@ -727,6 +727,63 @@ pyg_value_array_from_pyobject(GValue *value,
return 0;
}
+static int
+pyg_array_from_pyobject(GValue *value,
+ PyObject *obj)
+{
+ int len;
+ GArray *array;
+ int i;
+
+ len = PySequence_Length(obj);
+ if (len == -1) {
+ PyErr_Clear();
+ return -1;
+ }
+
+ array = g_array_new(FALSE, TRUE, sizeof(GValue));
+
+ for (i = 0; i < len; ++i) {
+ PyObject *item = PySequence_GetItem(obj, i);
+ GType type;
+ GValue item_value = { 0, };
+ int status;
+
+ if (! item) {
+ PyErr_Clear();
+ g_array_free(array, FALSE);
+ return -1;
+ }
+
+ if (item == Py_None)
+ type = G_TYPE_POINTER; /* store None as NULL */
+ else {
+ type = pyg_type_from_object((PyObject*)Py_TYPE(item));
+ if (! type) {
+ PyErr_Clear();
+ g_array_free(array, FALSE);
+ Py_DECREF(item);
+ return -1;
+ }
+ }
+
+ g_value_init(&item_value, type);
+ status = pyg_value_from_pyobject(&item_value, item);
+ Py_DECREF(item);
+
+ if (status == -1) {
+ g_array_free(array, FALSE);
+ g_value_unset(&item_value);
+ return -1;
+ }
+
+ g_array_append_val(array, item_value);
+ }
+
+ g_value_take_boxed(value, array);
+ return 0;
+}
+
/**
* pyg_value_from_pyobject:
* @value: the GValue object to store the converted value in.
@@ -959,6 +1016,9 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
else if (PySequence_Check(obj) &&
G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY))
return pyg_value_array_from_pyobject(value, obj, NULL);
+ else if (PySequence_Check(obj) &&
+ G_VALUE_HOLDS(value, G_TYPE_ARRAY))
+ return pyg_array_from_pyobject(value, obj);
else if (PYGLIB_PyUnicode_Check(obj) &&
G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
GString *string;
diff --git a/tests/test_everything.py b/tests/test_everything.py
index f1f14b7..4907a84 100644
--- a/tests/test_everything.py
+++ b/tests/test_everything.py
@@ -1195,6 +1195,28 @@ class TestSignals(unittest.TestCase):
obj.emit_sig_with_uint64()
self.assertEqual(obj.callback_i, GObject.G_MAXUINT64)
+ def test_intarray_ret(self):
+ obj = Everything.TestObj()
+
+ def callback(obj, i):
+ obj.callback_i = i
+ return [i, i + 1]
+
+ obj.callback_i = None
+
+ try:
+ obj.connect('sig-with-intarray-ret', callback)
+ except TypeError as e:
+ # compat with g-i 1.34.x
+ if 'unknown signal' in str(e):
+ return
+ raise
+
+ rv = obj.emit('sig-with-intarray-ret', 42)
+ self.assertEqual(obj.callback_i, 42)
+ self.assertEqual(type(rv), GLib.Array)
+ self.assertEqual(rv.len, 2)
+
@unittest.skipUnless(has_cairo, 'built without cairo support')
@unittest.skipUnless(Gtk, 'Gtk not available')
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]