bpo-29692: contextlib.contextmanager may incorrectly unchain RuntimeError (GH-949)

contextlib._GeneratorContextManager.__exit__ includes a special case to deal with
PEP 479 RuntimeErrors created when `StopIteration` is thrown into the context
manager body.

Previously this check was too permissive, and undid one level of chaining on *all*
RuntimeError instances, not just those that wrapped a StopIteration instance.
This commit is contained in:
svelankar 2017-04-11 05:11:13 -04:00 committed by Nick Coghlan
parent 6fab78e902
commit 00c75e9a45
3 changed files with 32 additions and 6 deletions

View file

@ -152,6 +152,29 @@ def woohoo():
else:
self.fail('StopIteration was suppressed')
def test_contextmanager_do_not_unchain_non_stopiteration_exceptions(self):
@contextmanager
def test_issue29692():
try:
yield
except Exception as exc:
raise RuntimeError('issue29692:Chained') from exc
try:
with test_issue29692():
raise ZeroDivisionError
except Exception as ex:
self.assertIs(type(ex), RuntimeError)
self.assertEqual(ex.args[0], 'issue29692:Chained')
self.assertIsInstance(ex.__cause__, ZeroDivisionError)
try:
with test_issue29692():
raise StopIteration('issue29692:Unchained')
except Exception as ex:
self.assertIs(type(ex), StopIteration)
self.assertEqual(ex.args[0], 'issue29692:Unchained')
self.assertIsNone(ex.__cause__)
def _create_contextmanager_attribs(self):
def attribs(**kw):
def decorate(func):