From: Stefan Behnel Date: Fri, 24 Aug 2012 15:45:14 +0000 (+0200) Subject: implement bare 'raise' statement outside of except blocks X-Git-Tag: 0.17b4~34 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f5f34c7b2523ddbf4b1d566c4b797563ccee23b2;p=platform%2Fupstream%2Fpython-cython.git implement bare 'raise' statement outside of except blocks --- diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index e2119ec..188de3d 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -5006,7 +5006,7 @@ class ReraiseStatNode(StatNode): is_terminator = True def analyse_expressions(self, env): - env.use_utility_code(restore_exception_utility_code) + pass nogil_check = Node.gil_error gil_message = "Raising exception" @@ -5014,6 +5014,7 @@ class ReraiseStatNode(StatNode): def generate_execution_code(self, code): vars = code.funcstate.exc_vars if vars: + code.globalstate.use_utility_code(restore_exception_utility_code) for varname in vars: code.put_giveref(varname) code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars)) @@ -5022,8 +5023,9 @@ class ReraiseStatNode(StatNode): code.putln() code.putln(code.error_goto(self.pos)) else: - error(self.pos, "Reraise not inside except clause") - + code.globalstate.use_utility_code( + UtilityCode.load_cached("ReRaiseException", "Exceptions.c")) + code.putln("__Pyx_ReraiseException(); %s" % code.error_goto(self.pos)) class AssertStatNode(StatNode): # assert statement diff --git a/Cython/Utility/Exceptions.c b/Cython/Utility/Exceptions.c index 33b068e..4de4c36 100644 --- a/Cython/Utility/Exceptions.c +++ b/Cython/Utility/Exceptions.c @@ -255,6 +255,41 @@ bad: return -1; } +/////////////// ReRaiseException.proto /////////////// + +static CYTHON_INLINE void __Pyx_ReraiseException(void); /*proto*/ + +/////////////// ReRaiseException.proto /////////////// + +static CYTHON_INLINE void __Pyx_ReraiseException(void) { + PyObject *type = NULL, *value = NULL, *tb = NULL; +#if CYTHON_COMPILING_IN_CPYTHON + PyThreadState *tstate = PyThreadState_GET(); + type = tstate->exc_type; + value = tstate->exc_value; + tb = tstate->exc_traceback; +#else + PyErr_GetExcInfo(type, value, tb); +#endif + if (!type || type == Py_None) { +#if !CYTHON_COMPILING_IN_CPYTHON + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tb); +#endif + PyErr_SetString(PyExc_RuntimeError, + "No active exception to reraise"); // message copied from Py3 + } else { +#if CYTHON_COMPILING_IN_CPYTHON + Py_INCREF(type); + Py_XINCREF(value); + Py_XINCREF(tb); + +#endif + PyErr_Restore(type, value, tb); + } +} + /////////////// SaveResetException.proto /////////////// static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ diff --git a/tests/run/reraise.py b/tests/run/reraise.py new file mode 100644 index 0000000..1303266 --- /dev/null +++ b/tests/run/reraise.py @@ -0,0 +1,35 @@ + +def reraise(): + raise + +def test_reraise(): + """ + >>> test_reraise() + Traceback (most recent call last): + ValueError: TEST + """ + try: + raise ValueError("TEST") + except ValueError: + raise + +def test_reraise_indirect(): + """ + >>> test_reraise_indirect() + Traceback (most recent call last): + ValueError: TEST INDIRECT + """ + try: + raise ValueError("TEST INDIRECT") + except ValueError: + reraise() + +def test_reraise_error(): + """ + >>> try: test_reraise_error() + ... except (RuntimeError, TypeError): pass # Py2, Py3, ... + ... else: print("FAILED") + """ + import sys + sys.exc_clear() + raise