diff options
author | Guido van Rossum <guido@python.org> | 2008-06-14 20:20:24 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2008-06-14 20:20:24 (GMT) |
commit | b4fb6e4d27b56c2119bd1dad83afce874e34a72a (patch) | |
tree | 8d3d70b49164329da4a47c9d08364f18018b16df /Python | |
parent | 973124fd70687f6032a1d6e3a0b9e640d2691133 (diff) | |
download | cpython-b4fb6e4d27b56c2119bd1dad83afce874e34a72a.zip cpython-b4fb6e4d27b56c2119bd1dad83afce874e34a72a.tar.gz cpython-b4fb6e4d27b56c2119bd1dad83afce874e34a72a.tar.bz2 |
Implicit exception chaining via __context__ (PEP 3134).
Patch 3108 by Antooine Pitrou.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 10 | ||||
-rw-r--r-- | Python/errors.c | 33 |
2 files changed, 37 insertions, 6 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index bcb15e7..6aaa52d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2817,11 +2817,12 @@ fail: /* Jump here from prelude on failure */ static enum why_code do_raise(PyObject *exc, PyObject *cause) { - PyObject *type = NULL, *value = NULL, *tb = NULL; + PyObject *type = NULL, *value = NULL; if (exc == NULL) { /* Reraise */ PyThreadState *tstate = PyThreadState_GET(); + PyObject *tb; type = tstate->exc_type; value = tstate->exc_value; tb = tstate->exc_traceback; @@ -2862,7 +2863,6 @@ do_raise(PyObject *exc, PyObject *cause) goto raise_error; } - tb = PyException_GetTraceback(value); if (cause) { PyObject *fixed_cause; if (PyExceptionClass_Check(cause)) { @@ -2883,13 +2883,15 @@ do_raise(PyObject *exc, PyObject *cause) PyException_SetCause(value, fixed_cause); } - PyErr_Restore(type, value, tb); + PyErr_SetObject(type, value); + /* PyErr_SetObject incref's its arguments */ + Py_XDECREF(value); + Py_XDECREF(type); return WHY_EXCEPTION; raise_error: Py_XDECREF(value); Py_XDECREF(type); - Py_XDECREF(tb); Py_XDECREF(cause); return WHY_EXCEPTION; } diff --git a/Python/errors.c b/Python/errors.c index b765b03..ac64b6a 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -52,6 +52,9 @@ PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback) void PyErr_SetObject(PyObject *exception, PyObject *value) { + PyThreadState *tstate = PyThreadState_GET(); + PyObject *tb = NULL; + if (exception != NULL && !PyExceptionClass_Check(exception)) { PyErr_Format(PyExc_SystemError, @@ -59,9 +62,35 @@ PyErr_SetObject(PyObject *exception, PyObject *value) exception); return; } - Py_XINCREF(exception); Py_XINCREF(value); - PyErr_Restore(exception, value, (PyObject *)NULL); + if (tstate->exc_value != NULL && tstate->exc_value != Py_None) { + /* Implicit exception chaining */ + if (value == NULL || !PyExceptionInstance_Check(value)) { + /* We must normalize the value right now */ + PyObject *args, *fixed_value; + if (value == NULL || value == Py_None) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } + else + args = PyTuple_Pack(1, value); + fixed_value = args ? + PyEval_CallObject(exception, args) : NULL; + Py_XDECREF(args); + Py_XDECREF(value); + if (fixed_value == NULL) + return; + value = fixed_value; + } + Py_INCREF(tstate->exc_value); + PyException_SetContext(value, tstate->exc_value); + } + if (value != NULL && PyExceptionInstance_Check(value)) + tb = PyException_GetTraceback(value); + Py_XINCREF(exception); + PyErr_Restore(exception, value, tb); } void |