Support PEP-415's Exception.__suppress_context__
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 #2631.
This commit is contained in:
parent
768edde899
commit
2e61f702c0
1
AUTHORS
1
AUTHORS
|
@ -84,6 +84,7 @@ John Towler
|
||||||
Jon Sonesen
|
Jon Sonesen
|
||||||
Jonas Obrist
|
Jonas Obrist
|
||||||
Jordan Guymon
|
Jordan Guymon
|
||||||
|
Jordan Moldow
|
||||||
Joshua Bronson
|
Joshua Bronson
|
||||||
Jurko Gospodnetić
|
Jurko Gospodnetić
|
||||||
Justyna Janczyszyn
|
Justyna Janczyszyn
|
||||||
|
|
|
@ -679,7 +679,7 @@ class FormattedExcinfo(object):
|
||||||
e = e.__cause__
|
e = e.__cause__
|
||||||
excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
|
excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
|
||||||
descr = 'The above exception was the direct cause of the following exception:'
|
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__
|
e = e.__context__
|
||||||
excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
|
excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
|
||||||
descr = 'During handling of the above exception, another exception occurred:'
|
descr = 'During handling of the above exception, another exception occurred:'
|
||||||
|
|
|
@ -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.
|
|
@ -1095,6 +1095,36 @@ raise ValueError()
|
||||||
assert line.endswith('mod.py')
|
assert line.endswith('mod.py')
|
||||||
assert tw.lines[47] == ":15: AttributeError"
|
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.skipif("sys.version_info[0] < 3")
|
||||||
@pytest.mark.parametrize('reason, description', [
|
@pytest.mark.parametrize('reason, description', [
|
||||||
('cause', 'The above exception was the direct cause of the following exception:'),
|
('cause', 'The above exception was the direct cause of the following exception:'),
|
||||||
|
|
Loading…
Reference in New Issue