Description
When two traceback frames come from the same filename and line number, pytest can keep a frame marked with __tracebackhide__ = True in an ExceptionGroup traceback.
This can happen whenever distinct traceback entries share the same source location but have different __tracebackhide__ values. Recursion provides a simple reproducer.
Minimal example
def fail(number):
__tracebackhide__ = number == 1
if number == 0:
raise ValueError("boom")
fail(number - 1)
def test_failure():
try:
fail(2)
except ValueError as error:
raise ExceptionGroup("failure", [error]) from None
Run:
pytest -q test_example.py
Actual result
The relevant part of the nested traceback contains the recursive line twice:
File "test_example.py", line 7, in fail
fail(number - 1)
File "test_example.py", line 7, in fail
fail(number - 1)
File "test_example.py", line 5, in fail
raise ValueError("boom")
ValueError: boom
Expected result
The calls have different __tracebackhide__ values:
fail(2) -> visible
fail(1) -> hidden
fail(0) -> raises ValueError
The fail(1) frame should be removed, so fail(number - 1) should appear only once. The equivalent traceback without the ExceptionGroup wrapper already behaves correctly.
Cause
_filter_tracebackexception() currently identifies filtered frames using (filename, line number). These values identify a source location, but not an individual occurrence in a traceback. A visible frame can therefore also retain a hidden frame from the same location.
This matching was added in #14649 for #14036. This report covers the remaining case where separate traceback frames share one source location.
Environment
- pytest
main at 28549a5f6b82bc916bb2ec5cb9fbfffe9b79fc66
- Python 3.12.13
- Red Hat Enterprise Linux 9.8
Description
When two traceback frames come from the same filename and line number, pytest can keep a frame marked with
__tracebackhide__ = Truein anExceptionGrouptraceback.This can happen whenever distinct traceback entries share the same source location but have different
__tracebackhide__values. Recursion provides a simple reproducer.Minimal example
Run:
pytest -q test_example.pyActual result
The relevant part of the nested traceback contains the recursive line twice:
Expected result
The calls have different
__tracebackhide__values:The
fail(1)frame should be removed, sofail(number - 1)should appear only once. The equivalent traceback without theExceptionGroupwrapper already behaves correctly.Cause
_filter_tracebackexception()currently identifies filtered frames using(filename, line number). These values identify a source location, but not an individual occurrence in a traceback. A visible frame can therefore also retain a hidden frame from the same location.This matching was added in #14649 for #14036. This report covers the remaining case where separate traceback frames share one source location.
Environment
mainat28549a5f6b82bc916bb2ec5cb9fbfffe9b79fc66