code: make TracebackEntry immutable
TracebackEntry being mutable caught me by surprise and makes reasoning about the exception formatting code harder. Make it a proper value.
This commit is contained in:
parent
0a20452f78
commit
6f7f89f3c4
|
@ -49,6 +49,7 @@ from _pytest.pathlib import absolutepath
|
||||||
from _pytest.pathlib import bestrelpath
|
from _pytest.pathlib import bestrelpath
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from typing_extensions import Final
|
||||||
from typing_extensions import Literal
|
from typing_extensions import Literal
|
||||||
from typing_extensions import SupportsIndex
|
from typing_extensions import SupportsIndex
|
||||||
|
|
||||||
|
@ -197,18 +198,20 @@ class TracebackEntry:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
rawentry: TracebackType,
|
rawentry: TracebackType,
|
||||||
|
repr_style: Optional['Literal["short", "long"]'] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self._rawentry = rawentry
|
self._rawentry: "Final" = rawentry
|
||||||
self._repr_style: Optional['Literal["short", "long"]'] = None
|
self._repr_style: "Final" = repr_style
|
||||||
|
|
||||||
|
def with_repr_style(
|
||||||
|
self, repr_style: Optional['Literal["short", "long"]']
|
||||||
|
) -> "TracebackEntry":
|
||||||
|
return TracebackEntry(self._rawentry, repr_style)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lineno(self) -> int:
|
def lineno(self) -> int:
|
||||||
return self._rawentry.tb_lineno - 1
|
return self._rawentry.tb_lineno - 1
|
||||||
|
|
||||||
def set_repr_style(self, mode: "Literal['short', 'long']") -> None:
|
|
||||||
assert mode in ("short", "long")
|
|
||||||
self._repr_style = mode
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def frame(self) -> Frame:
|
def frame(self) -> Frame:
|
||||||
return Frame(self._rawentry.tb_frame)
|
return Frame(self._rawentry.tb_frame)
|
||||||
|
|
|
@ -35,6 +35,7 @@ from _pytest._code import filter_traceback
|
||||||
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._io import TerminalWriter
|
from _pytest._io import TerminalWriter
|
||||||
from _pytest._io.saferepr import saferepr
|
from _pytest._io.saferepr import saferepr
|
||||||
from _pytest.compat import ascii_escaped
|
from _pytest.compat import ascii_escaped
|
||||||
|
@ -1819,8 +1820,12 @@ class Function(PyobjMixin, nodes.Item):
|
||||||
# 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(excinfo.traceback) > 2:
|
||||||
for entry in excinfo.traceback[1:-1]:
|
excinfo.traceback = Traceback(
|
||||||
entry.set_repr_style("short")
|
entry
|
||||||
|
if i == 0 or i == len(excinfo.traceback) - 1
|
||||||
|
else entry.with_repr_style("short")
|
||||||
|
for i, entry in enumerate(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]
|
||||||
|
|
|
@ -1122,8 +1122,10 @@ raise ValueError()
|
||||||
)
|
)
|
||||||
excinfo = pytest.raises(ValueError, mod.f)
|
excinfo = pytest.raises(ValueError, mod.f)
|
||||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||||
excinfo.traceback[1].set_repr_style("short")
|
excinfo.traceback = _pytest._code.Traceback(
|
||||||
excinfo.traceback[2].set_repr_style("short")
|
entry if i not in (1, 2) else entry.with_repr_style("short")
|
||||||
|
for i, entry in enumerate(excinfo.traceback)
|
||||||
|
)
|
||||||
r = excinfo.getrepr(style="long")
|
r = excinfo.getrepr(style="long")
|
||||||
r.toterminal(tw_mock)
|
r.toterminal(tw_mock)
|
||||||
for line in tw_mock.lines:
|
for line in tw_mock.lines:
|
||||||
|
|
Loading…
Reference in New Issue