[pygobject] Refactor pyg_value_from_pyobject into two functions



commit 2cff4827e6d15bcad630316a8a4e67968a70bbbf
Author: Simon Feltman <sfeltman src gnome org>
Date:   Sat Jul 6 14:10:20 2013 -0700

    Refactor pyg_value_from_pyobject into two functions
    
    Break pyg_value_from_pyobject into two functions. One which keeps
    Python exceptions queued (pyg_value_from_pyobject_with_error) and
    one which clears them (pyg_value_from_pyobject). This allows for
    re-use for code which want to keep the errors around
    
    https://bugzilla.gnome.org/show_bug.cgi?id=688081

 gi/_gobject/gobjectmodule.c     |    4 ++-
 gi/_gobject/pygobject-private.h |    1 +
 gi/_gobject/pygobject.h         |    2 +
 gi/_gobject/pygtype.c           |   67 ++++++++++++++++++++++++++++++--------
 4 files changed, 59 insertions(+), 15 deletions(-)
---
diff --git a/gi/_gobject/gobjectmodule.c b/gi/_gobject/gobjectmodule.c
index 81dc44b..736cd8c 100644
--- a/gi/_gobject/gobjectmodule.c
+++ b/gi/_gobject/gobjectmodule.c
@@ -2072,7 +2072,9 @@ struct _PyGObject_Functions pygobject_api_functions = {
   pyg_type_from_object_strict,
 
   pygobject_new_full,
-  &PyGObject_Type
+  &PyGObject_Type,
+
+  pyg_value_from_pyobject_with_error
 };
 
 /* for addon libraries ... */
diff --git a/gi/_gobject/pygobject-private.h b/gi/_gobject/pygobject-private.h
index e2a0af7..294b0f6 100644
--- a/gi/_gobject/pygobject-private.h
+++ b/gi/_gobject/pygobject-private.h
@@ -85,6 +85,7 @@ void      pyg_register_gtype_custom(GType gtype,
                             fromvaluefunc from_func,
                             tovaluefunc to_func);
 int       pyg_value_from_pyobject(GValue *value, PyObject *obj);
+int       pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj);
 PyObject *pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed);
 int       pyg_param_gvalue_from_pyobject(GValue* value,
                                          PyObject* py_obj,
diff --git a/gi/_gobject/pygobject.h b/gi/_gobject/pygobject.h
index f6b531d..76b8b11 100644
--- a/gi/_gobject/pygobject.h
+++ b/gi/_gobject/pygobject.h
@@ -195,6 +195,7 @@ struct _PyGObject_Functions {
 
     PyObject *(* newgobj_full)(GObject *obj, gboolean steal, gpointer g_class);
     PyTypeObject *object_type;
+    int (* value_from_pyobject_with_error)(GValue *value, PyObject *obj);
 };
 
 
@@ -244,6 +245,7 @@ struct _PyGObject_Functions *_PyGObject_API;
 #define pyg_flags_get_value         (_PyGObject_API->flags_get_value)
 #define pyg_register_gtype_custom   (_PyGObject_API->register_gtype_custom)
 #define pyg_value_from_pyobject     (_PyGObject_API->value_from_pyobject)
+#define pyg_value_from_pyobject_with_error (_PyGObject_API->value_from_pyobject_with_error)
 #define pyg_value_as_pyobject       (_PyGObject_API->value_as_pyobject)
 #define pyg_register_interface      (_PyGObject_API->register_interface)
 #define PyGBoxed_Type               (*_PyGObject_API->boxed_type)
diff --git a/gi/_gobject/pygtype.c b/gi/_gobject/pygtype.c
index 3f3f048..0b920f6 100644
--- a/gi/_gobject/pygtype.c
+++ b/gi/_gobject/pygtype.c
@@ -785,7 +785,7 @@ pyg_array_from_pyobject(GValue *value,
 }
 
 /**
- * pyg_value_from_pyobject:
+ * pyg_value_from_pyobject_with_error:
  * @value: the GValue object to store the converted value in.
  * @obj: the Python object to convert.
  *
@@ -797,7 +797,7 @@ pyg_array_from_pyobject(GValue *value,
  * Returns: 0 on success, -1 on error.
  */
 int
-pyg_value_from_pyobject(GValue *value, PyObject *obj)
+pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj)
 {
     PyObject *tmp;
     GType value_type = G_VALUE_TYPE(value);
@@ -810,15 +810,18 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
                 g_value_set_object(value, NULL);
             else {
                 if (!PyObject_TypeCheck(obj, &PyGObject_Type)) {
+                    PyErr_SetString(PyExc_TypeError, "GObject is required");
                     return -1;
                 }
                 if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
                         value_type)) {
+                    PyErr_SetString(PyExc_TypeError, "Invalid GObject type for assignment");
                     return -1;
                 }
                 g_value_set_object(value, pygobject_get(obj));
             }
         } else {
+            PyErr_SetString(PyExc_TypeError, "Unsupported conversion");
             return -1;
         }
         break;
