[pygobject] Ensure exceptions set in closure out argument marshaling are printed



commit ec3de7608ec970f6f272c9d7937344f02c6e9c3d
Author: Simon Feltman <sfeltman src gnome org>
Date:   Mon Jul 29 01:21:19 2013 -0700

    Ensure exceptions set in closure out argument marshaling are printed
    
    Call PyErr_Print when an exception occurs after marshaling closure
    out arguments. These exceptions were being ignored and cleared out
    only to show up in debug builds of Python.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705064

 gi/pygi-closure.c              |    8 ++++++++
 tests/test_generictreemodel.py |   17 +++++++++++------
 2 files changed, 19 insertions(+), 6 deletions(-)
---
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index 601db94..7582069 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -33,6 +33,9 @@ _pygi_closure_assign_pyobj_to_retval (gpointer retval, PyObject *object,
                                       GITransfer transfer)
 {
     GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
+    if (PyErr_Occurred ())
+        return;
+
     GITypeTag type_tag = g_type_info_get_tag (type_info);
 
     if (retval == NULL)
@@ -558,6 +561,11 @@ _pygi_closure_handle (ffi_cif *cif,
     }
 
     _pygi_closure_set_out_arguments (closure->info, retval, out_args, result);
+    if (PyErr_Occurred ()) {
+        _pygi_closure_clear_retval (closure->info, result);
+        PyErr_Print();
+    }
+
     Py_DECREF (retval);
 
 end:
diff --git a/tests/test_generictreemodel.py b/tests/test_generictreemodel.py
index ff0f523..9fa89ff 100644
--- a/tests/test_generictreemodel.py
+++ b/tests/test_generictreemodel.py
@@ -314,12 +314,12 @@ class ExceptHook(object):
     are never bubbled through from python to C back to python.
     This works because exception hooks are called in PyErr_Print.
     """
-    def __init__(self, exc_type):
-        self._exc_type = exc_type
+    def __init__(self, *expected_exc_types):
+        self._expected_exc_types = expected_exc_types
         self._exceptions = []
 
     def _excepthook(self, exc_type, value, traceback):
-        self._exceptions.append(exc_type)
+        self._exceptions.append((exc_type, value))
 
     def __enter__(self):
         self._oldhook = sys.excepthook
@@ -328,8 +328,13 @@ class ExceptHook(object):
 
     def __exit__(self, exc_type, exc_val, exc_tb):
         sys.excepthook = self._oldhook
-        assert len(self._exceptions) == 1, 'Expecting exactly one exception of type %s' % self._exc_type
-        assert issubclass(self._exceptions[0], self._exc_type), 'Expecting exactly one exception of type %s' 
% self._exc_type
+        error_message = 'Expecting the following exceptions: %s, got: %s' % \
+            (str(self._expected_exc_types), '\n'.join([str(item) for item in self._exceptions]))
+
+        assert len(self._expected_exc_types) == len(self._exceptions), error_message
+
+        for expected, got in zip(self._expected_exc_types, [exc[0] for exc in self._exceptions]):
+            assert issubclass(got, expected), error_message
 
 
 class TestReturnsAfterError(unittest.TestCase):
@@ -347,7 +352,7 @@ class TestReturnsAfterError(unittest.TestCase):
         self.assertEqual(count, 0)
 
     def test_get_column_type(self):
-        with ExceptHook(NotImplementedError):
+        with ExceptHook(NotImplementedError, TypeError):
             col_type = self.model.get_column_type(0)
         self.assertEqual(col_type, GObject.TYPE_INVALID)
 


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