[pygobject/gsoc2009: 42/160] Refactore a few functions



commit 4582bf6f403583ef6f79840d0b86435fab049838
Author: Simon van der Linden <svdlinden src gnome org>
Date:   Thu Jul 16 11:15:46 2009 +0200

    Refactore a few functions

 gi/gimodule.c           |   29 +++
 gi/pygargument.c        |  561 +++++++++++++++++++++++------------------------
 gi/pygargument.h        |   14 +-
 gi/pygi-private.h       |   22 ++
 gi/pygiinfo.c           |  290 +++++++++++++------------
 gi/pygiinfo.h           |    1 +
 gi/pygirepository.c     |   15 --
 gi/pygirepository.h     |    2 -
 gobject/gobjectmodule.c |    3 +-
 gobject/pygobject.h     |    2 +
 10 files changed, 482 insertions(+), 457 deletions(-)
---
diff --git a/gi/gimodule.c b/gi/gimodule.c
index fe49d53..d73e70a 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -25,6 +25,35 @@
 
 #include <pygobject.h>
 
+PyObject *
+pygi_py_type_find_by_name(const char *namespace_, const char *name)
+{
+    PyObject *py_module;
+    gchar *module_name;
+
+    module_name = g_strconcat("gi.repository.", namespace_, NULL);
+
+    py_module = PyImport_ImportModule(module_name);
+
+    g_free(module_name);
+
+    if (name != NULL) {
+        PyObject *py_object;
+
+        if (py_module == NULL) {
+            return NULL;
+        }
+
+        py_object = PyObject_GetAttrString(py_module, name);
+
+        Py_DECREF(py_module);
+
+        return py_object;
+    }
+
+    return py_module;
+}
+
 static PyObject *
 _wrap_set_object_has_new_constructor(PyObject *self, PyObject *args)
 {
diff --git a/gi/pygargument.c b/gi/pygargument.c
index cd22d71..51f1e01 100644
--- a/gi/pygargument.c
+++ b/gi/pygargument.c
@@ -26,23 +26,155 @@
 #include <string.h>
 #include <pygobject.h>
 
+gint
+pygi_gi_registered_type_info_check_py_object(GIRegisteredTypeInfo *info,
+        PyObject *object, gboolean is_instance)
+{
+    gint retval;
+    PyObject *type;
+    gchar *type_name_expected;
+
+    type = pygi_py_type_find_by_gi_info((GIBaseInfo *)info);
+    if (type == NULL) {
+        return FALSE;
+    }
+    g_assert(PyType_Check(type));
+
+    if (is_instance) {
+        retval = PyObject_IsInstance(object, type);
+        if (!retval) {
+            type_name_expected = pygi_gi_base_info_get_fullname(
+                    (GIBaseInfo *)info);
+        }
+    } else {
+        if (!PyObject_Type(type)) {
+            type_name_expected = "type";
+            retval = 0;
+        } else if (!PyType_IsSubtype((PyTypeObject *)object,
+                (PyTypeObject *)type)) {
+            type_name_expected = pygi_gi_base_info_get_fullname(
+                    (GIBaseInfo *)info);
+            retval = 0;
+        } else {
+            retval = 1;
+        }
+    }
+
+    Py_DECREF(type);
+
+    if (!retval) {
+        PyTypeObject *object_type;
+
+        if (type_name_expected == NULL) {
+            return -1;
+        }
+
+        object_type = (PyTypeObject *)PyObject_Type(object);
+        if (object_type == NULL) {
+            return -1;
+        }
+
+        PyErr_Format(PyExc_TypeError, "Must be %s, not %s",
+            type_name_expected, object_type->tp_name);
+
+        g_free(type_name_expected);
+    }
+
+    return retval;
+}
 
-GQuark
-pyg_argument_from_pyobject_error_quark(void)
+void
+pygi_gi_type_tag_get_py_bounds(GITypeTag type_tag, PyObject **lower,
+        PyObject **upper)
 {
-  return g_quark_from_static_string ("pyg-argument-from-pyobject-quark");
+    switch(type_tag) {
+        case GI_TYPE_TAG_INT8:
+            *lower = PyInt_FromLong(-128);
+            *upper = PyInt_FromLong(127);
+            break;
+        case GI_TYPE_TAG_INT16:
+            *lower = PyInt_FromLong(-32768);
+            *upper = PyInt_FromLong(32767);
+            break;
+        case GI_TYPE_TAG_INT32:
+            *lower = PyInt_FromLong(-2147483648);
+            *upper = PyInt_FromLong(2147483647);
+            break;
+        case GI_TYPE_TAG_INT64:
+            /* Note: On 32-bit archs, these numbers don't fit in a long. */
+            *lower = PyLong_FromLongLong(-9223372036854775808u);
+            *upper = PyLong_FromLongLong(9223372036854775807);
+            break;
+        case GI_TYPE_TAG_SHORT:
+            *lower = PyInt_FromLong(G_MINSHORT);
+            *upper = PyInt_FromLong(G_MAXSHORT);
+            break;
+        case GI_TYPE_TAG_INT:
+            *lower = PyInt_FromLong(G_MININT);
+            *upper = PyInt_FromLong(G_MAXINT);
+            break;
+        case GI_TYPE_TAG_LONG:
+        case GI_TYPE_TAG_SSIZE:
+            *lower = PyInt_FromLong(G_MINLONG);
+            *upper = PyInt_FromLong(G_MAXLONG);
+            break;
+        case GI_TYPE_TAG_UINT8:
+            *upper = PyInt_FromLong(255);
+            *lower = PyInt_FromLong(0);
+            break;
+        case GI_TYPE_TAG_UINT16:
+            *upper = PyInt_FromLong(65535);
+            *lower = PyInt_FromLong(0);
+            break;
+        case GI_TYPE_TAG_UINT32:
+            /* Note: On 32-bit archs, this number doesn't fit in a long. */
+            *upper = PyLong_FromLongLong(4294967295);
+            *lower = PyInt_FromLong(0);
+            break;
+        case GI_TYPE_TAG_UINT64:
+            *upper = PyLong_FromUnsignedLongLong(18446744073709551615u);
+            *lower = PyInt_FromLong(0);
+            break;
+        case GI_TYPE_TAG_USHORT:
+            *upper = PyInt_FromLong(G_MAXUSHORT);
+            *lower = PyInt_FromLong(0);
+            break;
+        case GI_TYPE_TAG_UINT:
+            /* Note: On 32-bit archs, this number doesn't fit in a long. */
+            *upper = PyLong_FromLongLong(G_MAXUINT);
+            *lower = PyInt_FromLong(0);
+            break;
+        case GI_TYPE_TAG_ULONG:
+        case GI_TYPE_TAG_SIZE:
+            *upper = PyLong_FromUnsignedLongLong(G_MAXULONG);
+            *lower = PyInt_FromLong(0);
+            break;
+        case GI_TYPE_TAG_FLOAT:
+            *upper = PyFloat_FromDouble(G_MAXFLOAT);
+            *lower = PyFloat_FromDouble(-G_MAXFLOAT);
+            break;
+        case GI_TYPE_TAG_DOUBLE:
+            *upper = PyFloat_FromDouble(G_MAXDOUBLE);
+            *lower = PyFloat_FromDouble(-G_MAXDOUBLE);
+            break;
+        default:
+            PyErr_SetString(PyExc_TypeError, "Non-numeric type tag");
+            *lower = *upper = NULL;
+            return;
+    }
 }
 
-gboolean
-pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError **error)
+gint
+pygi_gi_type_info_check_py_object(GITypeInfo *type_info, PyObject *object)
 {
-    gboolean retval;
+    gint retval;
+
     GITypeTag type_tag;
-    const gchar *py_type_name_expected;
+    const gchar *type_name_expected;
 
     type_tag = g_type_info_get_tag(type_info);
 
-    retval = TRUE;
+    retval = 1;
 
     switch(type_tag) {
         case GI_TYPE_TAG_VOID:
@@ -54,217 +186,97 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
         case GI_TYPE_TAG_INT8:
         case GI_TYPE_TAG_INT16:
         case GI_TYPE_TAG_INT32:
-        case GI_TYPE_TAG_INT:
+        case GI_TYPE_TAG_INT64:
+        case GI_TYPE_TAG_UINT64:
         case GI_TYPE_TAG_SHORT:
-        {
-            long value;
-            gint value_max, value_min;
-
-            if (!(PyInt_Check(object) || PyLong_Check(object))) {
-                py_type_name_expected = "int or long";
-                goto check_error_type;
-            }
-
-            if (type_tag == GI_TYPE_TAG_INT8) {
-                value_min = -128;
-                value_max = 127;
-            } else if (type_tag == GI_TYPE_TAG_INT16) {
-                value_min = -32768;
-                value_max = 32767;
-            } else if (type_tag == GI_TYPE_TAG_INT32) {
-                value_min = -2147483648;
-                value_max = 2147483647;
-            } else if (type_tag == GI_TYPE_TAG_INT) {
-                value_min = G_MININT;
-                value_max = G_MAXINT;
-            } else if (type_tag == GI_TYPE_TAG_SHORT) {
-                value_min = G_MINSHORT;
-                value_max = G_MAXSHORT;
-            } else {
-                g_assert_not_reached();
-                value_max = 0;
-                value_min = 0;
-            }
-
-            value = PyInt_AsLong(object);
-            if (PyErr_Occurred() || value < value_min || value > value_max) {
-                PyErr_Clear();
-                g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-                        "Must range from %i to %i", value_min, value_max);
-                retval = FALSE;
-            }
-            break;
-        }
+        case GI_TYPE_TAG_INT:
+        case GI_TYPE_TAG_LONG:
+        case GI_TYPE_TAG_SSIZE:
         case GI_TYPE_TAG_UINT8:
         case GI_TYPE_TAG_UINT16:
         case GI_TYPE_TAG_UINT32:
-        case GI_TYPE_TAG_UINT:
         case GI_TYPE_TAG_USHORT:
-        {
-            guint value_max;
-
-            if (type_tag == GI_TYPE_TAG_UINT8) {
-                value_max = 255;
-            } else if (type_tag == GI_TYPE_TAG_UINT16) {
-                value_max = 65535;
-            } else if (type_tag == GI_TYPE_TAG_UINT32) {
-                value_max = 4294967295;
-            } else if (type_tag == GI_TYPE_TAG_UINT) {
-                value_max = G_MAXUINT;
-            } else if (type_tag == GI_TYPE_TAG_USHORT) {
-                value_max = G_MAXUSHORT;
-            } else {
-                g_assert_not_reached();
-                value_max = 0;
-            }
-
-            if (PyInt_Check(object)) {
-                long value = PyInt_AsLong(object);
-                if (PyErr_Occurred() || value < 0 || value > value_max) {
-                    PyErr_Clear();
-                    g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-                            "Must range from 0 to %u", value_max);
-                    retval = FALSE;
-                }
-            } else if (PyLong_Check(object)) {
-                unsigned long value = PyLong_AsUnsignedLong(object);
-                if (PyErr_Occurred() || value > value_max) {
-                    PyErr_Clear();
-                    g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-                            "Must range from 0 to %u", value_max);
-                    retval = FALSE;
-                }
-            } else {
-                py_type_name_expected = "int or long";
-                goto check_error_type;
-            }
-            break;
-        }
-        case GI_TYPE_TAG_INT64:
-        case GI_TYPE_TAG_LONG:
-        case GI_TYPE_TAG_SSIZE:
-            if (PyLong_Check(object)) {
-                gint64 value_min, value_max;
-
-                PyErr_Clear();
-                if (type_tag == GI_TYPE_TAG_INT64) {
-                    (void) PyLong_AsLongLong(object);
-                    value_min = -9223372036854775808u;
-                    value_max = 9223372036854775807;
-                } else {
-                    (void) PyLong_AsLong(object);
-
-                    /* Could be different from above on a 64 bit arch. */
-                    value_min = G_MINLONG;
-                    value_max = G_MAXLONG;
-                }
-                if (PyErr_Occurred()) {
-                    PyErr_Clear();
-                    g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-                            "Must range from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT, value_min, value_max);
-                    retval = FALSE;
-                }
-            } else if (!PyInt_Check(object)) {
-                /* Python Integer objects are implemented with longs, so no possible error if it is one. */
-                py_type_name_expected = "int or long";
-                goto check_error_type;
-            }
-            break;
-        case GI_TYPE_TAG_UINT64:
+        case GI_TYPE_TAG_UINT:
         case GI_TYPE_TAG_ULONG:
         case GI_TYPE_TAG_SIZE:
+        case GI_TYPE_TAG_FLOAT:
+        case GI_TYPE_TAG_DOUBLE:
         {
-            guint64 value_max;
+            PyObject *lower, *upper;
 
-            if (type_tag == GI_TYPE_TAG_INT64) {
-                value_max = 18446744073709551615u;
-            } else {
-                /* Could be different from above on a 64 bit arch. */
-                value_max = G_MAXULONG;
+            if (!PyNumber_Check(object)) {
+                type_name_expected = "int or long";
+                goto gi_type_info_check_py_object_check_type_error;
             }
 
-            if (PyLong_Check(object)) {
-                PyErr_Clear();
-                if (type_tag == GI_TYPE_TAG_UINT64) {
-                    (void) PyLong_AsUnsignedLongLong(object);
-                } else {
-                    (void) PyLong_AsUnsignedLong(object);
-                }
-                if (PyErr_Occurred()) {
-                    PyErr_Clear();
-                    g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-                            "Must range from 0 to %" G_GUINT64_FORMAT, value_max);
-                    retval = FALSE;
-                }
-            } else if (PyInt_Check(object)) {
-                long value;
-                value = PyInt_AsLong(object);
-                if (PyErr_Occurred() || value < 0) {
-                    PyErr_Clear();
-                    g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-                            "Must range from 0 to %" G_GUINT64_FORMAT, value_max);
-                    retval = FALSE;
-                }
-            } else {
-                py_type_name_expected = "int or long";
-                goto check_error_type;
+            pygi_gi_type_tag_get_py_bounds(type_tag, &lower, &upper);
+            if (lower == NULL || upper == NULL) {
+                retval = -1;
+                goto gi_type_info_check_py_object_check_number_clean;
             }
-            break;
-        }
-        case GI_TYPE_TAG_FLOAT:
-        case GI_TYPE_TAG_DOUBLE:
-        {
-            gdouble value;
 
-            if (!PyFloat_Check(object)) {
-                py_type_name_expected = "float";
-                goto check_error_type;
-            }
+            /* Check bounds */
+            if (PyObject_Compare(lower, object) > 0
+                || PyObject_Compare(upper, object) < 0) {
+                PyObject *lower_str, *upper_str;
 
-            value = PyFloat_AsDouble(object);
-            if (type_tag == GI_TYPE_TAG_FLOAT) {
-                if (PyErr_Occurred() || value < -G_MAXFLOAT || value > G_MAXFLOAT) {
-                    PyErr_Clear();
-                    g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-                            "Must range from %f to %f", -G_MAXFLOAT, G_MAXFLOAT);
-                    retval = FALSE;
-                }
-            } else if (type_tag == GI_TYPE_TAG_DOUBLE) {
                 if (PyErr_Occurred()) {
-                    PyErr_Clear();
-                    g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-                            "Must range from %f to %f", -G_MAXDOUBLE, G_MAXDOUBLE);
-                    retval = FALSE;
+                    retval = -1;
+                    goto gi_type_info_check_py_object_check_number_error_clean;
+                }
+
+                lower_str = PyObject_Str(lower);
+                upper_str = PyObject_Str(upper);
+                if (lower_str == NULL || upper_str == NULL) {
+                    retval = -1;
+                    goto gi_type_info_check_py_object_check_number_error_clean;
                 }
+
+                PyErr_Format(PyExc_ValueError, "Must range from %s to %s",
+                        PyString_AS_STRING(lower_str),
+                        PyString_AS_STRING(upper_str));
+
+                retval = 0;
+
+gi_type_info_check_py_object_check_number_error_clean:
+                Py_XDECREF(lower_str);
+                Py_XDECREF(upper_str);
             }