@@ -841,7 +844,7 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
             g_value_set_schar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
             Py_DECREF(tmp);
         } else {
-            PyErr_Clear();
+            PyErr_SetString(PyExc_TypeError, "Cannot convert to TYPE_CHAR");
             return -1;
         }
 
@@ -936,7 +939,6 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
     {
         gint val = 0;
         if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
-            PyErr_Clear();
             return -1;
         }
         g_value_set_enum(value, val);
@@ -946,7 +948,6 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
     {
         guint val = 0;
         if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
-            PyErr_Clear();
             return -1;
         }
         g_value_set_flags(value, val);
@@ -970,6 +971,7 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
                     g_value_set_string(value, PYGLIB_PyBytes_AsString(tmp));
                     Py_DECREF(tmp);
                 } else {
+                    PyErr_SetString(PyExc_TypeError, "Expected string");
                     return -1;
                 }
             } else {
@@ -994,8 +996,10 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
             g_value_set_pointer(value, PYGLIB_CPointer_GetPointer(obj, NULL));
         else if (G_VALUE_HOLDS_GTYPE (value))
             g_value_set_gtype (value, pyg_type_from_object (obj));
-        else
+        else {
+            PyErr_SetString(PyExc_TypeError, "Expected pointer");
             return -1;
+        }
         break;
     case G_TYPE_BOXED: {
         PyGTypeMarshal *bm;
@@ -1013,13 +1017,12 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
 
             type = pyg_type_from_object((PyObject*)Py_TYPE(obj));
             if (G_UNLIKELY (! type)) {
-                PyErr_Clear();
                 return -1;
             }
             n_value = g_new0 (GValue, 1);
             g_value_init (n_value, type);
             g_value_take_boxed (value, n_value);
-            return pyg_value_from_pyobject (n_value, obj);
+            return pyg_value_from_pyobject_with_error (n_value, obj);
         }
         else if (PySequence_Check(obj) &&
                 G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY))
@@ -1043,8 +1046,10 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
             return bm->tovalue(value, obj);
         else if (PYGLIB_CPointer_Check(obj))
             g_value_set_boxed(value, PYGLIB_CPointer_GetPointer(obj, NULL));
-        else
+        else {
+            PyErr_SetString(PyExc_TypeError, "Expected Boxed");
             return -1;
+        }
         break;
     }
     case G_TYPE_PARAM:
@@ -1054,8 +1059,10 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
             g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj)));
         else if (PyGParamSpec_Check(obj))
             g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL));
-        else
+        else {
+            PyErr_SetString(PyExc_TypeError, "Expected ParamSpec");
             return -1;
+        }
         break;
     case G_TYPE_OBJECT:
         if (obj == Py_None) {
@@ -1064,8 +1071,10 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
                 G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
                         G_VALUE_TYPE(value))) {
             g_value_set_object(value, pygobject_get(obj));
-        } else
+        } else {
+            PyErr_SetString(PyExc_TypeError, "Expected GObject");
             return -1;
+        }
         break;
     case G_TYPE_VARIANT:
     {
@@ -1073,27 +1082,57 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
             g_value_set_variant(value, NULL);
         else if (pyg_type_from_object_strict(obj, FALSE) == G_TYPE_VARIANT)
             g_value_set_variant(value, pyg_boxed_get(obj, GVariant));
-        else
+        else {
+            PyErr_SetString(PyExc_TypeError, "Expected Variant");
             return -1;
+        }
         break;
     }
     default:
     {
         PyGTypeMarshal *bm;
-        if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
+        if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) {
             return bm->tovalue(value, obj);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "Unknown value type");
+            return -1;
+        }
         break;
     }
     }
+
+    /* If an error occurred, unset the GValue but don't clear the Python error. */
     if (PyErr_Occurred()) {
         g_value_unset(value);
-        PyErr_Clear();
         return -1;
     }
+
     return 0;
 }
 
 /**
+ * pyg_value_from_pyobject:
+ * @value: the GValue object to store the converted value in.
+ * @obj: the Python object to convert.
+ *
+ * Same basic function as pyg_value_from_pyobject_with_error but clears
+ * any Python errors before returning.
+ *
+ * Returns: 0 on success, -1 on error.
+ */
+int
+pyg_value_from_pyobject(GValue *value, PyObject *obj)
+{
+    int res = pyg_value_from_pyobject_with_error (value, obj);
+
+    if (PyErr_Occurred()) {
+        PyErr_Clear();
+        return -1;
+    }
+    return res;
+}
+
+/**
  * pyg_value_as_pyobject:
  * @value: the GValue object.
  * @copy_boxed: true if boxed values should be copied.


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