[pybank] Implement incoming lists handling



commit 6f7df17e7f306d4ffe0c5cb86d39141ff6b33a13
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date:   Thu May 14 10:21:04 2009 +0200

    Implement incoming lists handling
---
 bank/bank-argument.c   |  158 ++++++++++++++++++++++++++++++------------------
 everything_unittest.py |   14 +++-
 2 files changed, 109 insertions(+), 63 deletions(-)

diff --git a/bank/bank-argument.c b/bank/bank-argument.c
index c2870d4..464be8c 100644
--- a/bank/bank-argument.c
+++ b/bank/bank-argument.c
@@ -21,7 +21,6 @@
 #include "bank.h"
 #include <pygobject.h>
 
-
 GArgument
 pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
 {
@@ -113,76 +112,81 @@ pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
     return arg;
 }
 
-PyObject *
-pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
+static PyObject *
+glist_to_pyobject(GITypeTag list_tag, GITypeInfo *type_info, GList *list, GSList *slist)
 {
-    GITypeTag type_tag;
-    PyObject *obj;
-    GIBaseInfo* interface_info;
-    GIInfoType interface_type;
-    
-    g_return_val_if_fail(type_info != NULL, NULL);
-    type_tag = g_type_info_get_tag(type_info);
-    if ( type_tag == GI_TYPE_TAG_INTERFACE ) {
-        interface_info = g_type_info_get_interface(type_info);
-        interface_type = g_base_info_get_type(interface_info);
+    PyObject *py_list;
+    int i;
+    GArgument arg;
+    PyObject *child_obj;
 
-        if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
-            // Create new struct based on arg->v_pointer
-            const gchar *module_name = g_base_info_get_namespace(interface_info);
-            const gchar *type_name = g_base_info_get_name(interface_info);
-            PyObject *module = PyImport_ImportModule(module_name);
-            PyObject *tp = PyObject_GetAttrString(module, type_name);
-            gsize size;
-            PyObject *buffer;
-            PyObject **dict;
+    if ((py_list = PyList_New(0)) == NULL) {
+        g_list_free(list);
+        return NULL;
+    }
+    i = 0;
+    if (list_tag == GI_TYPE_TAG_GLIST) {
+        for ( ; list != NULL; list = list->next) {
+            arg.v_pointer = list->data;
 
-            if (tp == NULL) {
-                char buf[256];
-                snprintf(buf, sizeof(buf), "Type %s.%s not defined", module_name, type_name);
-                PyErr_SetString(PyExc_TypeError, buf);
-                return NULL;
-            }
+            child_obj = pyg_argument_to_pyobject(&arg, type_info);
 
-            obj = PyObject_New(PyObject, (PyTypeObject *) tp);
-            if (obj == NULL)
+            if (child_obj == NULL) {
+                g_list_free(list);
+                Py_DECREF(py_list);
                 return NULL;
+            }
+            PyList_Append(py_list, child_obj);
+            Py_DECREF(child_obj);
 
-            // FIXME: Any better way to initialize the dict pointer?
-            dict = (PyObject **) ((char *)obj + ((PyTypeObject *) tp)->tp_dictoffset);
-            *dict = NULL;
+            ++i;
+        }
+    } else {
+        for ( ; slist != NULL; slist = slist->next) {
+            arg.v_pointer = slist->data;
 
-            size = g_struct_info_get_size ((GIStructInfo*)type_info);
-            buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
+            child_obj = pyg_argument_to_pyobject(&arg, type_info);
 
-            PyObject_SetAttrString(obj, "__buffer__", buffer);
+            if (child_obj == NULL) {
+                g_list_free(list);
+                Py_DECREF(py_list);
+                return NULL;
+            }
+            PyList_Append(py_list, child_obj);
+            Py_DECREF(child_obj);
 
-            Py_INCREF(obj);
-            return obj;
-        } else if (interface_type == GI_INFO_TYPE_ENUM) {
-            g_warning("pyg_argument_to_pyobject: enums not implemented");
-	    obj = Py_None;
-	    Py_INCREF(obj);
-	    return obj;
-	} else if ( arg->v_pointer == NULL ) {
-	    obj = Py_None;
-	    Py_INCREF(obj);
-	    return obj;
-	} else {
-	    GValue value;
-	    GObject* obj = arg->v_pointer;
-	    GType gtype = G_OBJECT_TYPE(obj);
-	    value.g_type = gtype;
-	    value.data[0].v_pointer = obj;
-	    return pyg_value_as_pyobject(&value, FALSE);
-	}
+            ++i;
+        }
     }
+    g_list_free(list);
+    return py_list;
+}
+
+PyObject *
+pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
+{
+    GITypeTag type_tag;
+    PyObject *obj;
+    GIBaseInfo* interface_info;
+    GIInfoType interface_type;
+    GITypeInfo *param_info;
+
+    g_return_val_if_fail(type_info != NULL, NULL);
+    type_tag = g_type_info_get_tag(type_info);
 
     switch (type_tag) {
     case GI_TYPE_TAG_VOID:
+        obj = Py_None;
+        break;
     case GI_TYPE_TAG_GLIST:
-	obj = Py_None;
-	break;
+    case GI_TYPE_TAG_GSLIST:
+        param_info = g_type_info_get_param_type(type_info, 0);
+        g_assert(param_info != NULL);
+        obj = glist_to_pyobject(type_tag,
+                                param_info,
+                                type_tag == GI_TYPE_TAG_GLIST ? arg->v_pointer : NULL,
+                                type_tag == GI_TYPE_TAG_GSLIST ? arg->v_pointer : NULL);
+        break;
     case GI_TYPE_TAG_BOOLEAN:
 	obj = PyBool_FromLong(arg->v_boolean);
 	break;
@@ -235,8 +239,44 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
             obj = PyString_FromString(arg->v_string);
 	break;
     case GI_TYPE_TAG_INTERFACE:
-	obj = PyCObject_FromVoidPtr(arg->v_pointer, NULL);
-	break;
+        interface_info = g_type_info_get_interface(type_info);
+        interface_type = g_base_info_get_type(interface_info);
+
+        if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
+            // Create new struct based on arg->v_pointer
+            const gchar *module_name = g_base_info_get_namespace(interface_info);
+            const gchar *type_name = g_base_info_get_name(interface_info);
+            PyObject *module = PyImport_ImportModule(module_name);
+            PyObject *tp = PyObject_GetAttrString(module, type_name);
+            gsize size;
+            PyObject *buffer;
+            PyObject **dict;
+
+            if (tp == NULL) {
+                char buf[256];
+                snprintf(buf, sizeof(buf), "Type %s.%s not defined", module_name, type_name);
+                PyErr_SetString(PyExc_TypeError, buf);
+                return NULL;
+            }
+
+            obj = PyObject_New(PyObject, (PyTypeObject *) tp);
+            if (obj == NULL)
+                return NULL;
+
+            // FIXME: Any better way to initialize the dict pointer?
+            dict = (PyObject **) ((char *)obj + ((PyTypeObject *) tp)->tp_dictoffset);
+            *dict = NULL;
+
+            size = g_struct_info_get_size ((GIStructInfo*)type_info);
+            buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
+
+            PyObject_SetAttrString(obj, "__buffer__", buffer);
+
+        } else if (interface_type == GI_INFO_TYPE_ENUM) {
+            g_warning("pyg_argument_to_pyobject: enums not implemented");
+            obj = Py_None;
+        }
+        break;
     case GI_TYPE_TAG_ARRAY:
 	obj = Py_None;
 	break;
diff --git a/everything_unittest.py b/everything_unittest.py
index d2bb68a..fd245f0 100644
--- a/everything_unittest.py
+++ b/everything_unittest.py
@@ -180,13 +180,19 @@ class TestGIEverything(unittest.TestCase):
         self.assertRaises(TypeError, Everything.test_strv_in(('1', 2, 3)))
         self.assertEquals((1, 2, 3), Everything.test_strv_out())
 
-    # TODO add more asserts
     def testGList(self):
-        self.assertTrue(isinstance(Everything.test_glist_nothing_return(), GLib.List))
+        retval = Everything.test_glist_nothing_return()
+        self.assertTrue(isinstance(retval, list))
+        self.assertEquals(retval[0], '1')
+        self.assertEquals(retval[1], '2')
+        self.assertEquals(retval[2], '3')
 
-    # TODO add more asserts
     def testGSList(self):
-        self.assertTrue(isinstance(Everything.test_gslist_nothing_return(), GLib.SList))
+        retval = Everything.test_gslist_nothing_return()
+        self.assertTrue(isinstance(retval, list))
+        self.assertEquals(retval[0], '1')
+        self.assertEquals(retval[1], '2')
+        self.assertEquals(retval[2], '3')
 
 # XXX Currently causes a segfault.
 #    def testClosure(self):



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