diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index babac34f6..fd38b950c 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -975,18 +975,13 @@ class ReprExceptionInfo(ExceptionRepr): super().toterminal(tw) +@attr.s class ReprTraceback(TerminalRepr): - entrysep = "_ " + reprentries = attr.ib(type=Sequence[Union["ReprEntry", "ReprEntryNative"]]) + extraline = attr.ib(type=Optional[str]) + style = attr.ib(type="_TracebackStyle") - def __init__( - self, - reprentries: Sequence[Union["ReprEntry", "ReprEntryNative"]], - extraline: Optional[str], - style: "_TracebackStyle", - ) -> None: - self.reprentries = reprentries - self.extraline = extraline - self.style = style + entrysep = "_ " def toterminal(self, tw: TerminalWriter) -> None: # the entries might have different styles @@ -1105,11 +1100,11 @@ class ReprEntry(TerminalRepr): ) +@attr.s class ReprFileLocation(TerminalRepr): - def __init__(self, path, lineno: int, message: str) -> None: - self.path = str(path) - self.lineno = lineno - self.message = message + path = attr.ib(type=str, converter=str) + lineno = attr.ib(type=int) + message = attr.ib(type=str) def toterminal(self, tw: TerminalWriter) -> None: # filename and lineno output for each entry, diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 3ad67c224..38b028f48 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -6,6 +6,7 @@ from typing import Optional from typing import Tuple from typing import Union +import attr import py from _pytest._code.code import ExceptionChainRepr @@ -375,8 +376,8 @@ def _report_to_json(report): entry_data["data"][key] = value.__dict__.copy() return entry_data - def serialize_repr_traceback(reprtraceback): - result = reprtraceback.__dict__.copy() + def serialize_repr_traceback(reprtraceback: ReprTraceback): + result = attr.asdict(reprtraceback) result["reprentries"] = [ serialize_repr_entry(x) for x in reprtraceback.reprentries ] @@ -384,7 +385,7 @@ def _report_to_json(report): def serialize_repr_crash(reprcrash: Optional[ReprFileLocation]): if reprcrash is not None: - return reprcrash.__dict__.copy() + return attr.asdict(reprcrash) else: return None