+
+gi_type_info_check_py_object_check_number_clean:
+            Py_XDECREF(lower);
+            Py_XDECREF(upper);
             break;
         }
         case GI_TYPE_TAG_UTF8:
             if (!PyString_Check(object)) {
-                py_type_name_expected = "string";
-                goto check_error_type;
+                type_name_expected = "string";
+                goto gi_type_info_check_py_object_check_type_error;
             }
             break;
         case GI_TYPE_TAG_ARRAY:
         {
-            gssize size;
             gssize required_size;
             Py_ssize_t object_size;
             GITypeInfo *item_type_info;
             gsize i;
 
             if (!PyTuple_Check(object)) {
-                py_type_name_expected = "tuple";
-                goto check_error_type;
+                type_name_expected = "tuple";
+                goto gi_type_info_check_py_object_check_type_error;
             }
 
-            size = g_type_info_get_array_fixed_size(type_info);
-            required_size = g_type_info_get_array_fixed_size(type_info);
             object_size = PyTuple_Size(object);
-            if (required_size != -1 && object_size != required_size) {
-                g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_SIZE,
-                        "Must contain %zd items, not %zd", required_size, object_size);
-                retval = FALSE;
+            if (object_size < 0) {
+                retval = -1;
+                break;
+            }
+
+            required_size = g_type_info_get_array_fixed_size(type_info);
+            if (required_size >= 0 && object_size != required_size) {
+                PyErr_Format(PyExc_ValueError, "Must contain %zd items, not %zd",
+                        required_size, object_size);
+                retval = 0;
                 break;
             }
 
@@ -274,12 +286,18 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
                 PyObject *item;
 
                 item = PyTuple_GetItem(object, i);
-                g_assert(item != NULL);
+                if (item == NULL) {
+                    retval = -1;
+                    break;
+                }
 
-                g_assert(error == NULL || *error == NULL);
-                if (!pyg_argument_from_pyobject_check(item, item_type_info, error)) {
-                    g_prefix_error(error, "Item %zu: ", i);
-                    retval = FALSE;
+                retval = pygi_gi_type_info_check_py_object(item_type_info, item);
+                if (retval < 0) {
+                    break;
+                }
+
+                if (!retval) {
+                    PyErr_PREFIX_FROM_FORMAT("Item %zu :", i);
                     break;
                 }
             }
@@ -290,75 +308,68 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
         }
         case GI_TYPE_TAG_INTERFACE:
         {
-            GIBaseInfo *interface_info;
-            GIInfoType interface_info_type;
+            GIBaseInfo *info;
+            GIInfoType info_type;
 
-            interface_info = g_type_info_get_interface(type_info);
-            interface_info_type = g_base_info_get_type(interface_info);
+            info = g_type_info_get_interface(type_info);
+            info_type = g_base_info_get_type(info);
 
-            switch (interface_info_type) {
+            switch (info_type) {
                 case GI_INFO_TYPE_ENUM:
                 {
                     (void) PyInt_AsLong(object);
                     if (PyErr_Occurred()) {
                         PyErr_Clear();
-                        py_type_name_expected = "int";
-                        goto check_error_type;
+                        type_name_expected = "int";
+                        goto gi_type_info_check_py_object_check_type_error;
                     }
                     /* XXX: What if the value doesn't correspond to any enum field? */
                     break;
                 }
                 case GI_INFO_TYPE_STRUCT:
-                case GI_INFO_TYPE_BOXED:
                 {
-                    GType gtype;
+                    GType type;
 
-                    gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
-
-                    if (g_type_is_a(gtype, G_TYPE_VALUE)) {
+                    /* Handle special cases. */
+                    type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info);
+                    if (g_type_is_a(type, G_TYPE_VALUE)) {
                         /* Nothing to check. */
                         break;
-                    } else if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
+                    } else if (g_type_is_a(type, G_TYPE_CLOSURE)) {
                         if (!PyCallable_Check(object)) {
-                            g_base_info_unref(interface_info);
-                            py_type_name_expected = "callable";
-                            goto check_error_type;
-                        }
-                    } else {
-                        GIBaseInfo *info;
-
-                        info = pyg_base_info_from_object(object);
-                        if (info == NULL || !g_base_info_equals(info, interface_info)) {
-                            py_type_name_expected = g_base_info_get_name(interface_info);
-                            if (info != NULL) {
-                                g_base_info_unref(info);
-                            }
-                            g_base_info_unref(interface_info);
-                            goto check_error_type;
+                            g_base_info_unref(info);
+                            type_name_expected = "callable";
+                            goto gi_type_info_check_py_object_check_type_error;
                         }
-
-                        g_base_info_unref(info);
+                        break;
                     }
-
-                    break;
                 }
+                case GI_INFO_TYPE_BOXED:
+                case GI_INFO_TYPE_OBJECT:
+                    retval = pygi_gi_registered_type_info_check_py_object((GIRegisteredTypeInfo *)info, object, TRUE);
+                    break;
                 default:
                     /* TODO: To complete with other types. */
                     g_assert_not_reached();
             }
 
-            g_base_info_unref(interface_info);
-
+            g_base_info_unref(info);
             break;
         }
         case GI_TYPE_TAG_GTYPE:
         {
-            GType gtype;
-            gtype = pyg_type_from_object(object);
-            if (gtype == 0) {
-                py_type_name_expected = "GType";
-                goto check_error_type;
+            gint is_instance;
+
+            is_instance = PyObject_IsInstance(object, (PyObject *)&PyGTypeWrapper_Type);
+            if (is_instance < 0) {
+                return -1;
+            }
+
+            if (!is_instance && (!PyType_Check(object) || pyg_type_from_object(object) == 0)) {
+                type_name_expected = "GType";
+                goto gi_type_info_check_py_object_check_type_error;
             }
+
             break;
         }
         case GI_TYPE_TAG_TIME_T:
@@ -372,21 +383,24 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
             g_assert_not_reached();
     }
 
