Skip to content

Commit ba2ecd6

Browse files
committed
Issue #27123: When an exception is raised within the context being
managed by a contextlib.ExitStack() and one of the exit stack generators catches and raises it in a chain, do not re-raise the original exception when exiting, let the new chained one through. This avoids the PEP 479 bug described in issue25782.
1 parent c72828b commit ba2ecd6

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

Lib/contextlib.py

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ def __exit__(self, type, value, traceback):
8282
# raised inside the "with" statement from being suppressed.
8383
return exc is not value
8484
except RuntimeError as exc:
85+
# Don't re-raise the passed in exception. (issue27112)
86+
if exc is value:
87+
return False
8588
# Likewise, avoid suppressing if a StopIteration exception
8689
# was passed to throw() and later wrapped into a RuntimeError
8790
# (see PEP 479).

Lib/test/test_contextlib.py

+28
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,34 @@ class Example(object): pass
762762
stack.push(cm)
763763
self.assertIs(stack._exit_callbacks[-1], cm)
764764

765+
def test_dont_reraise_RuntimeError(self):
766+
"""https://bugs.python.org/issue27122"""
767+
class UniqueException(Exception): pass
768+
769+
@contextmanager
770+
def second():
771+
try:
772+
yield 1
773+
except Exception as exc:
774+
raise UniqueException("new exception") from exc
775+
776+
@contextmanager
777+
def first():
778+
try:
779+
yield 1
780+
except Exception as exc:
781+
raise exc
782+
783+
# The RuntimeError should be caught by second()'s exception
784+
# handler which chain raised a new UniqueException.
785+
with self.assertRaises(UniqueException) as err_ctx:
786+
with ExitStack() as es_ctx:
787+
es_ctx.enter_context(second())
788+
es_ctx.enter_context(first())
789+
raise RuntimeError("please no infinite loop.")
790+
791+
self.assertEqual(err_ctx.exception.args[0], "new exception")
792+
765793

766794
class TestRedirectStream:
767795

Misc/NEWS

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ Core and Builtins
1313
Library
1414
-------
1515

16+
- Issue #27123: When an exception is raised within the context being managed
17+
by a contextlib.ExitStack() and one of the exit stack generators
18+
catches and raises it in a chain, do not re-raise the original exception
19+
when exiting, let the new chained one through. This avoids the PEP 479
20+
bug described in issue25782.
21+
1622
- Issue #27278: Fix os.urandom() implementation using getrandom() on Linux.
1723
Truncate size to INT_MAX and loop until we collected enough random bytes,
1824
instead of casting a directly Py_ssize_t to int.

0 commit comments

Comments
 (0)