Skip to content

Commit

Permalink
Support PEP-415's Exception.__suppress_context__
Browse files Browse the repository at this point in the history
PEP-415 states that `exception.__context__` should be suppressed
in traceback outputs, if `exception.__suppress_context__` is
`True`.

Now if a ``raise exception from None`` is caught by pytest,
pytest will no longer chain the context in the test report.

The algorithm in `FormattedExcinfo` now better matches the one
in `traceback.TracebackException`.

`Exception.__suppress_context__` is available in all of the
versions of Python 3 that are supported by pytest.

Fixes pytest-dev#2631.
  • Loading branch information
jmoldow committed Jul 29, 2017
1 parent 768edde commit 2e61f70
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ John Towler
Jon Sonesen
Jonas Obrist
Jordan Guymon
Jordan Moldow
Joshua Bronson
Jurko Gospodnetić
Justyna Janczyszyn
Expand Down
2 changes: 1 addition & 1 deletion _pytest/_code/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ def repr_excinfo(self, excinfo):
e = e.__cause__
excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
descr = 'The above exception was the direct cause of the following exception:'
elif e.__context__ is not None:
elif (e.__context__ is not None and not e.__suppress_context__):
e = e.__context__
excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
descr = 'During handling of the above exception, another exception occurred:'
Expand Down
4 changes: 4 additions & 0 deletions changelog/2631.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Added support for `PEP-415's <https://www.python.org/dev/peps/pep-0415/>`_
``Exception.__suppress_context__``. Now if a ``raise exception from None`` is
caught by pytest, pytest will no longer chain the context in the test report.
The behavior now matches Python's traceback behavior.
30 changes: 30 additions & 0 deletions testing/code/test_excinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,36 @@ def h():
assert line.endswith('mod.py')
assert tw.lines[47] == ":15: AttributeError"

@pytest.mark.skipif("sys.version_info[0] < 3")
def test_exc_repr_with_raise_from_none_chain_suppression(self, importasmod):
mod = importasmod("""
def f():
try:
g()
except Exception:
raise AttributeError() from None
def g():
raise ValueError()
""")
excinfo = pytest.raises(AttributeError, mod.f)
r = excinfo.getrepr(style="long")
tw = TWMock()
r.toterminal(tw)
for line in tw.lines:
print(line)
assert tw.lines[0] == ""
assert tw.lines[1] == " def f():"
assert tw.lines[2] == " try:"
assert tw.lines[3] == " g()"
assert tw.lines[4] == " except Exception:"
assert tw.lines[5] == "> raise AttributeError() from None"
assert tw.lines[6] == "E AttributeError"
assert tw.lines[7] == ""
line = tw.get_write_msg(8)
assert line.endswith('mod.py')
assert tw.lines[9] == ":6: AttributeError"
assert len(tw.lines) == 10

@pytest.mark.skipif("sys.version_info[0] < 3")
@pytest.mark.parametrize('reason, description', [
('cause', 'The above exception was the direct cause of the following exception:'),
Expand Down

0 comments on commit 2e61f70

Please sign in to comment.