diff -r 1ff29b57628e Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py Wed Dec 02 14:37:35 2015 +0100 +++ b/Lib/test/test_exceptions.py Wed Dec 02 13:31:14 2015 -0500 @@ -625,6 +625,29 @@ obj = wr() self.assertTrue(obj is None, "%s" % obj) + def testExceptionChainedContext(self): + class Err1(Exception): pass + class Err2(Exception): pass + + try: + try: + raise Err1 + except Err1 as ex: + ex.__context__ = ex + raise Err2 + except Err2 as ex: + self.assertIs(type(ex.__context__), Err1) + + try: + try: + raise Err1 + except Err1 as ex: + ex.__context__ = Exception() + ex.__context__.__context__ = ex + raise Err2 + except Err2 as ex: + self.assertIs(type(ex.__context__), Err1) + def test_exception_target_in_nested_scope(self): # issue 4617: This used to raise a SyntaxError # "can not delete variable 'e' referenced in nested scope" diff -r 1ff29b57628e Objects/exceptions.c --- a/Objects/exceptions.c Wed Dec 02 14:37:35 2015 +0100 +++ b/Objects/exceptions.c Wed Dec 02 13:31:14 2015 -0500 @@ -347,6 +347,21 @@ /* Steals a reference to context */ void PyException_SetContext(PyObject *self, PyObject *context) { + PyObject *next_in_context; + + if (context != NULL) { + if (context == self) { + return; + } + next_in_context = context; + while ((next_in_context = PyException_GetContext(next_in_context))) { + Py_DECREF(next_in_context); + if (next_in_context == self) { + return; + } + } + } + PyObject *old_context = ((PyBaseExceptionObject *)self)->context; ((PyBaseExceptionObject *)self)->context = context; Py_XDECREF(old_context);

AltStyle によって変換されたページ (->オリジナル) /