[pygobject/gsoc2009: 27/160] Add generic value support as function argument



commit c4fcac17067da1d42f2c71753304040c62a6abb1
Author: Simon van der Linden <simon vanderlinden student uclouvain be>
Date:   Mon Jul 6 11:47:04 2009 +0200

    Add generic value support as function argument

 girepository/bank-argument.c |  191 ++++++++++++++++++++++++++++--------------
 tests/test_girepository.py   |   22 +----
 2 files changed, 132 insertions(+), 81 deletions(-)
---
diff --git a/girepository/bank-argument.c b/girepository/bank-argument.c
index 95df956..2e2a926 100644
--- a/girepository/bank-argument.c
+++ b/girepository/bank-argument.c
@@ -303,7 +303,10 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
 
                     gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
 
-                    if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
+                    if (g_type_is_a(gtype, G_TYPE_VALUE)) {
+                        /* Nothing to check. */
+                        break;
+                    } else if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
                         if (!PyCallable_Check(object)) {
                             g_base_info_unref(interface_info);
                             py_type_name_expected = "callable";
@@ -463,7 +466,24 @@ pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
 
                 gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
 
-                if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
+                if (g_type_is_a(gtype, G_TYPE_VALUE)) {
+                    GValue *value;
+                    int retval;
+                    PyObject *py_type;
+
+                    value = g_slice_new0(GValue);
+
+                    py_type = PyObject_Type(object);
+                    g_assert(py_type != NULL);
+
+                    g_value_init(value, pyg_type_from_object(py_type));
+
+                    retval = pyg_value_from_pyobject(value, object);
+                    g_assert(retval == 0);
+
+                    arg.v_pointer = value;
+                    break;
+                } else if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
                     arg.v_pointer = pyg_closure_new(object, NULL, NULL);
                     break;
                 }
@@ -722,13 +742,13 @@ 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);
 
