diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 3e42bc6b69a819..4d96f44b150622 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -316,6 +316,23 @@ def g(): self.assertEqual(cm.exception.value.value, 2) +class GeneratorThrowTest(unittest.TestCase): + + def test_exception_context_set(self): + def f(): + try: + raise KeyError('a') + except Exception: + yield + + gen = f() + gen.send(None) + with self.assertRaises(ValueError) as cm: + gen.throw(ValueError) + context = cm.exception.__context__ + self.assertEqual((type(context), context.args), (KeyError, ('a',))) + + class YieldFromTests(unittest.TestCase): def test_generator_gi_yieldfrom(self): def a(): diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-04-30-00-50-25.bpo-29587.oEwSq.rst b/Misc/NEWS.d/next/Core and Builtins/2020-04-30-00-50-25.bpo-29587.oEwSq.rst new file mode 100644 index 00000000000000..f44aa360cc2ef3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-04-30-00-50-25.bpo-29587.oEwSq.rst @@ -0,0 +1 @@ +Enable implicit exception chaining when calling :meth:`generator.throw`. diff --git a/Objects/genobject.c b/Objects/genobject.c index 6e36690b65148a..41a63ae2e666aa 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -512,6 +512,15 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, } PyErr_Restore(typ, val, tb); + /* XXX Should we also handle the case where exc_type is true and + exc_value is false? */ + if (gen->gi_exc_state.exc_type && gen->gi_exc_state.exc_value) { + Py_INCREF(gen->gi_exc_state.exc_type); + Py_INCREF(gen->gi_exc_state.exc_value); + Py_XINCREF(gen->gi_exc_state.exc_traceback); + _PyErr_ChainExceptions(gen->gi_exc_state.exc_type, + gen->gi_exc_state.exc_value, gen->gi_exc_state.exc_traceback); + } return gen_send_ex(gen, Py_None, 1, 0); failed_throw:
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: