Skip to content

Commit 881aa38

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.
2 parents c206f1e + ba2ecd6 commit 881aa38

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
@@ -105,6 +105,9 @@ def __exit__(self, type, value, traceback):
105105
# raised inside the "with" statement from being suppressed.
106106
return exc is not value
107107
except RuntimeError as exc:
108+
# Don't re-raise the passed in exception. (issue27112)
109+
if exc is value:
110+
return False
108111
# Likewise, avoid suppressing if a StopIteration exception
109112
# was passed to throw() and later wrapped into a RuntimeError
110113
# (see PEP 479).

Lib/test/test_contextlib.py

+28
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,34 @@ class Example(object): pass
795795
stack.push(cm)
796796
self.assertIs(stack._exit_callbacks[-1], cm)
797797

798+
def test_dont_reraise_RuntimeError(self):
799+
"""https://bugs.python.org/issue27122"""
800+
class UniqueException(Exception): pass
801+
802+
@contextmanager
803+
def second():
804+
try:
805+
yield 1
806+
except Exception as exc:
807+
raise UniqueException("new exception") from exc
808+
809+
@contextmanager
810+
def first():
811+
try:
812+
yield 1
813+
except Exception as exc:
814+
raise exc
815+
816+
# The RuntimeError should be caught by second()'s exception
817+
# handler which chain raised a new UniqueException.
818+
with self.assertRaises(UniqueException) as err_ctx:
819+
with ExitStack() as es_ctx:
820+
es_ctx.enter_context(second())
821+
es_ctx.enter_context(first())
822+
raise RuntimeError("please no infinite loop.")
823+
824+
self.assertEqual(err_ctx.exception.args[0], "new exception")
825+
798826

799827
class TestRedirectStream:
800828

Misc/NEWS

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ What's New in Python 3.6.0 alpha 3
1010
Library
1111
-------
1212

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

0 commit comments

Comments
 (0)