+    obj = NULL;
+
     switch (type_tag) {
     case GI_TYPE_TAG_VOID:
         // TODO: Should we take this as a buffer?
@@ -803,71 +823,119 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
             obj = PyString_FromString(arg->v_string);
         break;
     case GI_TYPE_TAG_INTERFACE:
+    {
+        GIBaseInfo* interface_info;
+        GIInfoType interface_info_type;
+
         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;
-            }
+        interface_info_type = g_base_info_get_type(interface_info);
 
-            obj = PyObject_GC_New(PyObject, (PyTypeObject *) tp);
-            if (obj == NULL)
-                return NULL;
+        if (arg->v_pointer == NULL) {
+            obj = Py_None;
+        }
 
-            // FIXME: Any better way to initialize the dict pointer?
-            dict = (PyObject **) ((char *)obj + ((PyTypeObject *) tp)->tp_dictoffset);
-            *dict = NULL;
+        switch (interface_info_type) {
+            case GI_INFO_TYPE_ENUM:
+               obj = PyInt_FromLong(arg->v_int);
+                break;
+            case GI_INFO_TYPE_STRUCT:
+            {
+                GType gtype;
+                const gchar *module_name;
+                const gchar *type_name;
+                PyObject *module;
+                PyObject *type;
+                gsize size;
+                PyObject *buffer;
+                PyObject **dict;
+                int retval;
 
-            size = g_struct_info_get_size ((GIStructInfo*)interface_info);
-            buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
-            if (buffer == NULL)
-                return NULL;
+                gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
 
-            PyObject_SetAttrString(obj, "__buffer__", buffer);
+                if (g_type_is_a(gtype, G_TYPE_VALUE)) {
+                    obj = pyg_value_as_pyobject(arg->v_pointer, FALSE);
+                    g_value_unset(arg->v_pointer);
+                    break;
+                }
 
-        } else if (interface_type == GI_INFO_TYPE_ENUM) {
-	    obj = PyInt_FromLong(arg->v_int);
-        } else if ( arg->v_pointer == NULL ) {
-            obj = Py_None;
-        } else {
-            GValue value;
-            GObject* gobj = arg->v_pointer;
-            GType gtype = G_OBJECT_TYPE(gobj);
-            GIRepository *repo = g_irepository_get_default();
-            GIBaseInfo *object_info = g_irepository_find_by_gtype(repo, gtype);
-            const gchar *module_name;
-            const gchar *type_name;
-
-            if (object_info != NULL) {
-                // It's a pybank class, we should make sure it is initialized.
-
-                module_name = g_base_info_get_namespace(object_info);
-                type_name = g_base_info_get_name(object_info);
-
-                // This will make sure the wrapper class is registered.
-                char buf[250];
-                snprintf(buf, sizeof(buf), "%s.%s", module_name, type_name);
-                PyRun_SimpleString(buf);
+                /* Wrap the structure. */
+                module_name = g_base_info_get_namespace(interface_info);
+                type_name = g_base_info_get_name(interface_info);
+
+                module = PyImport_ImportModule(module_name);
+                if (module == NULL) {
+                    PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
+                    break;
+                }
+
+                type = PyObject_GetAttrString(module, type_name);
+                if (type == NULL) {
+                    PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
+                    Py_DECREF(module);
+                    break;
+                }
+
+                obj = PyObject_GC_New(PyObject, (PyTypeObject *)type);
+                if (obj == NULL) {
+                    Py_DECREF(type);
+                    Py_DECREF(module);
+                    break;
+                }
+
+                /* FIXME: Any better way to initialize the dict pointer? */
+                dict = (PyObject **)((char *)obj + ((PyTypeObject *)type)->tp_dictoffset);
+                *dict = NULL;
+
+                size = g_struct_info_get_size ((GIStructInfo *)interface_info);
+                buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
+                if (buffer == NULL) {
+                    Py_DECREF(obj);
+                    Py_DECREF(type);
+                    Py_DECREF(module);
+                    break;
+                }
+
+                retval = PyObject_SetAttrString(obj, "__buffer__", buffer);
+                g_assert(retval == 0);
+
+                break;
             }
+            case GI_INFO_TYPE_OBJECT:
+            {
+                const gchar *module_name;
+                const gchar *type_name;
+                PyObject *type;
+                PyObject *module;
+
+                /* Make sure the class is initialized */
+                module_name = g_base_info_get_namespace(interface_info);
+                type_name = g_base_info_get_name(interface_info);
+
+                module = PyImport_ImportModule(module_name);
+                if (module == NULL) {
+                    PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
+                    break;
+                }
 
-            value.g_type = gtype;
-            value.data[0].v_pointer = gobj;
-            obj = pyg_value_as_pyobject(&value, FALSE);
+                type = PyObject_GetAttrString(module, type_name);
+                if (type == NULL) {
+                    PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
+                    break;
+                }
+
+                obj = pygobject_new(arg->v_pointer);
+
+                break;
+            }
+            default:
+                /* TODO: To complete with other types. */
+                g_assert_not_reached();
         }
+
+        g_base_info_unref((GIBaseInfo *)interface_info);
+
         break;
+    }
     case GI_TYPE_TAG_ARRAY:
         g_warning("pyg_argument_to_pyobject: use pyarray_to_pyobject instead for arrays");
         obj = Py_None;
@@ -886,10 +954,7 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
         break;
     }
 
-    if (obj != NULL)
-        Py_INCREF(obj);
-
+    Py_XINCREF(obj);
     return obj;
 }
 
-
diff --git a/tests/test_girepository.py b/tests/test_girepository.py
index c21d719..f9eb81f 100644
--- a/tests/test_girepository.py
+++ b/tests/test_girepository.py
@@ -371,25 +371,11 @@ class TestGIEverything(unittest.TestCase):
     def testClosureOneArg(self):
         self.assertEquals(3, Everything.test_closure_one_arg(lambda x: x, 3))
 
-#    def testIntValueArg(self):
-#        i = Everything.test_int_value_arg(42)
-#        self.assertEquals(42, i)
+    def testIntValueArg(self):
+        self.assertEquals(42, Everything.test_int_value_arg(42))
 
-# FIXME
-# ======================================================================
-# ERROR: testValueReturn (__main__.TestGIEverything)
-# ----------------------------------------------------------------------
-# Traceback (most recent call last):
-#   File "test_girepository.py", line 219, in testValueReturn
-#     self.assertEquals(42, i)
-#   File "/opt/gnome-introspection/lib64/python2.5/unittest.py", line 332, in failUnlessEqual
-#     if not first == second:
-#   File "/opt/gnome-introspection/lib64/python2.5/site-packages/gtk-2.0/girepository/btypes.py", line 297, in __eq__
-#     if getattr(self, field.getName()) != getattr(other, field.getName()):
-# AttributeError: 'int' object has no attribute 'g_type'
-# 	def testValueReturn(self):
-#        i = Everything.test_value_return(42)
-#        self.assertEquals(42, i)
+    def testValueReturn(self):
+        self.assertEquals(42, Everything.test_value_return(42))
 
     def testEnum(self):
         self.assertEqual('value1', Everything.test_enum_param(Everything.TestEnum.VALUE1))



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