Skip to content

Commit

Permalink
Issue jazzband#7: Backport fix for CPython issue #27122
Browse files Browse the repository at this point in the history
Prevents a potential infinite loop on Python 3.5 when handling
``RuntimeError``.

(CPython updates by Gregory P. Smith & Serhiy Storchaka)
  • Loading branch information
ncoghlan committed Jul 31, 2016
1 parent e4fbea4 commit 2f4fd22
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
3 changes: 3 additions & 0 deletions contextlib2.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ def __exit__(self, type, value, traceback):
# raised inside the "with" statement from being suppressed.
return exc is not value
except RuntimeError as exc:
# Don't re-raise the passed in exception
if exc is value:
return False
# Likewise, avoid suppressing if a StopIteration exception
# was passed to throw() and later wrapped into a RuntimeError
# (see PEP 479).
Expand Down
38 changes: 38 additions & 0 deletions test_contextlib2.py
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,44 @@ def __call__(self, *exc_details):
pass


def test_dont_reraise_RuntimeError(self):
# https://bugs.python.org/issue27122
class UniqueException(Exception): pass
class UniqueRuntimeError(RuntimeError): pass

@contextmanager
def second():
try:
yield 1
except Exception as exc:
# Py2 compatible explicit exception chaining
new_exc = UniqueException("new exception")
new_exc.__cause__ = exc
raise new_exc

@contextmanager
def first():
try:
yield 1
except Exception as exc:
raise exc

# The UniqueRuntimeError should be caught by second()'s exception
# handler which chain raised a new UniqueException.
with self.assertRaises(UniqueException) as err_ctx:
with ExitStack() as es_ctx:
es_ctx.enter_context(second())
es_ctx.enter_context(first())
raise UniqueRuntimeError("please no infinite loop.")

exc = err_ctx.exception
self.assertIsInstance(exc, UniqueException)
self.assertIsInstance(exc.__cause__, UniqueRuntimeError)
if check_exception_chaining:
self.assertIs(exc.__context__, exc.__cause__)
self.assertIsNone(exc.__cause__.__context__)
self.assertIsNone(exc.__cause__.__cause__)


class TestRedirectStream:

Expand Down

0 comments on commit 2f4fd22

Please sign in to comment.