From e757c76589d927e25c1202ef2482a1cfd0757fba Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Wed, 29 Apr 2020 22:21:08 -0700 Subject: [PATCH 1/4] Add a failing test for issue 29587. --- Lib/test/test_generators.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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(): From 57597f2738c7fe09d0a716dca72bd8feb66f447e Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Thu, 30 Apr 2020 00:31:39 -0700 Subject: [PATCH 2/4] bpo-29587: set exc.__context__ when calling gen.throw() (GH-19811) Before this commit, if an exception was active inside a generator when calling gen.throw(), then that exception was lost (i.e. there was no implicit exception chaining). This commit fixes that. --- .../2020-04-30-00-50-25.bpo-29587.oEwSq.rst | 1 + Objects/genobject.c | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-04-30-00-50-25.bpo-29587.oEwSq.rst 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..289ed79aa28a65 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -512,6 +512,12 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, } PyErr_Restore(typ, val, tb); + if (gen->gi_exc_state.exc_type) { + Py_INCREF(gen->gi_exc_state.exc_type); + Py_XINCREF(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: From c321731d95c121e76e377812ba522ad268476519 Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Fri, 1 May 2020 01:09:34 -0700 Subject: [PATCH 3/4] Wrap the long line. --- Objects/genobject.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Objects/genobject.c b/Objects/genobject.c index 289ed79aa28a65..65ad9d4d3d07b0 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -516,7 +516,8 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, Py_INCREF(gen->gi_exc_state.exc_type); Py_XINCREF(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); + _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); From 1bf33096f1b0c658801c1b16efc2d15d93d85109 Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Fri, 1 May 2020 01:16:26 -0700 Subject: [PATCH 4/4] Address the CI failures on Fedora, etc. --- Objects/genobject.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Objects/genobject.c b/Objects/genobject.c index 65ad9d4d3d07b0..41a63ae2e666aa 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -512,9 +512,11 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, } PyErr_Restore(typ, val, tb); - if (gen->gi_exc_state.exc_type) { + /* 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_XINCREF(gen->gi_exc_state.exc_value); + 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); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy