let CPython do the exception instantiation on 'raise' in Py3 to make sure we handle...
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 23 Nov 2013 07:50:14 +0000 (08:50 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 23 Nov 2013 07:50:14 +0000 (08:50 +0100)
Cython/Utility/Exceptions.c
tests/run/reraise_3args.pyx [new file with mode: 0644]

index 3c3b642..917f366 100644 (file)
@@ -135,7 +135,6 @@ raise_error:
 #else /* Python 3+ */
 
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
-    PyObject* owned_instance = NULL;
     if (tb == Py_None) {
         tb = 0;
     } else if (tb && !PyTraceBack_Check(tb)) {
@@ -143,11 +142,9 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             "raise: arg 3 must be a traceback or None");
         goto bad;
     }
-    if (value == Py_None)
-        value = 0;
 
     if (PyExceptionInstance_Check(type)) {
-        if (value) {
+        if (value && value != Py_None) {
             PyErr_SetString(PyExc_TypeError,
                 "instance exception may not have a separate value");
             goto bad;
@@ -156,21 +153,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
         type = (PyObject*) Py_TYPE(value);
     } else if (PyExceptionClass_Check(type)) {
         // instantiate the type now (we don't know when and how it will be caught)
-        PyObject *args;
-        if (!value)
-            args = PyTuple_New(0);
-        else if (PyTuple_Check(value)) {
-            Py_INCREF(value);
-            args = value;
-        } else
-            args = PyTuple_Pack(1, value);
-        if (!args)
-            goto bad;
-        owned_instance = PyEval_CallObject(type, args);
-        Py_DECREF(args);
-        if (!owned_instance)
-            goto bad;
-        value = owned_instance;
+        PyErr_NormalizeException(&type, &value, &tb);
         if (!PyExceptionInstance_Check(value)) {
             PyErr_Format(PyExc_TypeError,
                          "calling %R should have returned an instance of "
@@ -222,7 +205,6 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
     }
 
 bad:
-    Py_XDECREF(owned_instance);
     return;
 }
 #endif
diff --git a/tests/run/reraise_3args.pyx b/tests/run/reraise_3args.pyx
new file mode 100644 (file)
index 0000000..a892efe
--- /dev/null
@@ -0,0 +1,23 @@
+
+import sys
+
+
+class MyError(Exception):
+    def __init__(self, name, var):
+        self.name = name
+        self.var = var
+
+
+def reraise_explicitly():
+    """
+    >>> try: reraise_explicitly()
+    ... except MyError: print("RAISED!")
+    ... else: print("NOT RAISED!")
+    RAISED!
+    """
+    try:
+        raise MyError('Oh no!', 42)
+    except MyError:
+        tmp = sys.exc_info()
+
+    raise tmp[0], tmp[1], tmp[2]