[pygobject] Fix "Returns: (skip)" method calls without (out) arguments



commit 5c24760b797e985721f7fe51d52252e4dd54a417
Author: Martin Pitt <martin pitt ubuntu com>
Date:   Fri Oct 21 17:31:41 2011 +0200

    Fix "Returns: (skip)" method calls without (out) arguments
    
    When we have a method call with a skipped return value, but no other out
    arguments, we previously returned NULL to Python, which causes "SystemError:
    error return without exception set". Return None instead.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=662383

 gi/pygi-invoke.c         |   10 ++++++++++
 tests/test_everything.py |    8 ++++++++
 2 files changed, 18 insertions(+), 0 deletions(-)
---
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 0064fe5..42cdd01 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -550,6 +550,16 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
     total_out_args -= cache->n_to_py_child_args;
 
     if (cache->n_to_py_args - cache->n_to_py_child_args  == 0) {
+        if (cache->return_cache->is_skipped && state->error == NULL) {
+            /* we skip the return value and have no (out) arguments to return,
+             * so py_return should be NULL. But we must not return NULL,
+             * otherwise Python will expect an exception.
+             */
+            g_assert (py_return == NULL);
+            Py_INCREF(Py_None);
+            py_return = Py_None;
+        }
+
         py_out = py_return;
     } else if (total_out_args == 1) {
         /* if we get here there is one out arg an no return */
diff --git a/tests/test_everything.py b/tests/test_everything.py
index db46482..19d345b 100644
--- a/tests/test_everything.py
+++ b/tests/test_everything.py
@@ -484,6 +484,14 @@ class TestAdvancedInterfaces(unittest.TestCase):
         self.assertEquals(ret[1], 61);
         self.assertEquals(ret[2], 32);
 
+    def test_obj_skip_return_val_no_out(self):
+        obj = Everything.TestObj();
+        # raises an error for 0, succeeds for any other value
+        self.assertRaises(GLib.GError, obj.skip_return_val_no_out, 0)
+
+        ret = obj.skip_return_val_no_out(1)
+        self.assertEquals(ret, None)
+
 class TestSignals(unittest.TestCase):
     def test_object_param_signal(self):
         obj = Everything.TestObj();



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