Use attr.s(auto_attribs=True) in more places
It's nicer to read without the attr.ib noise.
This commit is contained in:
parent
dced00e60f
commit
e5468681b0
|
@ -1,3 +1,4 @@
|
|||
import ast
|
||||
import inspect
|
||||
import re
|
||||
import sys
|
||||
|
@ -12,6 +13,7 @@ from types import FrameType
|
|||
from types import TracebackType
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import ClassVar
|
||||
from typing import Dict
|
||||
from typing import Generic
|
||||
from typing import Iterable
|
||||
|
@ -238,7 +240,9 @@ class TracebackEntry:
|
|||
def getfirstlinesource(self) -> int:
|
||||
return self.frame.code.firstlineno
|
||||
|
||||
def getsource(self, astcache=None) -> Optional["Source"]:
|
||||
def getsource(
|
||||
self, astcache: Optional[Dict[Union[str, Path], ast.AST]] = None
|
||||
) -> Optional["Source"]:
|
||||
"""Return failing source code."""
|
||||
# we use the passed in astcache to not reparse asttrees
|
||||
# within exception info printing
|
||||
|
@ -258,7 +262,7 @@ class TracebackEntry:
|
|||
except SyntaxError:
|
||||
end = self.lineno + 1
|
||||
else:
|
||||
if key is not None:
|
||||
if key is not None and astcache is not None:
|
||||
astcache[key] = astnode
|
||||
return source[start:end]
|
||||
|
||||
|
@ -435,15 +439,15 @@ E = TypeVar("E", bound=BaseException, covariant=True)
|
|||
|
||||
|
||||
@final
|
||||
@attr.s(repr=False, init=False)
|
||||
@attr.s(repr=False, init=False, auto_attribs=True)
|
||||
class ExceptionInfo(Generic[E]):
|
||||
"""Wraps sys.exc_info() objects and offers help for navigating the traceback."""
|
||||
|
||||
_assert_start_repr = "AssertionError('assert "
|
||||
_assert_start_repr: ClassVar = "AssertionError('assert "
|
||||
|
||||
_excinfo = attr.ib(type=Optional[Tuple[Type["E"], "E", TracebackType]])
|
||||
_striptext = attr.ib(type=str)
|
||||
_traceback = attr.ib(type=Optional[Traceback])
|
||||
_excinfo: Optional[Tuple[Type["E"], "E", TracebackType]]
|
||||
_striptext: str
|
||||
_traceback: Optional[Traceback]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -673,22 +677,24 @@ class ExceptionInfo(Generic[E]):
|
|||
return True
|
||||
|
||||
|
||||
@attr.s
|
||||
@attr.s(auto_attribs=True)
|
||||
class FormattedExcinfo:
|
||||
"""Presenting information about failing Functions and Generators."""
|
||||
|
||||
# for traceback entries
|
||||
flow_marker = ">"
|
||||
fail_marker = "E"
|
||||
flow_marker: ClassVar = ">"
|
||||
fail_marker: ClassVar = "E"
|
||||
|
||||
showlocals = attr.ib(type=bool, default=False)
|
||||
style = attr.ib(type="_TracebackStyle", default="long")
|
||||
abspath = attr.ib(type=bool, default=True)
|
||||
tbfilter = attr.ib(type=bool, default=True)
|
||||
funcargs = attr.ib(type=bool, default=False)
|
||||
truncate_locals = attr.ib(type=bool, default=True)
|
||||
chain = attr.ib(type=bool, default=True)
|
||||
astcache = attr.ib(default=attr.Factory(dict), init=False, repr=False)
|
||||
showlocals: bool = False
|
||||
style: "_TracebackStyle" = "long"
|
||||
abspath: bool = True
|
||||
tbfilter: bool = True
|
||||
funcargs: bool = False
|
||||
truncate_locals: bool = True
|
||||
chain: bool = True
|
||||
astcache: Dict[Union[str, Path], ast.AST] = attr.ib(
|
||||
factory=dict, init=False, repr=False
|
||||
)
|
||||
|
||||
def _getindent(self, source: "Source") -> int:
|
||||
# Figure out indent for the given source.
|
||||
|
@ -951,7 +957,7 @@ class FormattedExcinfo:
|
|||
return ExceptionChainRepr(repr_chain)
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class TerminalRepr:
|
||||
def __str__(self) -> str:
|
||||
# FYI this is called from pytest-xdist's serialization of exception
|
||||
|
@ -987,13 +993,9 @@ class ExceptionRepr(TerminalRepr):
|
|||
tw.line(content)
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class ExceptionChainRepr(ExceptionRepr):
|
||||
chain = attr.ib(
|
||||
type=Sequence[
|
||||
Tuple["ReprTraceback", Optional["ReprFileLocation"], Optional[str]]
|
||||
]
|
||||
)
|
||||
chain: Sequence[Tuple["ReprTraceback", Optional["ReprFileLocation"], Optional[str]]]
|
||||
|
||||
def __attrs_post_init__(self) -> None:
|
||||
super().__attrs_post_init__()
|
||||
|
@ -1011,23 +1013,23 @@ class ExceptionChainRepr(ExceptionRepr):
|
|||
super().toterminal(tw)
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class ReprExceptionInfo(ExceptionRepr):
|
||||
reprtraceback = attr.ib(type="ReprTraceback")
|
||||
reprcrash = attr.ib(type="ReprFileLocation")
|
||||
reprtraceback: "ReprTraceback"
|
||||
reprcrash: "ReprFileLocation"
|
||||
|
||||
def toterminal(self, tw: TerminalWriter) -> None:
|
||||
self.reprtraceback.toterminal(tw)
|
||||
super().toterminal(tw)
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class ReprTraceback(TerminalRepr):
|
||||
reprentries = attr.ib(type=Sequence[Union["ReprEntry", "ReprEntryNative"]])
|
||||
extraline = attr.ib(type=Optional[str])
|
||||
style = attr.ib(type="_TracebackStyle")
|
||||
reprentries: Sequence[Union["ReprEntry", "ReprEntryNative"]]
|
||||
extraline: Optional[str]
|
||||
style: "_TracebackStyle"
|
||||
|
||||
entrysep = "_ "
|
||||
entrysep: ClassVar = "_ "
|
||||
|
||||
def toterminal(self, tw: TerminalWriter) -> None:
|
||||
# The entries might have different styles.
|
||||
|
@ -1055,22 +1057,23 @@ class ReprTracebackNative(ReprTraceback):
|
|||
self.extraline = None
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class ReprEntryNative(TerminalRepr):
|
||||
lines = attr.ib(type=Sequence[str])
|
||||
style: "_TracebackStyle" = "native"
|
||||
lines: Sequence[str]
|
||||
|
||||
style: ClassVar["_TracebackStyle"] = "native"
|
||||
|
||||
def toterminal(self, tw: TerminalWriter) -> None:
|
||||
tw.write("".join(self.lines))
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class ReprEntry(TerminalRepr):
|
||||
lines = attr.ib(type=Sequence[str])
|
||||
reprfuncargs = attr.ib(type=Optional["ReprFuncArgs"])
|
||||
reprlocals = attr.ib(type=Optional["ReprLocals"])
|
||||
reprfileloc = attr.ib(type=Optional["ReprFileLocation"])
|
||||
style = attr.ib(type="_TracebackStyle")
|
||||
lines: Sequence[str]
|
||||
reprfuncargs: Optional["ReprFuncArgs"]
|
||||
reprlocals: Optional["ReprLocals"]
|
||||
reprfileloc: Optional["ReprFileLocation"]
|
||||
style: "_TracebackStyle"
|
||||
|
||||
def _write_entry_lines(self, tw: TerminalWriter) -> None:
|
||||
"""Write the source code portions of a list of traceback entries with syntax highlighting.
|
||||
|
@ -1144,11 +1147,11 @@ class ReprEntry(TerminalRepr):
|
|||
)
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class ReprFileLocation(TerminalRepr):
|
||||
path = attr.ib(type=str, converter=str)
|
||||
lineno = attr.ib(type=int)
|
||||
message = attr.ib(type=str)
|
||||
path: str = attr.ib(converter=str)
|
||||
lineno: int
|
||||
message: str
|
||||
|
||||
def toterminal(self, tw: TerminalWriter) -> None:
|
||||
# Filename and lineno output for each entry, using an output format
|
||||
|
@ -1161,18 +1164,18 @@ class ReprFileLocation(TerminalRepr):
|
|||
tw.line(f":{self.lineno}: {msg}")
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class ReprLocals(TerminalRepr):
|
||||
lines = attr.ib(type=Sequence[str])
|
||||
lines: Sequence[str]
|
||||
|
||||
def toterminal(self, tw: TerminalWriter, indent="") -> None:
|
||||
for line in self.lines:
|
||||
tw.line(indent + line)
|
||||
|
||||
|
||||
@attr.s(eq=False)
|
||||
@attr.s(eq=False, auto_attribs=True)
|
||||
class ReprFuncArgs(TerminalRepr):
|
||||
args = attr.ib(type=Sequence[Tuple[str, object]])
|
||||
args: Sequence[Tuple[str, object]]
|
||||
|
||||
def toterminal(self, tw: TerminalWriter) -> None:
|
||||
if self.args:
|
||||
|
|
|
@ -55,10 +55,10 @@ Signature: 8a477f597d28d172789f06886806bc55
|
|||
|
||||
|
||||
@final
|
||||
@attr.s(init=False)
|
||||
@attr.s(init=False, auto_attribs=True)
|
||||
class Cache:
|
||||
_cachedir = attr.ib(type=Path, repr=False)
|
||||
_config = attr.ib(type=Config, repr=False)
|
||||
_cachedir: Path = attr.ib(repr=False)
|
||||
_config: Config = attr.ib(repr=False)
|
||||
|
||||
# Sub-directory under cache-dir for directories created by `mkdir()`.
|
||||
_CACHE_PREFIX_DIRS = "d"
|
||||
|
|
|
@ -858,7 +858,7 @@ class Config:
|
|||
"""
|
||||
|
||||
@final
|
||||
@attr.s(frozen=True)
|
||||
@attr.s(frozen=True, auto_attribs=True)
|
||||
class InvocationParams:
|
||||
"""Holds parameters passed during :func:`pytest.main`.
|
||||
|
||||
|
@ -874,21 +874,12 @@ class Config:
|
|||
Plugins accessing ``InvocationParams`` must be aware of that.
|
||||
"""
|
||||
|
||||
args = attr.ib(type=Tuple[str, ...], converter=_args_converter)
|
||||
"""The command-line arguments as passed to :func:`pytest.main`.
|
||||
|
||||
:type: Tuple[str, ...]
|
||||
"""
|
||||
plugins = attr.ib(type=Optional[Sequence[Union[str, _PluggyPlugin]]])
|
||||
"""Extra plugins, might be `None`.
|
||||
|
||||
:type: Optional[Sequence[Union[str, plugin]]]
|
||||
"""
|
||||
dir = attr.ib(type=Path)
|
||||
"""The directory from which :func:`pytest.main` was invoked.
|
||||
|
||||
:type: pathlib.Path
|
||||
"""
|
||||
args: Tuple[str, ...] = attr.ib(converter=_args_converter)
|
||||
"""The command-line arguments as passed to :func:`pytest.main`."""
|
||||
plugins: Optional[Sequence[Union[str, _PluggyPlugin]]]
|
||||
"""Extra plugins, might be `None`."""
|
||||
dir: Path
|
||||
"""The directory from which :func:`pytest.main` was invoked."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
|
|
@ -393,16 +393,16 @@ def get_direct_param_fixture_func(request):
|
|||
return request.param
|
||||
|
||||
|
||||
@attr.s(slots=True)
|
||||
@attr.s(slots=True, auto_attribs=True)
|
||||
class FuncFixtureInfo:
|
||||
# Original function argument names.
|
||||
argnames = attr.ib(type=Tuple[str, ...])
|
||||
argnames: Tuple[str, ...]
|
||||
# Argnames that function immediately requires. These include argnames +
|
||||
# fixture names specified via usefixtures and via autouse=True in fixture
|
||||
# definitions.
|
||||
initialnames = attr.ib(type=Tuple[str, ...])
|
||||
names_closure = attr.ib(type=List[str])
|
||||
name2fixturedefs = attr.ib(type=Dict[str, Sequence["FixtureDef[Any]"]])
|
||||
initialnames: Tuple[str, ...]
|
||||
names_closure: List[str]
|
||||
name2fixturedefs: Dict[str, Sequence["FixtureDef[Any]"]]
|
||||
|
||||
def prune_dependency_tree(self) -> None:
|
||||
"""Recompute names_closure from initialnames and name2fixturedefs.
|
||||
|
@ -1187,11 +1187,11 @@ def wrap_function_to_error_out_if_called_directly(
|
|||
|
||||
|
||||
@final
|
||||
@attr.s(frozen=True)
|
||||
@attr.s(frozen=True, auto_attribs=True)
|
||||
class FixtureFunctionMarker:
|
||||
scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = attr.ib()
|
||||
scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]"
|
||||
params: Optional[Tuple[object, ...]] = attr.ib(converter=_params_converter)
|
||||
autouse: bool = attr.ib(default=False)
|
||||
autouse: bool = False
|
||||
ids: Union[
|
||||
Tuple[Union[None, str, float, int, bool], ...],
|
||||
Callable[[Any], Optional[object]],
|
||||
|
@ -1199,7 +1199,7 @@ class FixtureFunctionMarker:
|
|||
default=None,
|
||||
converter=_ensure_immutable_ids,
|
||||
)
|
||||
name: Optional[str] = attr.ib(default=None)
|
||||
name: Optional[str] = None
|
||||
|
||||
def __call__(self, function: FixtureFunction) -> FixtureFunction:
|
||||
if inspect.isclass(function):
|
||||
|
|
|
@ -442,9 +442,9 @@ class Failed(Exception):
|
|||
"""Signals a stop as failed test run."""
|
||||
|
||||
|
||||
@attr.s
|
||||
@attr.s(slots=True, auto_attribs=True)
|
||||
class _bestrelpath_cache(Dict[Path, str]):
|
||||
path = attr.ib(type=Path)
|
||||
path: Path
|
||||
|
||||
def __missing__(self, path: Path) -> str:
|
||||
r = bestrelpath(self.path, path)
|
||||
|
|
|
@ -133,7 +133,7 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
|
|||
return None
|
||||
|
||||
|
||||
@attr.s(slots=True)
|
||||
@attr.s(slots=True, auto_attribs=True)
|
||||
class KeywordMatcher:
|
||||
"""A matcher for keywords.
|
||||
|
||||
|
@ -148,7 +148,7 @@ class KeywordMatcher:
|
|||
any item, as well as names directly assigned to test functions.
|
||||
"""
|
||||
|
||||
_names = attr.ib(type=AbstractSet[str])
|
||||
_names: AbstractSet[str]
|
||||
|
||||
@classmethod
|
||||
def from_item(cls, item: "Item") -> "KeywordMatcher":
|
||||
|
@ -217,17 +217,17 @@ def deselect_by_keyword(items: "List[Item]", config: Config) -> None:
|
|||
items[:] = remaining
|
||||
|
||||
|
||||
@attr.s(slots=True)
|
||||
@attr.s(slots=True, auto_attribs=True)
|
||||
class MarkMatcher:
|
||||
"""A matcher for markers which are present.
|
||||
|
||||
Tries to match on any marker names, attached to the given colitem.
|
||||
"""
|
||||
|
||||
own_mark_names = attr.ib()
|
||||
own_mark_names: AbstractSet[str]
|
||||
|
||||
@classmethod
|
||||
def from_item(cls, item) -> "MarkMatcher":
|
||||
def from_item(cls, item: "Item") -> "MarkMatcher":
|
||||
mark_names = {mark.name for mark in item.iter_markers()}
|
||||
return cls(mark_names)
|
||||
|
||||
|
|
|
@ -47,11 +47,11 @@ class TokenType(enum.Enum):
|
|||
EOF = "end of input"
|
||||
|
||||
|
||||
@attr.s(frozen=True, slots=True)
|
||||
@attr.s(frozen=True, slots=True, auto_attribs=True)
|
||||
class Token:
|
||||
type = attr.ib(type=TokenType)
|
||||
value = attr.ib(type=str)
|
||||
pos = attr.ib(type=int)
|
||||
type: TokenType
|
||||
value: str
|
||||
pos: int
|
||||
|
||||
|
||||
class ParseError(Exception):
|
||||
|
|
|
@ -33,7 +33,6 @@ from typing import TYPE_CHECKING
|
|||
from typing import Union
|
||||
from weakref import WeakKeyDictionary
|
||||
|
||||
import attr
|
||||
from iniconfig import IniConfig
|
||||
from iniconfig import SectionWrapper
|
||||
|
||||
|
@ -1518,7 +1517,6 @@ class LineComp:
|
|||
|
||||
|
||||
@final
|
||||
@attr.s(repr=False, str=False, init=False)
|
||||
class Testdir:
|
||||
"""
|
||||
Similar to :class:`Pytester`, but this class works with legacy legacy_path objects instead.
|
||||
|
|
|
@ -157,11 +157,11 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool,
|
|||
return result, reason
|
||||
|
||||
|
||||
@attr.s(slots=True, frozen=True)
|
||||
@attr.s(slots=True, frozen=True, auto_attribs=True)
|
||||
class Skip:
|
||||
"""The result of evaluate_skip_marks()."""
|
||||
|
||||
reason = attr.ib(type=str, default="unconditional skip")
|
||||
reason: str = "unconditional skip"
|
||||
|
||||
|
||||
def evaluate_skip_marks(item: Item) -> Optional[Skip]:
|
||||
|
@ -192,14 +192,14 @@ def evaluate_skip_marks(item: Item) -> Optional[Skip]:
|
|||
return None
|
||||
|
||||
|
||||
@attr.s(slots=True, frozen=True)
|
||||
@attr.s(slots=True, frozen=True, auto_attribs=True)
|
||||
class Xfail:
|
||||
"""The result of evaluate_xfail_marks()."""
|
||||
|
||||
reason = attr.ib(type=str)
|
||||
run = attr.ib(type=bool)
|
||||
strict = attr.ib(type=bool)
|
||||
raises = attr.ib(type=Optional[Tuple[Type[BaseException], ...]])
|
||||
reason: str
|
||||
run: bool
|
||||
strict: bool
|
||||
raises: Optional[Tuple[Type[BaseException], ...]]
|
||||
|
||||
|
||||
def evaluate_xfail_marks(item: Item) -> Optional[Xfail]:
|
||||
|
|
|
@ -14,6 +14,7 @@ from pathlib import Path
|
|||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import cast
|
||||
from typing import ClassVar
|
||||
from typing import Dict
|
||||
from typing import Generator
|
||||
from typing import List
|
||||
|
@ -279,7 +280,7 @@ def pytest_report_teststatus(report: BaseReport) -> Tuple[str, str, str]:
|
|||
return outcome, letter, outcome.upper()
|
||||
|
||||
|
||||
@attr.s
|
||||
@attr.s(auto_attribs=True)
|
||||
class WarningReport:
|
||||
"""Simple structure to hold warnings information captured by ``pytest_warning_recorded``.
|
||||
|
||||
|
@ -291,10 +292,11 @@ class WarningReport:
|
|||
File system location of the source of the warning (see ``get_location``).
|
||||
"""
|
||||
|
||||
message = attr.ib(type=str)
|
||||
nodeid = attr.ib(type=Optional[str], default=None)
|
||||
fslocation = attr.ib(type=Optional[Tuple[str, int]], default=None)
|
||||
count_towards_summary = True
|
||||
message: str
|
||||
nodeid: Optional[str] = None
|
||||
fslocation: Optional[Tuple[str, int]] = None
|
||||
|
||||
count_towards_summary: ClassVar = True
|
||||
|
||||
def get_location(self, config: Config) -> Optional[str]:
|
||||
"""Return the more user-friendly information about the location of a warning, or None."""
|
||||
|
|
|
@ -158,12 +158,12 @@ class TempPathFactory:
|
|||
|
||||
|
||||
@final
|
||||
@attr.s(init=False)
|
||||
@attr.s(init=False, auto_attribs=True)
|
||||
class TempdirFactory:
|
||||
"""Backward compatibility wrapper that implements :class:``_pytest.compat.LEGACY_PATH``
|
||||
for :class:``TempPathFactory``."""
|
||||
|
||||
_tmppath_factory = attr.ib(type=TempPathFactory)
|
||||
_tmppath_factory: TempPathFactory
|
||||
|
||||
def __init__(
|
||||
self, tmppath_factory: TempPathFactory, *, _ispytest: bool = False
|
||||
|
|
|
@ -116,7 +116,7 @@ _W = TypeVar("_W", bound=PytestWarning)
|
|||
|
||||
|
||||
@final
|
||||
@attr.s
|
||||
@attr.s(auto_attribs=True)
|
||||
class UnformattedWarning(Generic[_W]):
|
||||
"""A warning meant to be formatted during runtime.
|
||||
|
||||
|
@ -124,8 +124,8 @@ class UnformattedWarning(Generic[_W]):
|
|||
as opposed to a direct message.
|
||||
"""
|
||||
|
||||
category = attr.ib(type=Type["_W"])
|
||||
template = attr.ib(type=str)
|
||||
category: Type["_W"]
|
||||
template: str
|
||||
|
||||
def format(self, **kwargs: Any) -> _W:
|
||||
"""Return an instance of the warning category, formatted with given kwargs."""
|
||||
|
|
|
@ -455,7 +455,7 @@ class TestFormattedExcinfo:
|
|||
pass
|
||||
"""
|
||||
).strip()
|
||||
pr.flow_marker = "|"
|
||||
pr.flow_marker = "|" # type: ignore[misc]
|
||||
lines = pr.get_source(source, 0)
|
||||
assert len(lines) == 2
|
||||
assert lines[0] == "| def f(x):"
|
||||
|
|
Loading…
Reference in New Issue