Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/9509.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added :option:`--tb-hide-internal` option to hide pytest/pluggy internal frames even when :option:`--full-trace` is used.
4 changes: 4 additions & 0 deletions doc/en/how-to/output.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ with Ctrl+C to find out where the tests are *hanging*. By default no output
will be shown (because KeyboardInterrupt is caught by pytest). By using this
option you make sure a trace is shown.

The :option:`--tb-hide-internal` option can be used together with
:option:`--full-trace` to hide pytest/pluggy internal frames from the traceback,
showing the full user-written traceback without pytest's internal call stack.


Verbosity
--------------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions doc/en/reference/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3005,6 +3005,12 @@ Debugging

See :ref:`how-to-modifying-python-tb-printing` for more information.

.. option:: --tb-hide-internal

Hide pytest/pluggy internal frames even with :option:`--full-trace`.

See :ref:`how-to-modifying-python-tb-printing` for more information.

.. option:: --debug, --debug=DEBUG_FILE_NAME

Store internal tracing debug information in this log file.
Expand Down Expand Up @@ -3472,6 +3478,8 @@ All the command-line flags can also be obtained by running ``pytest --help``::
Controls how captured stdout/stderr/log is shown on
failed tests. Default: all.
--full-trace Don't cut any tracebacks (default is to cut)
--tb-hide-internal Hide pytest/pluggy internal frames even with --full-
trace
--color=color Color terminal output (yes/no/auto)
--code-highlight={yes,no}
Whether code should be highlighted (only if --color
Expand Down
9 changes: 8 additions & 1 deletion src/_pytest/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import _pytest._code
from _pytest._code import getfslineno
from _pytest._code.code import ExceptionInfo
from _pytest._code.code import filter_traceback
from _pytest._code.code import TerminalRepr
from _pytest._code.code import Traceback
from _pytest._code.code import TracebackStyle
Expand Down Expand Up @@ -415,7 +416,13 @@ def _repr_failure_py(
tbfilter: bool | Callable[[ExceptionInfo[BaseException]], Traceback]
if self.config.getoption("fulltrace", False):
style = "long"
tbfilter = False
if self.config.getoption("tb_hide_internal", False):

def tbfilter(excinfo: ExceptionInfo[BaseException]) -> Traceback:
return excinfo.traceback.filter(filter_traceback)

else:
tbfilter = False
else:
tbfilter = self._traceback_filter
if style == "auto":
Expand Down
6 changes: 6 additions & 0 deletions src/_pytest/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ def pytest_addoption(parser: Parser) -> None:
default=False,
help="Don't cut any tracebacks (default is to cut)",
)
group.addoption(
"--tb-hide-internal",
action="store_true",
default=False,
help="Hide pytest/pluggy internal frames even with --full-trace",
)
group.addoption(
"--color",
metavar="color",
Expand Down
33 changes: 33 additions & 0 deletions testing/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,39 @@ def test_interrupt_me():
)
result.stdout.fnmatch_lines(["*KeyboardInterrupt*"])

@pytest.mark.parametrize(
("extra_args", "expect_internal"),
[
(("--fulltrace",), True),
(("--fulltrace", "--tb-hide-internal"), False),
],
)
def test_fulltrace_hide_internal(
self,
pytester: Pytester,
extra_args: tuple[str, ...],
expect_internal: bool,
) -> None:
pytester.makepyfile(
"""
def helper():
assert False

def test_fail():
helper()
"""
)
result = pytester.runpytest(*extra_args)
assert result.ret == 1
if expect_internal:
result.stdout.fnmatch_lines(["*/pluggy/*.py*"])
result.stdout.fnmatch_lines(["*/_pytest/runner.py*"])
else:
result.stdout.no_fnmatch_line("*/pluggy/*.py*")
result.stdout.no_fnmatch_line("*/_pytest/runner.py*")
# Ensure the user frames are still shown.
result.stdout.fnmatch_lines(["> helper()", "> assert False"])

def test_keyboard_in_sessionstart(self, pytester: Pytester) -> None:
pytester.makeconftest(
"""
Expand Down