-    g_assert(error == NULL || (retval == (*error == NULL)));
     return retval;
 
-check_error_type:
+gi_type_info_check_py_object_check_type_error:
     {
-        PyObject *py_type;
+        PyTypeObject *type;
 
-        py_type = PyObject_Type(object);
+        type = (PyTypeObject *)PyObject_Type(object);
+        if (type == NULL) {
+            return -1;
+        }
 
-        g_assert(py_type_name_expected != NULL);
+        g_assert(type_name_expected != NULL);
+        PyErr_Format(PyExc_TypeError, "Must be %s, not %s", 
+            type_name_expected, type->tp_name);
 
-        g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_TYPE,
-                "Must be %s, not %s", py_type_name_expected, ((PyTypeObject *)py_type)->tp_name);
-        Py_XDECREF(py_type);
-        return FALSE;
+        Py_DECREF((PyObject *)type);
+
+        return 0;
     }
 }
 
@@ -865,10 +879,7 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
             case GI_INFO_TYPE_STRUCT:
             {
                 GType gtype;
-                const gchar *module_name;
-                const gchar *type_name;
-                PyObject *module;
-                PyObject *type;
+                PyObject *py_type;
                 gsize size;
                 PyObject *buffer;
                 PyObject **dict;
@@ -882,70 +893,46 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
                     break;
                 }
 
