Merge pull request #7604 from bluetech/typing-disallow-any-generics

typing: set disallow_any_generics
This commit is contained in:
Ran Benita 2020-08-01 20:55:45 +03:00 committed by GitHub
commit be354b36f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 123 additions and 104 deletions

View File

@ -96,6 +96,7 @@ formats = sdist.tgz,bdist_wheel
[mypy]
mypy_path = src
check_untyped_defs = True
disallow_any_generics = True
ignore_missing_imports = True
no_implicit_optional = True
show_error_codes = True

View File

@ -613,7 +613,7 @@ class ExceptionInfo(Generic[_E]):
)
return fmt.repr_excinfo(self)
def match(self, regexp: "Union[str, Pattern]") -> "Literal[True]":
def match(self, regexp: "Union[str, Pattern[str]]") -> "Literal[True]":
"""Check whether the regular expression `regexp` matches the string
representation of the exception using :func:`python:re.search`.
@ -678,7 +678,7 @@ class FormattedExcinfo:
self,
source: "Source",
line_index: int = -1,
excinfo: Optional[ExceptionInfo] = None,
excinfo: Optional[ExceptionInfo[BaseException]] = None,
short: bool = False,
) -> List[str]:
"""Return formatted and marked up source lines."""
@ -703,7 +703,10 @@ class FormattedExcinfo:
return lines
def get_exconly(
self, excinfo: ExceptionInfo, indent: int = 4, markall: bool = False
self,
excinfo: ExceptionInfo[BaseException],
indent: int = 4,
markall: bool = False,
) -> List[str]:
lines = []
indentstr = " " * indent
@ -743,7 +746,9 @@ class FormattedExcinfo:
return None
def repr_traceback_entry(
self, entry: TracebackEntry, excinfo: Optional[ExceptionInfo] = None
self,
entry: TracebackEntry,
excinfo: Optional[ExceptionInfo[BaseException]] = None,
) -> "ReprEntry":
lines = [] # type: List[str]
style = entry._repr_style if entry._repr_style is not None else self.style
@ -785,7 +790,7 @@ class FormattedExcinfo:
path = np
return path
def repr_traceback(self, excinfo: ExceptionInfo) -> "ReprTraceback":
def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> "ReprTraceback":
traceback = excinfo.traceback
if self.tbfilter:
traceback = traceback.filter()
@ -850,12 +855,14 @@ class FormattedExcinfo:
return traceback, extraline
def repr_excinfo(self, excinfo: ExceptionInfo) -> "ExceptionChainRepr":
def repr_excinfo(
self, excinfo: ExceptionInfo[BaseException]
) -> "ExceptionChainRepr":
repr_chain = (
[]
) # type: List[Tuple[ReprTraceback, Optional[ReprFileLocation], Optional[str]]]
e = excinfo.value
excinfo_ = excinfo # type: Optional[ExceptionInfo]
e = excinfo.value # type: Optional[BaseException]
excinfo_ = excinfo # type: Optional[ExceptionInfo[BaseException]]
descr = None
seen = set() # type: Set[int]
while e is not None and id(e) not in seen:

View File

@ -710,7 +710,7 @@ class AssertionRewriter(ast.NodeVisitor):
node = nodes.pop()
for name, field in ast.iter_fields(node):
if isinstance(field, list):
new = [] # type: List
new = [] # type: List[ast.AST]
for i, child in enumerate(field):
if isinstance(child, ast.Assert):
# Transform assert.

View File

@ -181,7 +181,7 @@ class LFPluginCollWrapper:
self._collected_at_least_one_failure = False
@pytest.hookimpl(hookwrapper=True)
def pytest_make_collect_report(self, collector: nodes.Collector) -> Generator:
def pytest_make_collect_report(self, collector: nodes.Collector):
if isinstance(collector, Session):
out = yield
res = out.get_result() # type: CollectReport

View File

@ -3,7 +3,10 @@ import argparse
import functools
import sys
import types
from typing import Any
from typing import Callable
from typing import Generator
from typing import List
from typing import Tuple
from typing import Union
@ -91,7 +94,7 @@ class pytestPDB:
_pluginmanager = None # type: PytestPluginManager
_config = None # type: Config
_saved = [] # type: list
_saved = [] # type: List[Tuple[Callable[..., None], PytestPluginManager, Config]]
_recursive_debug = 0
_wrapped_pdb_cls = None
@ -274,7 +277,7 @@ class pytestPDB:
class PdbInvoke:
def pytest_exception_interact(
self, node: Node, call: "CallInfo", report: BaseReport
self, node: Node, call: "CallInfo[Any]", report: BaseReport
) -> None:
capman = node.config.pluginmanager.getplugin("capturemanager")
if capman:

View File

@ -94,8 +94,8 @@ _FixtureCachedResult = Union[
@attr.s(frozen=True)
class PseudoFixtureDef:
cached_result = attr.ib(type="_FixtureCachedResult")
class PseudoFixtureDef(Generic[_FixtureValue]):
cached_result = attr.ib(type="_FixtureCachedResult[_FixtureValue]")
scope = attr.ib(type="_Scope")
@ -141,7 +141,7 @@ def scopeproperty(name=None, doc=None):
return decoratescope
def get_scope_package(node, fixturedef: "FixtureDef"):
def get_scope_package(node, fixturedef: "FixtureDef[object]"):
import pytest
cls = pytest.Package
@ -397,7 +397,7 @@ class FuncFixtureInfo:
# definitions.
initialnames = attr.ib(type=Tuple[str, ...])
names_closure = attr.ib(type=List[str])
name2fixturedefs = attr.ib(type=Dict[str, Sequence["FixtureDef"]])
name2fixturedefs = attr.ib(type=Dict[str, Sequence["FixtureDef[Any]"]])
def prune_dependency_tree(self) -> None:
"""Recompute names_closure from initialnames and name2fixturedefs.
@ -441,7 +441,7 @@ class FixtureRequest:
self.fixturename = None # type: Optional[str]
#: Scope string, one of "function", "class", "module", "session".
self.scope = "function" # type: _Scope
self._fixture_defs = {} # type: Dict[str, FixtureDef]
self._fixture_defs = {} # type: Dict[str, FixtureDef[Any]]
fixtureinfo = pyfuncitem._fixtureinfo # type: FuncFixtureInfo
self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy()
self._arg2index = {} # type: Dict[str, int]
@ -467,7 +467,7 @@ class FixtureRequest:
"""Underlying collection node (depends on current request scope)."""
return self._getscopeitem(self.scope)
def _getnextfixturedef(self, argname: str) -> "FixtureDef":
def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]":
fixturedefs = self._arg2fixturedefs.get(argname, None)
if fixturedefs is None:
# We arrive here because of a dynamic call to
@ -586,7 +586,7 @@ class FixtureRequest:
def _get_active_fixturedef(
self, argname: str
) -> Union["FixtureDef", PseudoFixtureDef]:
) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]:
try:
return self._fixture_defs[argname]
except KeyError:
@ -604,9 +604,9 @@ class FixtureRequest:
self._fixture_defs[argname] = fixturedef
return fixturedef
def _get_fixturestack(self) -> List["FixtureDef"]:
def _get_fixturestack(self) -> List["FixtureDef[Any]"]:
current = self
values = [] # type: List[FixtureDef]
values = [] # type: List[FixtureDef[Any]]
while 1:
fixturedef = getattr(current, "_fixturedef", None)
if fixturedef is None:
@ -616,7 +616,7 @@ class FixtureRequest:
assert isinstance(current, SubRequest)
current = current._parent_request
def _compute_fixture_value(self, fixturedef: "FixtureDef") -> None:
def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None:
"""Create a SubRequest based on "self" and call the execute method
of the given FixtureDef object.
@ -689,7 +689,7 @@ class FixtureRequest:
self._schedule_finalizers(fixturedef, subrequest)
def _schedule_finalizers(
self, fixturedef: "FixtureDef", subrequest: "SubRequest"
self, fixturedef: "FixtureDef[object]", subrequest: "SubRequest"
) -> None:
# If fixture function failed it might have registered finalizers.
self.session._setupstate.addfinalizer(
@ -751,7 +751,7 @@ class SubRequest(FixtureRequest):
scope: "_Scope",
param,
param_index: int,
fixturedef: "FixtureDef",
fixturedef: "FixtureDef[object]",
) -> None:
self._parent_request = request
self.fixturename = fixturedef.argname
@ -773,7 +773,7 @@ class SubRequest(FixtureRequest):
self._fixturedef.addfinalizer(finalizer)
def _schedule_finalizers(
self, fixturedef: "FixtureDef", subrequest: "SubRequest"
self, fixturedef: "FixtureDef[object]", subrequest: "SubRequest"
) -> None:
# If the executing fixturedef was not explicitly requested in the argument list (via
# getfixturevalue inside the fixture call) then ensure this fixture def will be finished
@ -1456,8 +1456,8 @@ class FixtureManager:
def __init__(self, session: "Session") -> None:
self.session = session
self.config = session.config # type: Config
self._arg2fixturedefs = {} # type: Dict[str, List[FixtureDef]]
self._holderobjseen = set() # type: Set
self._arg2fixturedefs = {} # type: Dict[str, List[FixtureDef[Any]]]
self._holderobjseen = set() # type: Set[object]
self._nodeid_and_autousenames = [
("", self.config.getini("usefixtures"))
] # type: List[Tuple[str, List[str]]]
@ -1534,7 +1534,7 @@ class FixtureManager:
def getfixtureclosure(
self, fixturenames: Tuple[str, ...], parentnode, ignore_args: Sequence[str] = ()
) -> Tuple[Tuple[str, ...], List[str], Dict[str, Sequence[FixtureDef]]]:
) -> Tuple[Tuple[str, ...], List[str], Dict[str, Sequence[FixtureDef[Any]]]]:
# Collect the closure of all fixtures, starting with the given
# fixturenames as the initial set. As we have to visit all
# factory definitions anyway, we also return an arg2fixturedefs
@ -1557,7 +1557,7 @@ class FixtureManager:
# need to return it as well, so save this.
initialnames = tuple(fixturenames_closure)
arg2fixturedefs = {} # type: Dict[str, Sequence[FixtureDef]]
arg2fixturedefs = {} # type: Dict[str, Sequence[FixtureDef[Any]]]
lastlen = -1
while lastlen != len(fixturenames_closure):
lastlen = len(fixturenames_closure)
@ -1677,7 +1677,7 @@ class FixtureManager:
def getfixturedefs(
self, argname: str, nodeid: str
) -> Optional[Sequence[FixtureDef]]:
) -> Optional[Sequence[FixtureDef[Any]]]:
"""Get a list of fixtures which are applicable to the given node id.
:param str argname: Name of the fixture to search for.
@ -1691,8 +1691,8 @@ class FixtureManager:
return tuple(self._matchfactories(fixturedefs, nodeid))
def _matchfactories(
self, fixturedefs: Iterable[FixtureDef], nodeid: str
) -> Iterator[FixtureDef]:
self, fixturedefs: Iterable[FixtureDef[Any]], nodeid: str
) -> Iterator[FixtureDef[Any]]:
from _pytest import nodes
for fixturedef in fixturedefs:

