[pygobject/gsoc2009: 17/160] Add type checking in FieldInfo.set_value



commit f825e71e6a1bcf9f0b31f6d44ae7e406941eee63
Author: Simon van der Linden <simon vanderlinden student uclouvain be>
Date:   Sat Jun 27 15:33:33 2009 +0200

    Add type checking in FieldInfo.set_value
    
    Add type checking in _wrap_g_field_info_set_value and structure type
    checking in pyg_argument_from_pyobject_check.
    
    Return a GType wrapper instead of an integer in
    _wrap_g_registered_type_info_get_g_type.
    
    Correct GType lookup for structures and boxed values in
    DynamicModule._create_boxed.

 girepository/bank-argument.c |   18 ++++++++++++++++--
 girepository/bank-info.c     |   35 +++++++++++++++++++++++++++++++++--
 girepository/module.py       |   13 +++++++++----
 3 files changed, 58 insertions(+), 8 deletions(-)
---
diff --git a/girepository/bank-argument.c b/girepository/bank-argument.c
index 75538c4..9f4d058 100644
--- a/girepository/bank-argument.c
+++ b/girepository/bank-argument.c
@@ -265,12 +265,22 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
                 (void) PyInt_AsLong(object);
                 if (PyErr_Occurred()) {
                     PyErr_Clear();
+                    g_base_info_unref(interface_info);
                     py_type_name_expected = "int";
                     goto check_error_type;
                 }
                 /* XXX: What if the value doesn't correspond to any enum field? */
-            } else {
-                /* TODO */
+            } else if (interface_info_type == GI_INFO_TYPE_STRUCT || interface_info_type == GI_INFO_TYPE_BOXED) {
+                GType gtype;
+                GType object_gtype;
+
+                gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
+                object_gtype = pyg_type_from_object(object);
+                if (object_gtype != gtype) {
+                    g_base_info_unref(interface_info);
+                    py_type_name_expected = g_type_name(gtype);
+                    goto check_error_type;
+                }
             }
 
             g_base_info_unref(interface_info);
@@ -304,7 +314,11 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
 check_error_type:
     {
         PyObject *py_type;
+
         py_type = PyObject_Type(object);
+
+        g_assert(py_type_name_expected != NULL);
+
         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);
diff --git a/girepository/bank-info.c b/girepository/bank-info.c
index ca09f52..652b1f8 100644
--- a/girepository/bank-info.c
+++ b/girepository/bank-info.c
@@ -602,17 +602,22 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
                     /* FIXME: We should reuse this. Perhaps by separating the
                      * wrapper creation from the binding to the wrapper.
                      */
+                    GIStructInfo *struct_info;
                     gsize size;
                     PyObject *buffer;
                     int retval;
 
-                    size = g_struct_info_get_size ((GIStructInfo *)return_info);
+                    struct_info = g_interface_info_get_iface_struct((GIInterfaceInfo *)interface_info);
+
+                    size = g_struct_info_get_size (struct_info);
                     g_assert(size > 0);
 
                     buffer = PyBuffer_FromReadWriteMemory(return_arg.v_pointer, size);
 
                     retval = PyObject_SetAttrString(return_value, "__buffer__", buffer);
                     g_assert(retval != -1);
+
+                    g_base_info_unref((GIBaseInfo *)struct_info);
                 } else {
                     PyGObject *gobject;
 
@@ -798,7 +803,7 @@ _wrap_g_registered_type_info_get_g_type (PyGIBaseInfo* self)
     int gtype;
 
     gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo*)self->info);
-    return PyInt_FromLong(gtype);
+    return pyg_type_wrapper_new(gtype);
 }
 
 static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = {
@@ -1272,6 +1277,7 @@ _wrap_g_field_info_set_value(PyGIBaseInfo *self, PyObject *args)
     GIInfoType container_type;
     GITypeInfo *field_type_info;
     PyObject *retval;
+    GError *error;
 
     retval = Py_None;
 
@@ -1308,6 +1314,31 @@ _wrap_g_field_info_set_value(PyGIBaseInfo *self, PyObject *args)
         buffer = ((PyGObject *) obj)->obj;
     }
 
+    /* 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;
+        }
+
+        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);
+
+        retval = NULL;
+        goto field_info_set_value_return;
+    }
+
     arg = pyg_argument_from_pyobject(value, field_type_info);
 
     /* A few types are not handled by g_field_info_set_field, so do it here. */
diff --git a/girepository/module.py b/girepository/module.py
index d05c9c0..6b6b875 100644
--- a/girepository/module.py
+++ b/girepository/module.py
@@ -194,7 +194,7 @@ class DynamicModule(object):
 
         namespace = repository.get_c_prefix(boxed_info.getNamespace())
         full_name = namespace + name
-        boxed_info.getGType()
+
         gtype = None
         try:
             gtype = gobject.GType.from_name(full_name)
@@ -203,6 +203,7 @@ class DynamicModule(object):
         else:
             if gtype.pytype is not None:
                 return gtype.pytype
+
         # Check if the klass is already created, eg
         # present in our namespace, this is necessary since we're
         # not always entering here through the __getattr__ hook.
@@ -215,9 +216,13 @@ class DynamicModule(object):
             bases += gobject.Boxed
 
         klass = buildType(boxed_info, bases)
-        if gtype is not None:
-            klass.__gtype__ = gtype
-            gtype.pytype = klass
+
+        if gtype is None:
+            gtype = boxed_info.getGType()
+
+        klass.__gtype__ = gtype
+        gtype.pytype = klass
+
         self.__dict__[name] = klass
 
         return klass



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