[pygobject/gsoc2009: 45/160] Refactore pygi_g_argument_from_py_object



commit 23f11a80329b0d7fc4a4df3c2678a91151628763
Author: Simon van der Linden <svdlinden src gnome org>
Date:   Mon Jul 20 17:58:49 2009 +0200

    Refactore pygi_g_argument_from_py_object

 gi/pygargument.c |  307 ++++++++++++++++++++++++++++++------------------------
 gi/pygargument.h |    5 +-
 gi/pygiinfo.c    |   14 ++-
 3 files changed, 186 insertions(+), 140 deletions(-)
---
diff --git a/gi/pygargument.c b/gi/pygargument.c
index aab413a..bd27313 100644
--- a/gi/pygargument.c
+++ b/gi/pygargument.c
@@ -393,160 +393,197 @@ check_number_clean:
 }
 
 GArgument
-pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
+pygi_g_argument_from_py_object(PyObject *object, GITypeInfo *type_info)
 {
     GArgument arg;
-    GITypeTag type_tag;
 
-    type_tag = g_type_info_get_tag((GITypeInfo*)type_info);
-    switch (type_tag) {
-    case GI_TYPE_TAG_VOID:
-        /* Nothing to do */
-        break;
-    case GI_TYPE_TAG_UTF8:
-        if (object == Py_None)
-            arg.v_pointer = NULL;
-        else
-            arg.v_pointer = g_strdup(PyString_AsString(object));
-        break;
-    case GI_TYPE_TAG_USHORT:
-        arg.v_ushort = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_UINT8:
-        arg.v_uint8 = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_UINT:
-        arg.v_uint = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_UINT16:
-        arg.v_uint16 = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_UINT32:
-        arg.v_uint32 = PyLong_AsLongLong(object);
-        break;
-    case GI_TYPE_TAG_UINT64:
-        if (PyInt_Check(object)) {
-            PyObject *long_obj = PyNumber_Long(object);
-            arg.v_uint64 = PyLong_AsUnsignedLongLong(long_obj);
-            Py_DECREF(long_obj);
-        } else
-            arg.v_uint64 = PyLong_AsUnsignedLongLong(object);
-        break;
-    case GI_TYPE_TAG_SHORT:
-        arg.v_short = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_INT8:
-        arg.v_int8 = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_INT:
-        arg.v_int = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_SSIZE:
-    case GI_TYPE_TAG_LONG:
-        arg.v_long = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_SIZE:
-    case GI_TYPE_TAG_ULONG:
-        arg.v_ulong = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_BOOLEAN:
-        arg.v_boolean = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_INT16:
-        arg.v_int16 = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_INT32:
-        arg.v_int32 = PyInt_AsLong(object);
-        break;
-    case GI_TYPE_TAG_INT64:
-        arg.v_int64 = PyLong_AsLongLong(object);
-        break;
-    case GI_TYPE_TAG_FLOAT:
-        arg.v_float = (float)PyFloat_AsDouble(object);
-        break;
-    case GI_TYPE_TAG_DOUBLE:
-        arg.v_double = PyFloat_AsDouble(object);
-        break;
-    case GI_TYPE_TAG_INTERFACE:
+    switch (g_type_info_get_tag(type_info))
     {
-        GIBaseInfo* interface_info;
-        GIInfoType interface_info_type;
+        case GI_TYPE_TAG_VOID:
+            /* Nothing to do */
+            break;
+        case GI_TYPE_TAG_BOOLEAN:
+            arg.v_boolean = PyObject_IsTrue(object);
+            break;
+        case GI_TYPE_TAG_SHORT:
+        case GI_TYPE_TAG_USHORT:
+        case GI_TYPE_TAG_INT8:
+        case GI_TYPE_TAG_UINT8:
+        case GI_TYPE_TAG_INT16:
+        case GI_TYPE_TAG_UINT16:
+        case GI_TYPE_TAG_INT32:
+        case GI_TYPE_TAG_INT:
+        case GI_TYPE_TAG_SSIZE:
+        case GI_TYPE_TAG_LONG:
+        {
+            PyObject *int_;
+            int_ = PyNumber_Int(object);
+            if (int_ == NULL) {
+                break;
+            }
+            arg.v_long = PyInt_AsLong(int_);
+            Py_DECREF(int_);
+            break;
+        }
+        case GI_TYPE_TAG_UINT32:
+        case GI_TYPE_TAG_UINT64:
+        case GI_TYPE_TAG_UINT:
+        case GI_TYPE_TAG_SIZE:
+        case GI_TYPE_TAG_ULONG:
+        {
+            PyObject *long_;
+            long_ = PyNumber_Long(object);
+            if (long_ == NULL) {
+                break;
+            }
+            arg.v_uint64 = PyLong_AsUnsignedLongLong(long_);
+            Py_DECREF(long_);
+            break;
+        }
+        case GI_TYPE_TAG_INT64:
+        {
+            PyObject *long_;
+            long_ = PyNumber_Long(object);
+            if (long_ == NULL) {
+                break;
+            }
+            arg.v_int64 = PyLong_AsLongLong(long_);
+            Py_DECREF(long_);
+            break;
+        }
+        case GI_TYPE_TAG_FLOAT:
+        {
+            PyObject *float_;
+            float_ = PyNumber_Float(object);
+            if (float_ == NULL) {
+                break;
+            }
+            arg.v_float = (float)PyFloat_AsDouble(float_);
+            Py_DECREF(float_);
+            break;
+        }
+        case GI_TYPE_TAG_DOUBLE:
+        {
+            PyObject *float_;
+            float_ = PyNumber_Float(object);
+            if (float_ == NULL) {
+                break;
+            }
+            arg.v_double = PyFloat_AsDouble(float_);
+            Py_DECREF(float_);
+            break;
+        }
+        case GI_TYPE_TAG_UTF8:
+            arg.v_string = g_strdup(PyString_AsString(object));
+            break;
+        case GI_TYPE_TAG_INTERFACE:
+        {
+            GIBaseInfo *info;
 
-        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);
 
-        switch (interface_info_type) {
-            case GI_INFO_TYPE_ENUM:
-                arg.v_int = PyInt_AsLong(object);
-                break;
-            case GI_INFO_TYPE_STRUCT:
-            {
-                GType gtype;
-                PyObject *py_buffer;
+            switch (g_base_info_get_type(info)) {
+                case GI_INFO_TYPE_ENUM:
+                {
+                    PyObject *int_;
+                    int_ = PyNumber_Int(object);
+                    if (int_ == NULL) {
+                        break;
+                    }
+                    arg.v_long = PyInt_AsLong(int_);
+                    Py_DECREF(int_);
+                    break;
+                }
+                case GI_INFO_TYPE_STRUCT:
+                {
+                    GType type;
+                    gsize size;
+                    gpointer buffer;
 
-                gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
+                    type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info);
 
-                if (g_type_is_a(gtype, G_TYPE_VALUE)) {
-                    GValue *value;
-                    int retval;
-                    PyObject *py_type;
+                    /* Handle special cases first. */
+                    if (g_type_is_a(type, G_TYPE_VALUE)) {
+                        GValue *value;
+                        GType object_type;
+                        gint retval;
+
+                        object_type = pyg_type_from_object(object->ob_type);
+                        if (object_type == G_TYPE_INVALID) {
+                            PyErr_SetString(PyExc_RuntimeError, "Unable to retrieve object's GType");
+                            break;
+                        }
 
-                    value = g_slice_new0(GValue);
+                        value = g_slice_new0(GValue);
+                        g_value_init(value, object_type);
 
-                    py_type = PyObject_Type(object);
-                    g_assert(py_type != NULL);
+                        retval = pyg_value_from_pyobject(value, object);
+                        if (retval < 0) {
+                            g_slice_free(GValue, value);
+                            PyErr_SetString(PyExc_RuntimeError, "PyObject conversion to GValue failed");
+                            break;
+                        }
 
-                    g_value_init(value, pyg_type_from_object(py_type));
+                        arg.v_pointer = value;
+                        break;
+                    } else if (g_type_is_a(type, G_TYPE_CLOSURE)) {
+                        GClosure *closure;
 
-                    retval = pyg_value_from_pyobject(value, object);
-                    g_assert(retval == 0);
+                        closure = pyg_closure_new(object, NULL, NULL);
+                        if (closure == NULL) {
+                            PyErr_SetString(PyExc_RuntimeError, "GClosure creation failed");
+                            break;
+                        }
 
-                    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;
-                }
+                        arg.v_pointer = closure;
+                        break;
+                    }
 
-                py_buffer = PyObject_GetAttrString(object, "__buffer__");
-                g_assert(py_buffer != NULL);
-                (*py_buffer->ob_type->tp_as_buffer->bf_getreadbuffer)(py_buffer, 0, &arg.v_pointer);
+                    buffer = pygi_py_object_get_buffer(object, &size);
 
-                break;
-            }
-            case GI_INFO_TYPE_OBJECT:
-                if (object == Py_None) {
-                    arg.v_pointer = NULL;
+                    arg.v_pointer = buffer;
                     break;
                 }
-                arg.v_pointer = pygobject_get(object);
-                break;
-            default:
-                /* TODO: To complete with other types. */
-                g_assert_not_reached();
+                case GI_INFO_TYPE_OBJECT:
+                    arg.v_pointer = pygobject_get(object);
+                    break;
+                default:
+                    /* TODO */
+                    g_assert_not_reached();
+            }
+            g_base_info_unref(info);
+            break;
         }
-        g_base_info_unref((GIBaseInfo *)interface_info);
-        break;
-    }
-    case GI_TYPE_TAG_ARRAY:
-    {
-        gsize length;
-        arg.v_pointer = pyg_array_from_pyobject(object, type_info, &length);
-        break;
-    }
-    case GI_TYPE_TAG_ERROR:
-        /* Allow NULL GError, otherwise fall through */
-        if (object == Py_None) {
-            arg.v_pointer = NULL;
+        case GI_TYPE_TAG_ARRAY:
+        {
+            gsize length;
+            arg.v_pointer = pyg_array_from_pyobject(object, type_info, &length);
             break;
         }
-    case GI_TYPE_TAG_GTYPE:
-        arg.v_int = pyg_type_from_object(object);
-        break;
-    default:
-        g_print("<PyO->GArg> GITypeTag %s is unhandled\n",
-                g_type_tag_to_string(type_tag));
-        break;
+        case GI_TYPE_TAG_ERROR:
+            /* Allow NULL GError, otherwise fall through */
+            if (object == Py_None) {
+                arg.v_pointer = NULL;
+                break;
+            }
+            /* TODO */
+            g_assert_not_reached();
+            break;
+        case GI_TYPE_TAG_GTYPE:
+        {
+            GType type;
+
+            type = pyg_type_from_object(object);
+            if (type == G_TYPE_INVALID) {
+                PyErr_SetString(PyExc_RuntimeError, "GType conversion failed");
+            }
+
+            arg.v_long = type;
+            break;
+        }
+        default:
+            /* TODO */
+            g_assert_not_reached();
     }
 
     return arg;
@@ -693,7 +730,7 @@ pyg_array_from_pyobject(PyObject *object, GITypeInfo *type_info, gsize *length)
         py_item = PyTuple_GetItem(object, i);
         g_assert(py_item != NULL);
 
-        arg = pyg_argument_from_pyobject(py_item, item_type_info);
+        arg = pygi_g_argument_from_py_object(py_item, item_type_info);
 
         g_memmove(current_item, &arg, item_size);
 
diff --git a/gi/pygargument.h b/gi/pygargument.h
index d55a606..580ab16 100644
--- a/gi/pygargument.h
+++ b/gi/pygargument.h
@@ -31,8 +31,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);
+GArgument pygi_g_argument_from_py_object(PyObject *object,
+				                         GITypeInfo *type_info);
+
 PyObject*  pyg_argument_to_pyobject(GArgument *arg,
 				    GITypeInfo *info);
 
diff --git a/gi/pygiinfo.c b/gi/pygiinfo.c
index 3f393c1..10c8f57 100644
--- a/gi/pygiinfo.c
+++ b/gi/pygiinfo.c
@@ -552,7 +552,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
             container_info = g_base_info_get_container(self->info);
             container_info_type = g_base_info_get_type(container_info);
 
-            /* FIXME: this could take place in pyg_argument_from_pyobject, but we need to create an
+            /* FIXME: this could take place in pygi_g_argument_from_py_object, but we need to create an
                independant function because it needs a GITypeInfo to be passed. */
 
             switch(container_info_type) {
@@ -799,7 +799,15 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
                 py_arg = PyTuple_GetItem(args, py_args_pos);
                 g_assert(py_arg != NULL);
 
-                GArgument in_value = pyg_argument_from_pyobject(py_arg, g_arg_info_get_type(arg_info));
+                GArgument in_value = pygi_g_argument_from_py_object(py_arg, g_arg_info_get_type(arg_info));
+
+                if (PyErr_Occurred()) {
+                    /* TODO: Release ressources allocated for previous arguments. */
+                    g_base_info_unref((GIBaseInfo *)arg_type_info);
+                    g_base_info_unref((GIBaseInfo *)arg_info);
+                    g_base_info_unref((GIBaseInfo *)return_info);
+                    return NULL;
+                }
 
                 if (direction == GI_DIRECTION_IN) {
                     /* Pass the value. */
@@ -1591,7 +1599,7 @@ _wrap_g_field_info_set_value(PyGIBaseInfo *self, PyObject *args)
         goto return_;
     }
 
-    value = pyg_argument_from_pyobject(py_value, field_type_info);
+    value = pygi_g_argument_from_py_object(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)



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