View File

@ -533,7 +533,7 @@ def pytest_report_from_serializable(
@hookspec(firstresult=True)
def pytest_fixture_setup(
fixturedef: "FixtureDef", request: "SubRequest"
fixturedef: "FixtureDef[Any]", request: "SubRequest"
) -> Optional[object]:
"""Perform fixture setup execution.
@ -549,7 +549,7 @@ def pytest_fixture_setup(
def pytest_fixture_post_finalizer(
fixturedef: "FixtureDef", request: "SubRequest"
fixturedef: "FixtureDef[Any]", request: "SubRequest"
) -> None:
"""Called after fixture teardown, but before the cache is cleared, so
the fixture result ``fixturedef.cached_result`` is still available (not
@ -826,7 +826,7 @@ def pytest_keyboard_interrupt(
def pytest_exception_interact(
node: Union["Item", "Collector"],
call: "CallInfo[object]",
call: "CallInfo[Any]",
report: Union["CollectReport", "TestReport"],
) -> None:
"""Called when an exception was raised which can potentially be

View File

@ -404,7 +404,7 @@ class Failed(Exception):
@attr.s
class _bestrelpath_cache(dict):
class _bestrelpath_cache(Dict[py.path.local, str]):
path = attr.ib(type=py.path.local)
def __missing__(self, path: py.path.local) -> str:

View File

@ -5,6 +5,7 @@ import warnings
from typing import Any
from typing import Callable
from typing import Iterable
from typing import Iterator
from typing import List
from typing import Mapping
from typing import NamedTuple
@ -30,6 +31,8 @@ from _pytest.warning_types import PytestUnknownMarkWarning
if TYPE_CHECKING:
from typing import Type
from ..nodes import Node
EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
@ -521,13 +524,14 @@ class MarkGenerator:
MARK_GEN = MarkGenerator()
class NodeKeywords(collections.abc.MutableMapping):
def __init__(self, node):
# TODO(py36): inherit from typing.MutableMapping[str, Any].
class NodeKeywords(collections.abc.MutableMapping): # type: ignore[type-arg]
def __init__(self, node: "Node") -> None:
self.node = node
self.parent = node.parent
self._markers = {node.name: True}
def __getitem__(self, key):
def __getitem__(self, key: str) -> Any:
try:
return self._markers[key]
except KeyError:
@ -535,17 +539,17 @@ class NodeKeywords(collections.abc.MutableMapping):
raise
return self.parent.keywords[key]
def __setitem__(self, key, value):
def __setitem__(self, key: str, value: Any) -> None:
self._markers[key] = value
def __delitem__(self, key):
def __delitem__(self, key: str) -> None:
raise ValueError("cannot delete key in keywords dict")
def __iter__(self):
def __iter__(self) -> Iterator[str]:
seen = self._seen()
return iter(seen)
def _seen(self):
def _seen(self) -> Set[str]:
seen = set(self._markers)
if self.parent is not None:
seen.update(self.parent.keywords)

View File

@ -1,6 +1,7 @@
import os
import warnings
from functools import lru_cache
from typing import Any
from typing import Callable
from typing import Dict
from typing import Iterable
@ -167,7 +168,7 @@ class Node(metaclass=NodeMeta):
self.extra_keyword_matches = set() # type: Set[str]
# Used for storing artificial fixturedefs for direct parametrization.
self._name2pseudofixturedef = {} # type: Dict[str, FixtureDef]
self._name2pseudofixturedef = {} # type: Dict[str, FixtureDef[Any]]
if nodeid is not None:
assert "::()" not in nodeid
@ -354,7 +355,7 @@ class Node(metaclass=NodeMeta):
assert current is None or isinstance(current, cls)
return current
def _prunetraceback(self, excinfo):
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
pass
def _repr_failure_py(
@ -479,7 +480,7 @@ class Collector(Node):
return self._repr_failure_py(excinfo, style=tbstyle)
def _prunetraceback(self, excinfo):
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
if hasattr(self, "fspath"):
traceback = excinfo.traceback
ntraceback = traceback.cut(path=self.fspath)

View File

@ -83,7 +83,7 @@ class Exit(Exception):
# Elaborate hack to work around https://github.com/python/mypy/issues/2087.
# Ideally would just be `exit.Exception = Exit` etc.
_F = TypeVar("_F", bound=Callable)
_F = TypeVar("_F", bound=Callable[..., object])
_ET = TypeVar("_ET", bound="Type[BaseException]")

View File

@ -1179,7 +1179,7 @@ class Metafunc:
def _find_parametrized_scope(
argnames: typing.Sequence[str],
arg2fixturedefs: Mapping[str, typing.Sequence[fixtures.FixtureDef]],
arg2fixturedefs: Mapping[str, typing.Sequence[fixtures.FixtureDef[object]]],
indirect: Union[bool, typing.Sequence[str]],
) -> "fixtures._Scope":
"""Find the most appropriate scope for a parametrized call based on its arguments.
@ -1578,7 +1578,7 @@ class Function(PyobjMixin, nodes.Item):
self.obj = self._getobj()
self._request._fillfixtures()
def _prunetraceback(self, excinfo: ExceptionInfo) -> None:
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
if hasattr(self, "_obj") and not self.config.getoption("fulltrace", False):
code = _pytest._code.Code(get_real_func(self.obj))
path, firstlineno = code.path, code.firstlineno

View File

@ -526,7 +526,7 @@ _E = TypeVar("_E", bound=BaseException)
def raises(
expected_exception: Union["Type[_E]", Tuple["Type[_E]", ...]],
*,
match: "Optional[Union[str, Pattern]]" = ...
match: "Optional[Union[str, Pattern[str]]]" = ...
) -> "RaisesContext[_E]":
... # pragma: no cover
@ -534,7 +534,7 @@ def raises(
@overload # noqa: F811
def raises( # noqa: F811
expected_exception: Union["Type[_E]", Tuple["Type[_E]", ...]],
func: Callable,
func: Callable[..., Any],
*args: Any,
**kwargs: Any
) -> _pytest._code.ExceptionInfo[_E]:
@ -670,7 +670,7 @@ def raises( # noqa: F811
message = "DID NOT RAISE {}".format(expected_exception)
if not args:
match = kwargs.pop("match", None)
match = kwargs.pop("match", None) # type: Optional[Union[str, Pattern[str]]]
if kwargs:
msg = "Unexpected keyword arguments passed to pytest.raises: "
msg += ", ".join(sorted(kwargs))
@ -703,7 +703,7 @@ class RaisesContext(Generic[_E]):
self,
expected_exception: Union["Type[_E]", Tuple["Type[_E]", ...]],
message: str,
match_expr: Optional[Union[str, "Pattern"]] = None,
match_expr: Optional[Union[str, "Pattern[str]"]] = None,
) -> None:
self.expected_exception = expected_exception
self.message = message

View File

@ -40,7 +40,7 @@ def recwarn() -> Generator["WarningsRecorder", None, None]:
@overload
def deprecated_call(
*, match: Optional[Union[str, "Pattern"]] = ...
*, match: Optional[Union[str, "Pattern[str]"]] = ...
) -> "WarningsRecorder":
raise NotImplementedError()
@ -53,7 +53,7 @@ def deprecated_call( # noqa: F811
def deprecated_call( # noqa: F811
func: Optional[Callable] = None, *args: Any, **kwargs: Any
func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any
) -> Union["WarningsRecorder", Any]:
"""Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning``.
@ -87,7 +87,7 @@ def deprecated_call( # noqa: F811
def warns(
expected_warning: Optional[Union["Type[Warning]", Tuple["Type[Warning]", ...]]],
*,
match: "Optional[Union[str, Pattern]]" = ...
match: "Optional[Union[str, Pattern[str]]]" = ...
) -> "WarningsChecker":
raise NotImplementedError()
@ -105,7 +105,7 @@ def warns( # noqa: F811
def warns( # noqa: F811
expected_warning: Optional[Union["Type[Warning]", Tuple["Type[Warning]", ...]]],
*args: Any,
match: Optional[Union[str, "Pattern"]] = None,
match: Optional[Union[str, "Pattern[str]"]] = None,
**kwargs: Any
) -> Union["WarningsChecker", Any]:
r"""Assert that code raises a particular class of warning.
@ -234,7 +234,7 @@ class WarningsChecker(WarningsRecorder):
expected_warning: Optional[
Union["Type[Warning]", Tuple["Type[Warning]", ...]]
] = None,
match_expr: Optional[Union[str, "Pattern"]] = None,
match_expr: Optional[Union[str, "Pattern[str]"]] = None,
) -> None:
super().__init__()

View File

@ -514,7 +514,7 @@ def _report_kwargs_from_json(reportdict: Dict[str, Any]) -> Dict[str, Any]:
]
return ReprTraceback(**repr_traceback_dict)
def deserialize_repr_crash(repr_crash_dict: Optional[dict]):
def deserialize_repr_crash(repr_crash_dict: Optional[Dict[str, Any]]):
if repr_crash_dict is not None:
return ReprFileLocation(**repr_crash_dict)
else:

View File

@ -213,7 +213,7 @@ def call_and_report(
return report
def check_interactive_exception(call: "CallInfo", report: BaseReport) -> bool:
def check_interactive_exception(call: "CallInfo[object]", report: BaseReport) -> bool:
"""Check whether the call raised an exception that should be reported as
interactive."""
if call.excinfo is None:
@ -247,11 +247,11 @@ def call_runtest_hook(
)
_T = TypeVar("_T")
TResult = TypeVar("TResult", covariant=True)
@attr.s(repr=False)
class CallInfo(Generic[_T]):
class CallInfo(Generic[TResult]):
"""Result/Exception info a function invocation.
:param T result:
@ -269,7 +269,7 @@ class CallInfo(Generic[_T]):
The context of invocation: "setup", "call", "teardown", ...
"""
_result = attr.ib(type="Optional[_T]")
_result = attr.ib(type="Optional[TResult]")
excinfo = attr.ib(type=Optional[ExceptionInfo[BaseException]])
start = attr.ib(type=float)
stop = attr.ib(type=float)
@ -277,26 +277,26 @@ class CallInfo(Generic[_T]):
when = attr.ib(type="Literal['collect', 'setup', 'call', 'teardown']")
@property
def result(self) -> _T:
def result(self) -> TResult:
if self.excinfo is not None:
raise AttributeError("{!r} has no valid result".format(self))
# The cast is safe because an exception wasn't raised, hence
# _result has the expected function return type (which may be
# None, that's why a cast and not an assert).
return cast(_T, self._result)
return cast(TResult, self._result)
@classmethod
def from_call(
cls,
func: "Callable[[], _T]",
func: "Callable[[], TResult]",
when: "Literal['collect', 'setup', 'call', 'teardown']",
reraise: "Optional[Union[Type[BaseException], Tuple[Type[BaseException], ...]]]" = None,
) -> "CallInfo[_T]":
) -> "CallInfo[TResult]":
excinfo = None
start = timing.time()
precise_start = timing.perf_counter()
try:
result = func() # type: Optional[_T]
result = func() # type: Optional[TResult]
except BaseException:
excinfo = ExceptionInfo.from_current()
if reraise is not None and isinstance(excinfo.value, reraise):

View File

@ -29,7 +29,7 @@ def pytest_addoption(parser: Parser) -> None:
@pytest.hookimpl(hookwrapper=True)
def pytest_fixture_setup(
fixturedef: FixtureDef, request: SubRequest
fixturedef: FixtureDef[object], request: SubRequest
) -> Generator[None, None, None]:
yield
if request.config.option.setupshow:
@ -47,7 +47,7 @@ def pytest_fixture_setup(
_show_fixture_action(fixturedef, "SETUP")
def pytest_fixture_post_finalizer(fixturedef: FixtureDef) -> None:
def pytest_fixture_post_finalizer(fixturedef: FixtureDef[object]) -> None:
if fixturedef.cached_result is not None:
config = fixturedef._fixturemanager.config
if config.option.setupshow:
@ -56,7 +56,7 @@ def pytest_fixture_post_finalizer(fixturedef: FixtureDef) -> None:
del fixturedef.cached_param # type: ignore[attr-defined]
def _show_fixture_action(fixturedef: FixtureDef, msg: str) -> None:
def _show_fixture_action(fixturedef: FixtureDef[object], msg: str) -> None:
config = fixturedef._fixturemanager.config
capman = config.pluginmanager.getplugin("capturemanager")
if capman:

View File

@ -22,7 +22,7 @@ def pytest_addoption(parser: Parser) -> None:
@pytest.hookimpl(tryfirst=True)
def pytest_fixture_setup(
fixturedef: FixtureDef, request: SubRequest
fixturedef: FixtureDef[object], request: SubRequest
) -> Optional[object]:
# Will return a dummy fixture if the setuponly option is provided.
if request.config.option.setupplan:

View File

@ -319,7 +319,7 @@ class TerminalReporter:
self.stats = {} # type: Dict[str, List[Any]]
self._main_color = None # type: Optional[str]
self._known_types = None # type: Optional[List]
self._known_types = None # type: Optional[List[str]]
self.startdir = config.invocation_dir
if file is None:
file = sys.stdout
@ -469,7 +469,7 @@ class TerminalReporter:
def line(self, msg: str, **kw: bool) -> None:
self._tw.line(msg, **kw)
def _add_stats(self, category: str, items: Sequence) -> None:
def _add_stats(self, category: str, items: Sequence[Any]) -> None:
set_main_color = category not in self.stats
self.stats.setdefault(category, []).extend(items)
if set_main_color:

View File

@ -141,7 +141,7 @@ def _make_xunit_fixture(
class TestCaseFunction(Function):
nofuncargs = True
_excinfo = None # type: Optional[List[_pytest._code.ExceptionInfo]]
_excinfo = None # type: Optional[List[_pytest._code.ExceptionInfo[BaseException]]]
_testcase = None # type: Optional[unittest.TestCase]
def setup(self) -> None:
@ -279,7 +279,9 @@ class TestCaseFunction(Function):
finally:
delattr(self._testcase, self.name)
def _prunetraceback(self, excinfo: _pytest._code.ExceptionInfo) -> None:
def _prunetraceback(
self, excinfo: _pytest._code.ExceptionInfo[BaseException]
) -> None:
Function._prunetraceback(self, excinfo)
traceback = excinfo.traceback.filter(
lambda x: not x.frame.f_globals.get("__unittest")

View File

@ -144,7 +144,7 @@ class TestMetafunc:
scope = attr.ib()
fixtures_defs = cast(
Dict[str, Sequence[fixtures.FixtureDef]],
Dict[str, Sequence[fixtures.FixtureDef[object]]],
dict(
session_fix=[DummyFixtureDef("session")],
package_fix=[DummyFixtureDef("package")],

View File

@ -640,7 +640,8 @@ class TestAssert_reprcompare:
def test_Sequence(self) -> None:
# Test comparing with a Sequence subclass.
class TestSequence(collections.abc.MutableSequence):
# TODO(py36): Inherit from typing.MutableSequence[int].
class TestSequence(collections.abc.MutableSequence): # type: ignore[type-arg]
def __init__(self, iterable):
self.elements = list(iterable)

View File

@ -1564,66 +1564,66 @@ def tr() -> TerminalReporter:
# dict value, not the actual contents, so tuples of anything
# suffice
# Important statuses -- the highest priority of these always wins
("red", [("1 failed", {"bold": True, "red": True})], {"failed": (1,)}),
("red", [("1 failed", {"bold": True, "red": True})], {"failed": [1]}),
(
"red",
[
("1 failed", {"bold": True, "red": True}),
("1 passed", {"bold": False, "green": True}),
],
{"failed": (1,), "passed": (1,)},
{"failed": [1], "passed": [1]},
),
("red", [("1 error", {"bold": True, "red": True})], {"error": (1,)}),
("red", [("2 errors", {"bold": True, "red": True})], {"error": (1, 2)}),
("red", [("1 error", {"bold": True, "red": True})], {"error": [1]}),
("red", [("2 errors", {"bold": True, "red": True})], {"error": [1, 2]}),
(
"red",
[
("1 passed", {"bold": False, "green": True}),
("1 error", {"bold": True, "red": True}),
],
{"error": (1,), "passed": (1,)},
{"error": [1], "passed": [1]},
),
# (a status that's not known to the code)
("yellow", [("1 weird", {"bold": True, "yellow": True})], {"weird": (1,)}),
("yellow", [("1 weird", {"bold": True, "yellow": True})], {"weird": [1]}),
(
"yellow",
[
("1 passed", {"bold": False, "green": True}),
("1 weird", {"bold": True, "yellow": True}),
],
{"weird": (1,), "passed": (1,)},
{"weird": [1], "passed": [1]},
),
("yellow", [("1 warning", {"bold": True, "yellow": True})], {"warnings": (1,)}),
("yellow", [("1 warning", {"bold": True, "yellow": True})], {"warnings": [1]}),
(
"yellow",
[
("1 passed", {"bold": False, "green": True}),
("1 warning", {"bold": True, "yellow": True}),
],
{"warnings": (1,), "passed": (1,)},
{"warnings": [1], "passed": [1]},
),
(
"green",
[("5 passed", {"bold": True, "green": True})],
{"passed": (1, 2, 3, 4, 5)},
{"passed": [1, 2, 3, 4, 5]},
),
# "Boring" statuses. These have no effect on the color of the summary
# line. Thus, if *every* test has a boring status, the summary line stays
# at its default color, i.e. yellow, to warn the user that the test run
# produced no useful information
("yellow", [("1 skipped", {"bold": True, "yellow": True})], {"skipped": (1,)}),
("yellow", [("1 skipped", {"bold": True, "yellow": True})], {"skipped": [1]}),
(
"green",
[
("1 passed", {"bold": True, "green": True}),
("1 skipped", {"bold": False, "yellow": True}),
],
{"skipped": (1,), "passed": (1,)},
{"skipped": [1], "passed": [1]},
),
(
"yellow",
[("1 deselected", {"bold": True, "yellow": True})],
{"deselected": (1,)},
{"deselected": [1]},
),
(
"green",
@ -1631,34 +1631,34 @@ def tr() -> TerminalReporter:
("1 passed", {"bold": True, "green": True}),
("1 deselected", {"bold": False, "yellow": True}),
],
{"deselected": (1,), "passed": (1,)},
{"deselected": [1], "passed": [1]},
),
("yellow", [("1 xfailed", {"bold": True, "yellow": True})], {"xfailed": (1,)}),
("yellow", [("1 xfailed", {"bold": True, "yellow": True})], {"xfailed": [1]}),
(
"green",
[
("1 passed", {"bold": True, "green": True}),
("1 xfailed", {"bold": False, "yellow": True}),
],
{"xfailed": (1,), "passed": (1,)},
{"xfailed": [1], "passed": [1]},
),
("yellow", [("1 xpassed", {"bold": True, "yellow": True})], {"xpassed": (1,)}),
("yellow", [("1 xpassed", {"bold": True, "yellow": True})], {"xpassed": [1]}),
(
"yellow",
[
("1 passed", {"bold": False, "green": True}),
("1 xpassed", {"bold": True, "yellow": True}),
],
{"xpassed": (1,), "passed": (1,)},
{"xpassed": [1], "passed": [1]},
),
# Likewise if no tests were found at all
("yellow", [("no tests ran", {"yellow": True})], {}),
# Test the empty-key special case
("yellow", [("no tests ran", {"yellow": True})], {"": (1,)}),
("yellow", [("no tests ran", {"yellow": True})], {"": [1]}),
(
"green",
[("1 passed", {"bold": True, "green": True})],
{"": (1,), "passed": (1,)},
{"": [1], "passed": [1]},
),
# A couple more complex combinations
(
@ -1668,7 +1668,7 @@ def tr() -> TerminalReporter:
("2 passed", {"bold": False, "green": True}),
("3 xfailed", {"bold": False, "yellow": True}),
],
{"passed": (1, 2), "failed": (1,), "xfailed": (1, 2, 3)},
{"passed": [1, 2], "failed": [1], "xfailed": [1, 2, 3]},
),
(
"green",
@ -1679,10 +1679,10 @@ def tr() -> TerminalReporter:
("2 xfailed", {"bold": False, "yellow": True}),
],
{
"passed": (1,),
"skipped": (1, 2),
"deselected": (1, 2, 3),
"xfailed": (1, 2),
"passed": [1],
"skipped": [1, 2],
"deselected": [1, 2, 3],
"xfailed": [1, 2],
},
),
],
@ -1691,7 +1691,7 @@ def test_summary_stats(
tr: TerminalReporter,
exp_line: List[Tuple[str, Dict[str, bool]]],
exp_color: str,
stats_arg: Dict[str, List],
stats_arg: Dict[str, List[object]],
) -> None:
tr.stats = stats_arg