nodes: change _prunetraceback to return the new traceback instead of modifying excinfo

This makes it usable as a general function, and just more understandable
in general.
This commit is contained in:
Ran Benita 2023-04-13 13:48:44 +03:00
parent 6f7f89f3c4
commit fcada1ea47
3 changed files with 23 additions and 17 deletions

View File

@ -22,6 +22,7 @@ import _pytest._code
from _pytest._code import getfslineno from _pytest._code import getfslineno
from _pytest._code.code import ExceptionInfo from _pytest._code.code import ExceptionInfo
from _pytest._code.code import TerminalRepr from _pytest._code.code import TerminalRepr
from _pytest._code.code import Traceback
from _pytest.compat import cached_property from _pytest.compat import cached_property
from _pytest.compat import LEGACY_PATH from _pytest.compat import LEGACY_PATH
from _pytest.config import Config from _pytest.config import Config
@ -432,8 +433,8 @@ class Node(metaclass=NodeMeta):
assert current is None or isinstance(current, cls) assert current is None or isinstance(current, cls)
return current return current
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
pass return excinfo.traceback
def _repr_failure_py( def _repr_failure_py(
self, self,
@ -452,7 +453,7 @@ class Node(metaclass=NodeMeta):
if self.config.getoption("fulltrace", False): if self.config.getoption("fulltrace", False):
style = "long" style = "long"
else: else:
self._prunetraceback(excinfo) excinfo.traceback = self._traceback_filter(excinfo)
if style == "auto": if style == "auto":
style = "long" style = "long"
# XXX should excinfo.getrepr record all data and toterminal() process it? # XXX should excinfo.getrepr record all data and toterminal() process it?
@ -554,13 +555,14 @@ class Collector(Node):
return self._repr_failure_py(excinfo, style=tbstyle) return self._repr_failure_py(excinfo, style=tbstyle)
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
if hasattr(self, "path"): if hasattr(self, "path"):
traceback = excinfo.traceback traceback = excinfo.traceback
ntraceback = traceback.cut(path=self.path) ntraceback = traceback.cut(path=self.path)
if ntraceback == traceback: if ntraceback == traceback:
ntraceback = ntraceback.cut(excludepath=tracebackcutdir) ntraceback = ntraceback.cut(excludepath=tracebackcutdir)
excinfo.traceback = ntraceback.filter(excinfo) return excinfo.traceback.filter(excinfo)
return excinfo.traceback
def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[str]: def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[str]:

View File

@ -1802,7 +1802,7 @@ class Function(PyobjMixin, nodes.Item):
def setup(self) -> None: def setup(self) -> None:
self._request._fillfixtures() self._request._fillfixtures()
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
if hasattr(self, "_obj") and not self.config.getoption("fulltrace", False): if hasattr(self, "_obj") and not self.config.getoption("fulltrace", False):
code = _pytest._code.Code.from_function(get_real_func(self.obj)) code = _pytest._code.Code.from_function(get_real_func(self.obj))
path, firstlineno = code.path, code.firstlineno path, firstlineno = code.path, code.firstlineno
@ -1814,19 +1814,22 @@ class Function(PyobjMixin, nodes.Item):
ntraceback = ntraceback.filter(filter_traceback) ntraceback = ntraceback.filter(filter_traceback)
if not ntraceback: if not ntraceback:
ntraceback = traceback ntraceback = traceback
ntraceback = ntraceback.filter(excinfo)
excinfo.traceback = ntraceback.filter(excinfo)
# issue364: mark all but first and last frames to # issue364: mark all but first and last frames to
# only show a single-line message for each frame. # only show a single-line message for each frame.
if self.config.getoption("tbstyle", "auto") == "auto": if self.config.getoption("tbstyle", "auto") == "auto":
if len(excinfo.traceback) > 2: if len(ntraceback) > 2:
excinfo.traceback = Traceback( ntraceback = Traceback(
entry entry
if i == 0 or i == len(excinfo.traceback) - 1 if i == 0 or i == len(ntraceback) - 1
else entry.with_repr_style("short") else entry.with_repr_style("short")
for i, entry in enumerate(excinfo.traceback) for i, entry in enumerate(ntraceback)
) )
return ntraceback
return excinfo.traceback
# TODO: Type ignored -- breaks Liskov Substitution. # TODO: Type ignored -- breaks Liskov Substitution.
def repr_failure( # type: ignore[override] def repr_failure( # type: ignore[override]
self, self,

View File

@ -334,15 +334,16 @@ class TestCaseFunction(Function):
finally: finally:
delattr(self._testcase, self.name) delattr(self._testcase, self.name)
def _prunetraceback( def _traceback_filter(
self, excinfo: _pytest._code.ExceptionInfo[BaseException] self, excinfo: _pytest._code.ExceptionInfo[BaseException]
) -> None: ) -> _pytest._code.Traceback:
super()._prunetraceback(excinfo) traceback = super()._traceback_filter(excinfo)
traceback = excinfo.traceback.filter( ntraceback = traceback.filter(
lambda x: not x.frame.f_globals.get("__unittest"), lambda x: not x.frame.f_globals.get("__unittest"),
) )
if traceback: if not ntraceback:
excinfo.traceback = traceback ntraceback = traceback
return ntraceback
@hookimpl(tryfirst=True) @hookimpl(tryfirst=True)