-                /* Wrap the structure. */
-                module_name = g_base_info_get_namespace(interface_info);
-                type_name = g_base_info_get_name(interface_info);
-
-                module = pygi_repository_get_py_module(module_name);
-                if (module == NULL) {
-                    PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
+                /* Create a Python buffer. */
+                size = g_struct_info_get_size ((GIStructInfo *)interface_info);
+                buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
+                if (buffer == NULL) {
                     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;
-                }
+                /* Wrap the structure. */
+                py_type = pygi_py_type_find_by_gi_info((GIBaseInfo *)interface_info);
+                g_assert(py_type != NULL);
+
+                obj = PyObject_GC_New(PyObject, (PyTypeObject *)py_type);
+
+                Py_DECREF(py_type);
 
-                obj = PyObject_GC_New(PyObject, (PyTypeObject *)type);
                 if (obj == NULL) {
-                    Py_DECREF(type);
-                    Py_DECREF(module);
+                    Py_DECREF(buffer);
                     break;
                 }
 
                 /* FIXME: Any better way to initialize the dict pointer? */
-                dict = (PyObject **)((char *)obj + ((PyTypeObject *)type)->tp_dictoffset);
+                dict = (PyObject **)((char *)obj + ((PyTypeObject *)py_type)->tp_dictoffset);
                 *dict = NULL;
 
-                size = g_struct_info_get_size ((GIStructInfo *)interface_info);
-                buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
-                if (buffer == NULL) {
+                retval = PyObject_SetAttrString(obj, "__buffer__", buffer);
+                if (retval < 0) {
                     Py_DECREF(obj);
-                    Py_DECREF(type);
-                    Py_DECREF(module);
-                    break;
+                    obj = NULL;
                 }
 
-                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 = pygi_repository_get_py_module(module_name);
-                if (module == NULL) {
-                    PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
-                    break;
-                }
+                PyObject *py_type;
 
-                type = PyObject_GetAttrString(module, type_name);
-                if (type == NULL) {
-                    PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
-                    break;
-                }
+                /* Make sure the class is initialized. */
+                py_type = pygi_py_type_find_by_gi_info((GIBaseInfo *)interface_info);
+                g_assert(py_type != NULL);
+                Py_DECREF(py_type);
 
                 obj = pygobject_new(arg->v_pointer);
 
diff --git a/gi/pygargument.h b/gi/pygargument.h
index e4fae41..d55a606 100644
--- a/gi/pygargument.h
+++ b/gi/pygargument.h
@@ -28,6 +28,9 @@
 
 G_BEGIN_DECLS
 
+gint pygi_gi_type_info_check_py_object(GITypeInfo *type_info,
+                                       PyObject *object);
+
 GArgument pyg_argument_from_pyobject(PyObject *object,
 				     GITypeInfo *info);
 PyObject*  pyg_argument_to_pyobject(GArgument *arg,
@@ -36,17 +39,6 @@ PyObject*  pyg_argument_to_pyobject(GArgument *arg,
 PyObject* pyg_array_to_pyobject(gpointer items, gsize length, GITypeInfo *info);
 gpointer pyg_array_from_pyobject(PyObject *object, GITypeInfo *type_info, gsize *length);
 
-#define PyG_ARGUMENT_FROM_PYOBJECT_ERROR pyg_argument_from_pyobject_error_quark()
-GQuark pyg_argument_from_pyobject_error_quark(void);
-
-typedef enum {
-    PyG_ARGUMENT_FROM_PYOBJECT_ERROR_TYPE,
-    PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
-    PyG_ARGUMENT_FROM_PYOBJECT_ERROR_SIZE
-} PyGArgumentFromPyObjectError;
-
-gboolean pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError **error);
-
 G_END_DECLS
 
 #endif /* __PYG_ARGUMENT_H__ */
diff --git a/gi/pygi-private.h b/gi/pygi-private.h
index 652aab5..22bead0 100644
--- a/gi/pygi-private.h
+++ b/gi/pygi-private.h
@@ -39,4 +39,26 @@ extern PyTypeObject PyGIErrorDomainInfo_Type;
 #endif
 extern PyTypeObject PyGIUnresolvedInfo_Type;
 
+#define PyErr_PREFIX_FROM_FORMAT(format, ...) G_STMT_START { \
+	PyObject *py_error_prefix; \
+	py_error_prefix = PyString_FromFormat(format, ## __VA_ARGS__); \
+	if (py_error_prefix != NULL) { \
+		PyObject *py_error_type, *py_error_value, *py_error_traceback; \
+		PyErr_Fetch(&py_error_type, &py_error_value, &py_error_traceback); \
+		if (PyString_Check(py_error_value)) { \
+			PyString_ConcatAndDel(&py_error_prefix, py_error_value); \
+			if (py_error_prefix != NULL) { \
+				py_error_value = py_error_prefix; \
+			} \
+		} \
+		PyErr_Restore(py_error_type, py_error_value, py_error_traceback); \
+	} \
+} G_STMT_END
+
+PyObject * pygi_py_type_find_by_name(const char *namespace_,
+                                     const char *name);
+
+#define pygi_py_type_find_by_gi_info(info) \
+    pygi_py_type_find_by_name(g_base_info_get_namespace(info), g_base_info_get_name(info))
+
 #endif /* __PYGI_PRIVATE_H__ */
diff --git a/gi/pygiinfo.c b/gi/pygiinfo.c
index 9e12723..5878d89 100644
--- a/gi/pygiinfo.c
+++ b/gi/pygiinfo.c
@@ -202,6 +202,13 @@ _wrap_g_base_info_get_type(PyGIBaseInfo *self)
     return PyInt_FromLong(g_base_info_get_type(self->info));
 }
 
+static PyMethodDef _PyGIBaseInfo_methods[] = {
+    { "getName", (PyCFunction)_wrap_g_base_info_get_name, METH_NOARGS },
+    { "getType", (PyCFunction)_wrap_g_base_info_get_type, METH_NOARGS },
+    { "getNamespace", (PyCFunction)_wrap_g_base_info_get_namespace, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
 PyObject *
 pyg_info_new(void *info)
 {
@@ -275,13 +282,6 @@ pyg_info_new(void *info)
     return (PyObject*)self;
 }
 
-static PyMethodDef _PyGIBaseInfo_methods[] = {
-    { "getName", (PyCFunction)_wrap_g_base_info_get_name, METH_NOARGS },
-    { "getType", (PyCFunction)_wrap_g_base_info_get_type, METH_NOARGS },
-    { "getNamespace", (PyCFunction)_wrap_g_base_info_get_namespace, METH_NOARGS },
-    { NULL, NULL, 0 }
-};
-
 GIBaseInfo *
 pyg_base_info_from_object(PyObject *object)
 {
@@ -308,6 +308,30 @@ pyg_base_info_from_object(PyObject *object)
     return info;
 }
 
+gchar *
+pygi_gi_base_info_get_fullname(GIBaseInfo *info) {
+    GIBaseInfo *container_info;
+    gchar *fullname;
+
+    container_info = g_base_info_get_container(info);
+    if (container_info != NULL) {
+        fullname = g_strdup_printf("%s.%s.%s",
+                g_base_info_get_namespace(container_info),
+                g_base_info_get_name(container_info),
+                g_base_info_get_name(info));
+    } else {
+        fullname = g_strdup_printf("%s.%s",
+                g_base_info_get_namespace(info),
+                g_base_info_get_name(info));
+    }
+
+    if (fullname == NULL) {
+        PyErr_SetString(PyExc_MemoryError, "Out of memory");
+    }
+
+    return fullname;
+}
+
 /* CallableInfo */
 PYGIINFO_DEFINE_TYPE("CallableInfo", GICallableInfo, PyGIBaseInfo_Type);
 
@@ -468,9 +492,8 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
         /* Check the argument count. */
         if (n_py_args != n_in_args + (is_constructor ? 1 : 0) - n_aux_in_args) {
             g_base_info_unref((GIBaseInfo *)return_info);
-            PyErr_Format(PyExc_TypeError, "%s.%s() takes exactly %zd argument(s) (%zd given)",
-                    g_base_info_get_namespace((GIBaseInfo *)callable_info),
-                    g_base_info_get_name((GIBaseInfo *)callable_info),
+            PyErr_Format(PyExc_TypeError, "%s() takes exactly %zd argument(s) (%zd given)",
+                    pygi_gi_base_info_get_fullname(self->info),
                     n_in_args + (is_constructor ? 1 : 0) - n_aux_in_args, n_py_args);
             return NULL;
         }
@@ -485,13 +508,13 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
             g_assert(py_arg != NULL);
 
             if (!PyType_Check(py_arg)) {
-                PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be type, not %s",
-                    g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
-                    py_args_pos, ((PyTypeObject *)py_arg)->tp_name);
+                PyErr_Format(PyExc_TypeError, "%s() argument %zd: Must be type, not %s",
+                    pygi_gi_base_info_get_fullname(self->info), py_args_pos,
+                    ((PyTypeObject *)py_arg)->tp_name);
             } else if (!PyType_IsSubtype((PyTypeObject *)py_arg, &PyGObject_Type)) {
-                PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be a non-strict subclass of %s",
-                    g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
-                    py_args_pos, PyGObject_Type.tp_name);
+                PyErr_Format(PyExc_TypeError, "%s() argument %zd: Must be a non-strict subclass of %s",
+                    pygi_gi_base_info_get_fullname(self->info), py_args_pos,
+                    PyGObject_Type.tp_name);
             } else {
                 GIBaseInfo *interface_info;
                 GType interface_g_type;
@@ -503,9 +526,9 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
                 arg_g_type = pyg_type_from_object(py_arg);
 
                 if (!g_type_is_a(arg_g_type, interface_g_type)) {
-                    PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be a non-strict subclass of %s",
-                        g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
-                        py_args_pos, g_type_name(interface_g_type));
+                    PyErr_Format(PyExc_TypeError, "%s() argument %zd: Must be a non-strict subclass of %s",
+                        pygi_gi_base_info_get_fullname(self->info), py_args_pos,
+                        g_type_name(interface_g_type));
                 }
 
                 g_base_info_unref(interface_info);
@@ -547,9 +570,9 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
 
                     /* Note: If the first argument is not an instance, its type hasn't got a gtype. */
                     if (!g_type_is_a(arg_g_type, container_g_type)) {
-                        PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be %s, not %s",
-                            g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
-                            py_args_pos, g_base_info_get_name(container_info), ((PyTypeObject *)py_type)->tp_name);
+                        PyErr_Format(PyExc_TypeError, "%s() argument %zd: Must be %s, not %s",
+                            pygi_gi_base_info_get_fullname(self->info), py_args_pos,
+                            g_base_info_get_name(container_info), ((PyTypeObject *)py_type)->tp_name);
                     }
 
                     Py_DECREF(py_type);
@@ -568,9 +591,9 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
                         py_type = PyObject_Type(py_arg);
                         g_assert(py_type != NULL);
 
-                        PyErr_Format(PyExc_TypeError, "%s.%s() argument %zd: Must be %s, not %s",
-                            g_base_info_get_namespace(self->info), g_base_info_get_name(self->info),
-                            py_args_pos, g_base_info_get_name(container_info), ((PyTypeObject *)py_type)->tp_name);
+                        PyErr_Format(PyExc_TypeError, "%s() argument %zd: Must be %s, not %s",
+                            pygi_gi_base_info_get_fullname(self->info), py_args_pos,
+                            g_base_info_get_name(container_info), ((PyTypeObject *)py_type)->tp_name);
 
                         Py_DECREF(py_type);
                     }
@@ -601,7 +624,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
             GITypeInfo *type_info;
             GIDirection direction;
             PyObject *py_arg;
-            GError *error;
+            gint retval;
 
             if (aux_args[i] != NULL) {
                 /* No check needed for auxiliary arguments. */
@@ -620,39 +643,26 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
             py_arg = PyTuple_GetItem(args, py_args_pos);
             g_assert(py_arg != NULL);
 
-            error = NULL;
             type_info = g_arg_info_get_type(arg_info);
-            if (!pyg_argument_from_pyobject_check(py_arg, type_info, &error)) {
-                PyObject *py_error_type;
-                switch(error->code) {
-                    case PyG_ARGUMENT_FROM_PYOBJECT_ERROR_TYPE:
-                        py_error_type = PyExc_TypeError;
-                        break;
-                    case PyG_ARGUMENT_FROM_PYOBJECT_ERROR_SIZE:
-                    case PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE:
-                        py_error_type = PyExc_ValueError;
-                        break;
-                    default:
-                        g_assert_not_reached();
-                        py_error_type = NULL;
-                }
-
-                PyErr_Format(py_error_type, "%s.%s() argument %zd: %s",
-                        g_base_info_get_namespace((GIBaseInfo *)self->info),
-                        g_base_info_get_name((GIBaseInfo *)self->info),
-                        py_args_pos, error->message);
 
-                g_clear_error(&error);
-            }
+            retval = pygi_gi_type_info_check_py_object(type_info, py_arg);
 
             g_base_info_unref((GIBaseInfo *)type_info);
             g_base_info_unref((GIBaseInfo *)arg_info);
 
-            if (PyErr_Occurred()) {
+            if (retval < 0) {
                 g_base_info_unref((GIBaseInfo *)return_info);
                 return NULL;
             }
 
+            if (!retval) {
+                g_base_info_unref((GIBaseInfo *)return_info);
+                PyErr_PREFIX_FROM_FORMAT("%s() argument %zd: ",
+                        pygi_gi_base_info_get_fullname(self->info),
+                        py_args_pos);
+                return NULL;
+            }
+
             py_args_pos += 1;
         }
 
@@ -1439,67 +1449,69 @@ PYGIINFO_DEFINE_TYPE("FieldInfo", GIFieldInfo, PyGIBaseInfo_Type);
 static PyObject *
 _wrap_g_field_info_get_value(PyGIBaseInfo *self, PyObject *args)
 {
-    PyObject *obj;
-    gpointer buffer;
-    GArgument value;
-    GIBaseInfo *container;
-    GIInfoType container_type;
-    GIFieldInfo *field_info;
-    GITypeInfo *field_type_info;
     PyObject *retval;
+    GIBaseInfo *container_info;
+    GIInfoType container_info_type;
+    GITypeInfo *field_type_info;
+    GArgument value;
+    PyObject *object;
+    gpointer buffer;
 
     retval = NULL;
 
-    field_info = (GIFieldInfo *)self->info;
-
-    if (!PyArg_ParseTuple(args, "O:TypeInfo.getValue", &obj))
+    if (!PyArg_ParseTuple(args, "O:FieldInfo.getValue", &object)) {
         return NULL;
+    }
 
-    container = g_base_info_get_container((GIBaseInfo *)field_info);
-    container_type = g_base_info_get_type(container);
+    container_info = g_base_info_get_container(self->info);
+    container_info_type = g_base_info_get_type(container_info);
 
-    field_type_info = g_field_info_get_type(field_info);
+    field_type_info = g_field_info_get_type((GIFieldInfo *)self->info);
 
-    if (container_type == GI_INFO_TYPE_STRUCT || container_type == GI_INFO_TYPE_BOXED) {
+    if (container_info_type == GI_INFO_TYPE_STRUCT
+            || container_info_type == GI_INFO_TYPE_BOXED) {
         PyBufferProcs *py_buffer_procs;
         PyObject *py_buffer;
 
-        py_buffer = PyObject_GetAttrString(obj, "__buffer__");
+        py_buffer = PyObject_GetAttrString(object, "__buffer__");
         if (py_buffer == NULL) {
             goto field_info_get_value_return;
         }
 
+        /* We don't need to keep a reference. */
+        Py_DECREF(py_buffer);
+
         py_buffer_procs = py_buffer->ob_type->tp_as_buffer;
-        if (py_buffer_procs == NULL || py_buffer_procs->bf_getreadbuffer == 0) {
-            Py_DECREF(py_buffer);
+        if (py_buffer_procs == NULL || py_buffer_procs->bf_getreadbuffer == NULL) {
             PyErr_SetString(PyExc_RuntimeError, "Failed to get buffer for struct");
             goto field_info_get_value_return;
         }
 
         (*py_buffer_procs->bf_getreadbuffer)(py_buffer, 0, &buffer);
     } else {
-        buffer = ((PyGObject *) obj)->obj;
+        buffer = pygobject_get(object);
     }
 
     /* A few types are not handled by g_field_info_get_field, so do it here. */
-    if (!g_type_info_is_pointer(field_type_info) && g_type_info_get_tag(field_type_info) == GI_TYPE_TAG_INTERFACE) {
-        GIBaseInfo *interface_info;
+    if (!g_type_info_is_pointer(field_type_info)
+            && g_type_info_get_tag(field_type_info) == GI_TYPE_TAG_INTERFACE) {
+        GIBaseInfo *info;
 
-        if (!g_field_info_get_flags (field_info) & GI_FIELD_IS_READABLE) {
+        if (!(g_field_info_get_flags((GIFieldInfo *)self->info) & GI_FIELD_IS_READABLE)) {
             PyErr_SetString(PyExc_RuntimeError, "Field is not readable");
             goto field_info_get_value_return;
         }
 
-        interface_info = g_type_info_get_interface (field_type_info);
-        switch(g_base_info_get_type(interface_info))
+        info = g_type_info_get_interface (field_type_info);
+        switch(g_base_info_get_type(info))
         {
             case GI_INFO_TYPE_STRUCT:
             {
                 gsize offset;
                 gsize size;
 
-                offset = g_field_info_get_offset(field_info);
-                size = g_struct_info_get_size((GIStructInfo *)interface_info);
+                offset = g_field_info_get_offset((GIFieldInfo *)self->info);
+                size = g_struct_info_get_size((GIStructInfo *)info);
                 g_assert(size > 0);
 
                 value.v_pointer = g_try_malloc(size);
@@ -1508,29 +1520,34 @@ _wrap_g_field_info_get_value(PyGIBaseInfo *self, PyObject *args)
                     break;
                 }
                 g_memmove(value.v_pointer, buffer + offset, size);
-                break;
+
+                g_base_info_unref(info);
+                goto field_info_get_value_g_argument_to_py_object;
             }
             case GI_INFO_TYPE_UNION:
             case GI_INFO_TYPE_BOXED:
-                PyErr_SetString(PyExc_NotImplementedError, "Interface type not handled yet");
+                /* TODO */
+                g_assert_not_reached();
                 break;
             default:
-                if (!g_field_info_get_field(field_info, buffer, &value)) {
-                    PyErr_SetString(PyExc_RuntimeError, "Failed to get value for field");
-                }
+                /* Fallback. */
+                break;
         }
 
-        g_base_info_unref(interface_info);
+        g_base_info_unref(info);
 
         if (PyErr_Occurred()) {
             goto field_info_get_value_return;
         }
-    } else if (!g_field_info_get_field (field_info, buffer, &value)) {
+    }
+
+    if (!g_field_info_get_field((GIFieldInfo *)self->info, buffer, &value)) {
         PyErr_SetString(PyExc_RuntimeError, "Failed to get value for field");
         goto field_info_get_value_return;
     }
 
-    retval = pyg_argument_to_pyobject (&value, g_field_info_get_type (field_info));
+field_info_get_value_g_argument_to_py_object:
+    retval = pyg_argument_to_pyobject(&value, field_type_info);
 
 field_info_get_value_return:
     g_base_info_unref((GIBaseInfo *)field_type_info);
@@ -1542,123 +1559,114 @@ field_info_get_value_return:
 static PyObject *
 _wrap_g_field_info_set_value(PyGIBaseInfo *self, PyObject *args)
 {
-    PyObject *obj;
-    PyObject *value;
+    PyObject *object;
+    PyObject *py_value;
+    GArgument value;
     gpointer buffer;
-    GArgument arg;
-    GIFieldInfo *field_info;
-    GIBaseInfo *container;
-    GIInfoType container_type;
+    GIBaseInfo *container_info;
+    GIInfoType container_info_type;
     GITypeInfo *field_type_info;
     PyObject *retval;
-    GError *error;
+    gint check_retval;
 
-    retval = Py_None;
-
-    field_info = (GIFieldInfo *)self->info;
+    retval = NULL;
 
-    if (!PyArg_ParseTuple(args, "OO:TypeInfo.setValue", &obj, &value))
+    if (!PyArg_ParseTuple(args, "OO:FieldInfo.setValue", &object, &py_value)) {
         return NULL;
+    }
 
-    container = g_base_info_get_container((GIBaseInfo *) self->info);
-    container_type = g_base_info_get_type(container);
+    container_info = g_base_info_get_container(self->info);
+    container_info_type = g_base_info_get_type(container_info);
 
-    field_type_info = g_field_info_get_type(field_info);
+    field_type_info = g_field_info_get_type((GIFieldInfo *)self->info);
 
-    if (container_type == GI_INFO_TYPE_STRUCT || container_type == GI_INFO_TYPE_BOXED) {
+    if (container_info_type == GI_INFO_TYPE_STRUCT
+            || container_info_type == GI_INFO_TYPE_BOXED) {
         PyObject *py_buffer;
         PyBufferProcs *py_buffer_procs;
 
-        py_buffer = PyObject_GetAttrString(obj, "__buffer__");
+        py_buffer = PyObject_GetAttrString(object, "__buffer__");
         if (py_buffer == NULL) {
-            retval = NULL;
             goto field_info_set_value_return;
         }
 
+        /* We don't need to keep a reference. */
+        Py_DECREF(py_buffer);
+
         py_buffer_procs = py_buffer->ob_type->tp_as_buffer;
         if (py_buffer_procs == NULL || py_buffer_procs->bf_getreadbuffer == 0) {
-            Py_DECREF(py_buffer);
             PyErr_SetString(PyExc_RuntimeError, "Failed to get buffer for struct");
-            retval = NULL;
             goto field_info_set_value_return;
         }
 
         (*py_buffer_procs->bf_getreadbuffer)(py_buffer, 0, &buffer);
     } else {
-        buffer = ((PyGObject *) obj)->obj;
+        buffer = pygobject_get(object);
     }
 
     /* Check the value. */
-    error = NULL;
-    if (!pyg_argument_from_pyobject_check(value, field_type_info, &error)) {
-        PyObject *py_error_type;
-        switch(error->code) {
-            case PyG_ARGUMENT_FROM_PYOBJECT_ERROR_TYPE:
-                py_error_type = PyExc_TypeError;
-                break;
-            case PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE:
-                py_error_type = PyExc_ValueError;
-                break;
-            default:
-                g_assert_not_reached();
-                py_error_type = NULL;
-        }
+    check_retval = pygi_gi_type_info_check_py_object(field_type_info, py_value);
 
-        PyErr_Format(py_error_type, "%s.set_value() argument 1: %s",
-                g_base_info_get_namespace((GIBaseInfo *)self->info), error->message);
-
-        g_clear_error(&error);
+    if (check_retval < 0) {
+        goto field_info_set_value_return;
+    }
 
-        retval = NULL;
+    if (!check_retval) {
+        PyErr_PREFIX_FROM_FORMAT("%s.set_value() argument 1: ",
+                g_base_info_get_namespace(self->info));
         goto field_info_set_value_return;
     }
 
-    arg = pyg_argument_from_pyobject(value, field_type_info);
+    value = pyg_argument_from_pyobject(py_value, field_type_info);
 
     /* A few types are not handled by g_field_info_set_field, so do it here. */
-    if (!g_type_info_is_pointer(field_type_info) && g_type_info_get_tag(field_type_info) == GI_TYPE_TAG_INTERFACE) {
-        GIBaseInfo *interface_info;
+    if (!g_type_info_is_pointer(field_type_info)
+            && g_type_info_get_tag(field_type_info) == GI_TYPE_TAG_INTERFACE) {
+        GIBaseInfo *info;
 
-        if (!g_field_info_get_flags (field_info) & GI_FIELD_IS_WRITABLE) {
+        if (!(g_field_info_get_flags((GIFieldInfo *)self->info) & GI_FIELD_IS_WRITABLE)) {
             PyErr_SetString(PyExc_RuntimeError, "Field is not writable");
-            retval = NULL;
             goto field_info_set_value_return;
         }
 
-        interface_info = g_type_info_get_interface (field_type_info);
-        switch (g_base_info_get_type(interface_info))
+        info = g_type_info_get_interface(field_type_info);
+        switch (g_base_info_get_type(info))
         {
             case GI_INFO_TYPE_STRUCT:
             {
                 gsize offset;
                 gsize size;
 
-                offset = g_field_info_get_offset(field_info);
-                size = g_struct_info_get_size((GIStructInfo *)interface_info);
+                offset = g_field_info_get_offset((GIFieldInfo *)self->info);
+                size = g_struct_info_get_size((GIStructInfo *)info);
                 g_assert(size > 0);
 
-                g_memmove(buffer + offset, arg.v_pointer, size);
-                break;
+                g_memmove(buffer + offset, value.v_pointer, size);
+
+                retval = Py_None;
+                g_base_info_unref(info);
+                goto field_info_set_value_return;
             }
             case GI_INFO_TYPE_UNION:
             case GI_INFO_TYPE_BOXED:
-                PyErr_SetString(PyExc_NotImplementedError, "Interface type not handled yet");
-                retval = NULL;
+                /* TODO */
+                g_assert_not_reached();
                 break;
             default:
-                if (!g_field_info_set_field(field_info, buffer, &arg)) {
-                    PyErr_SetString(PyExc_RuntimeError, "Failed to set value for field");
-                    retval = NULL;
-                }
+                /* Fallback. */
+                break;
         }
 
-        g_base_info_unref(interface_info);
+        g_base_info_unref(info);
+    }
 
-    } else if (!g_field_info_set_field(field_info, buffer, &arg)) {
+    if (!g_field_info_set_field((GIFieldInfo *)self->info, buffer, &value)) {
         PyErr_SetString(PyExc_RuntimeError, "Failed to set value for field");
-        retval = NULL;
+        goto field_info_set_value_return;
     }
 
+    retval = Py_None;
+
 field_info_set_value_return:
     g_base_info_unref((GIBaseInfo *)field_type_info);
 
diff --git a/gi/pygiinfo.h b/gi/pygiinfo.h
index 18ba1fb..992a362 100644
--- a/gi/pygiinfo.h
+++ b/gi/pygiinfo.h
@@ -30,6 +30,7 @@ G_BEGIN_DECLS
 
 PyObject* pyg_info_new(gpointer info);
 
+gchar * pygi_gi_base_info_get_fullname(GIBaseInfo *info);
 GIBaseInfo* pyg_base_info_from_object(PyObject *object);
 
 void pygi_info_register_types(PyObject *m);
diff --git a/gi/pygirepository.c b/gi/pygirepository.c
index 879f7d0..ae1bf70 100644
--- a/gi/pygirepository.c
+++ b/gi/pygirepository.c
@@ -251,21 +251,6 @@ static PyMethodDef _PyGIRepository_methods[] = {
     { NULL, NULL, 0 }
 };
 
-PyObject *
-pygi_repository_get_py_module(const char * namespace_)
-{
-    PyObject *py_module;
-    gchar *module_name;
-
-    module_name = g_strconcat("gi.repository.", namespace_, NULL);
-
-    py_module = PyImport_ImportModule(module_name);
-
-    g_free(module_name);
-
-    return py_module;
-}
-
 void
 pygi_repository_register_types(PyObject *m)
 {
diff --git a/gi/pygirepository.h b/gi/pygirepository.h
index 6d519ad..573ecf3 100644
--- a/gi/pygirepository.h
+++ b/gi/pygirepository.h
@@ -26,8 +26,6 @@
 
 G_BEGIN_DECLS
 
-PyObject * pygi_repository_get_py_module(const char * namespace_);
-
 void pygi_repository_register_types(PyObject *m);
 
 G_END_DECLS
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index bef5bcf..f8f772f 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -2505,7 +2505,8 @@ struct _PyGObject_Functions pygobject_api_functions = {
 
   pyglib_option_group_new,
 
-  &PyGObject_Type
+  &PyGObject_Type,
+  &PyGTypeWrapper_Type
 };
 
 /* for addon libraries ... */
diff --git a/gobject/pygobject.h b/gobject/pygobject.h
index cf3ee53..b74e95b 100644
--- a/gobject/pygobject.h
+++ b/gobject/pygobject.h
@@ -200,6 +200,7 @@ struct _PyGObject_Functions {
     PyObject* (*option_group_new) (GOptionGroup *group);
 
     PyTypeObject *object_type;
+    PyTypeObject *type_wrapper_type;
 };
 
 #ifndef _INSIDE_PYGOBJECT_
@@ -267,6 +268,7 @@ struct _PyGObject_Functions *_PyGObject_API;
 #define pyg_gerror_exception_check (_PyGObject_API->gerror_exception_check)
 #define pyg_option_group_new       (_PyGObject_API->option_group_new)
 #define PyGObject_Type             (*_PyGObject_API->object_type)
+#define PyGTypeWrapper_Type        (*_PyGObject_API->type_wrapper_type)
 
 #define pyg_block_threads()   G_STMT_START {   \
     if (_PyGObject_API->block_threads != NULL) \



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