[pre-commit.ci] pre-commit autoupdate (#12115)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
Co-authored-by: Ran Benita <ran@unusedvar.com>
This commit is contained in:
pre-commit-ci[bot] 2024-03-13 15:30:18 +02:00 committed by GitHub
parent 14437788f0
commit c0532dda18
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
61 changed files with 185 additions and 212 deletions

View File

@ -1,6 +1,6 @@
repos: repos:
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.2.2" rev: "v0.3.2"
hooks: hooks:
- id: ruff - id: ruff
args: ["--fix"] args: ["--fix"]
@ -26,7 +26,7 @@ repos:
hooks: hooks:
- id: python-use-type-annotations - id: python-use-type-annotations
- repo: https://github.com/pre-commit/mirrors-mypy - repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0 rev: v1.9.0
hooks: hooks:
- id: mypy - id: mypy
files: ^(src/|testing/|scripts/) files: ^(src/|testing/|scripts/)

View File

@ -281,6 +281,7 @@ template = "changelog/_template.rst"
showcontent = true showcontent = true
[tool.mypy] [tool.mypy]
files = ["src", "testing", "scripts"]
mypy_path = ["src"] mypy_path = ["src"]
check_untyped_defs = true check_untyped_defs = true
disallow_any_generics = true disallow_any_generics = true
@ -293,3 +294,4 @@ warn_return_any = true
warn_unreachable = true warn_unreachable = true
warn_unused_configs = true warn_unused_configs = true
no_implicit_reexport = true no_implicit_reexport = true
warn_unused_ignores = true

View File

@ -8,6 +8,7 @@ our CHANGELOG) into Markdown (which is required by GitHub Releases).
Requires Python3.6+. Requires Python3.6+.
""" """
from pathlib import Path from pathlib import Path
import re import re
import sys import sys

View File

@ -13,6 +13,7 @@ After that, it will create a release using the `release` tox environment, and pu
**Token**: currently the token from the GitHub Actions is used, pushed with **Token**: currently the token from the GitHub Actions is used, pushed with
`pytest bot <pytestbot@gmail.com>` commit author. `pytest bot <pytestbot@gmail.com>` commit author.
""" """
import argparse import argparse
from pathlib import Path from pathlib import Path
import re import re

View File

@ -1,5 +1,6 @@
# mypy: disallow-untyped-defs # mypy: disallow-untyped-defs
"""Invoke development tasks.""" """Invoke development tasks."""
import argparse import argparse
import os import os
from pathlib import Path from pathlib import Path

View File

@ -7,4 +7,4 @@ except ImportError: # pragma: no cover
# broken installation, we don't even try # broken installation, we don't even try
# unknown only works because we do poor mans version compare # unknown only works because we do poor mans version compare
__version__ = "unknown" __version__ = "unknown"
version_tuple = (0, 0, "unknown") # type:ignore[assignment] version_tuple = (0, 0, "unknown")

View File

@ -279,9 +279,9 @@ class TracebackEntry:
Mostly for internal use. Mostly for internal use.
""" """
tbh: Union[ tbh: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]] = (
bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool] False
] = False )
for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals): for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals):
# in normal cases, f_locals and f_globals are dictionaries # in normal cases, f_locals and f_globals are dictionaries
# however via `exec(...)` / `eval(...)` they can be other types # however via `exec(...)` / `eval(...)` they can be other types
@ -378,12 +378,10 @@ class Traceback(List[TracebackEntry]):
return self return self
@overload @overload
def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: ...
...
@overload @overload
def __getitem__(self, key: slice) -> "Traceback": def __getitem__(self, key: slice) -> "Traceback": ...
...
def __getitem__( def __getitem__(
self, key: Union["SupportsIndex", slice] self, key: Union["SupportsIndex", slice]
@ -1051,13 +1049,13 @@ class FormattedExcinfo:
# full support for exception groups added to ExceptionInfo. # full support for exception groups added to ExceptionInfo.
# See https://github.com/pytest-dev/pytest/issues/9159 # See https://github.com/pytest-dev/pytest/issues/9159
if isinstance(e, BaseExceptionGroup): if isinstance(e, BaseExceptionGroup):
reprtraceback: Union[ reprtraceback: Union[ReprTracebackNative, ReprTraceback] = (
ReprTracebackNative, ReprTraceback ReprTracebackNative(
] = ReprTracebackNative( traceback.format_exception(
traceback.format_exception( type(excinfo_.value),
type(excinfo_.value), excinfo_.value,
excinfo_.value, excinfo_.traceback[0]._rawentry,
excinfo_.traceback[0]._rawentry, )
) )
) )
else: else:
@ -1348,7 +1346,7 @@ def getfslineno(obj: object) -> Tuple[Union[str, Path], int]:
# in 6ec13a2b9. It ("place_as") appears to be something very custom. # in 6ec13a2b9. It ("place_as") appears to be something very custom.
obj = get_real_func(obj) obj = get_real_func(obj)
if hasattr(obj, "place_as"): if hasattr(obj, "place_as"):
obj = obj.place_as # type: ignore[attr-defined] obj = obj.place_as
try: try:
code = Code.from_function(obj) code = Code.from_function(obj)

View File

@ -47,12 +47,10 @@ class Source:
__hash__ = None # type: ignore __hash__ = None # type: ignore
@overload @overload
def __getitem__(self, key: int) -> str: def __getitem__(self, key: int) -> str: ...
...
@overload @overload
def __getitem__(self, key: slice) -> "Source": def __getitem__(self, key: slice) -> "Source": ...
...
def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]: def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]:
if isinstance(key, int): if isinstance(key, int):

View File

@ -9,6 +9,7 @@ from typing import Optional
from typing import Sequence from typing import Sequence
from typing import TextIO from typing import TextIO
from ..compat import assert_never
from .wcwidth import wcswidth from .wcwidth import wcswidth
@ -209,6 +210,8 @@ class TerminalWriter:
from pygments.lexers.python import PythonLexer as Lexer from pygments.lexers.python import PythonLexer as Lexer
elif lexer == "diff": elif lexer == "diff":
from pygments.lexers.diff import DiffLexer as Lexer from pygments.lexers.diff import DiffLexer as Lexer
else:
assert_never(lexer)
from pygments import highlight from pygments import highlight
import pygments.util import pygments.util
except ImportError: except ImportError:

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""local path implementation.""" """local path implementation."""
from __future__ import annotations from __future__ import annotations
import atexit import atexit
@ -205,12 +206,10 @@ class Stat:
if TYPE_CHECKING: if TYPE_CHECKING:
@property @property
def size(self) -> int: def size(self) -> int: ...
...
@property @property
def mtime(self) -> float: def mtime(self) -> float: ...
...
def __getattr__(self, name: str) -> Any: def __getattr__(self, name: str) -> Any:
return getattr(self._osstatresult, "st_" + name) return getattr(self._osstatresult, "st_" + name)
@ -225,7 +224,7 @@ class Stat:
raise NotImplementedError("XXX win32") raise NotImplementedError("XXX win32")
import pwd import pwd
entry = error.checked_call(pwd.getpwuid, self.uid) # type:ignore[attr-defined] entry = error.checked_call(pwd.getpwuid, self.uid) # type:ignore[attr-defined,unused-ignore]
return entry[0] return entry[0]
@property @property
@ -235,7 +234,7 @@ class Stat:
raise NotImplementedError("XXX win32") raise NotImplementedError("XXX win32")
import grp import grp
entry = error.checked_call(grp.getgrgid, self.gid) # type:ignore[attr-defined] entry = error.checked_call(grp.getgrgid, self.gid) # type:ignore[attr-defined,unused-ignore]
return entry[0] return entry[0]
def isdir(self): def isdir(self):
@ -253,7 +252,7 @@ def getuserid(user):
import pwd import pwd
if not isinstance(user, int): if not isinstance(user, int):
user = pwd.getpwnam(user)[2] # type:ignore[attr-defined] user = pwd.getpwnam(user)[2] # type:ignore[attr-defined,unused-ignore]
return user return user
@ -261,7 +260,7 @@ def getgroupid(group):
import grp import grp
if not isinstance(group, int): if not isinstance(group, int):
group = grp.getgrnam(group)[2] # type:ignore[attr-defined] group = grp.getgrnam(group)[2] # type:ignore[attr-defined,unused-ignore]
return group return group
@ -318,7 +317,7 @@ class LocalPath:
def readlink(self) -> str: def readlink(self) -> str:
"""Return value of a symbolic link.""" """Return value of a symbolic link."""
# https://github.com/python/mypy/issues/12278 # https://github.com/python/mypy/issues/12278
return error.checked_call(os.readlink, self.strpath) # type: ignore[arg-type,return-value] return error.checked_call(os.readlink, self.strpath) # type: ignore[arg-type,return-value,unused-ignore]
def mklinkto(self, oldname): def mklinkto(self, oldname):
"""Posix style hard link to another name.""" """Posix style hard link to another name."""
@ -757,15 +756,11 @@ class LocalPath:
if ensure: if ensure:
self.dirpath().ensure(dir=1) self.dirpath().ensure(dir=1)
if encoding: if encoding:
# Using type ignore here because of this error:
# error: Argument 1 has incompatible type overloaded function;
# expected "Callable[[str, Any, Any], TextIOWrapper]" [arg-type]
# Which seems incorrect, given io.open supports the given argument types.
return error.checked_call( return error.checked_call(
io.open, io.open,
self.strpath, self.strpath,
mode, mode,
encoding=encoding, # type:ignore[arg-type] encoding=encoding,
) )
return error.checked_call(open, self.strpath, mode) return error.checked_call(open, self.strpath, mode)
@ -966,12 +961,10 @@ class LocalPath:
return p return p
@overload @overload
def stat(self, raising: Literal[True] = ...) -> Stat: def stat(self, raising: Literal[True] = ...) -> Stat: ...
...
@overload @overload
def stat(self, raising: Literal[False]) -> Stat | None: def stat(self, raising: Literal[False]) -> Stat | None: ...
...
def stat(self, raising: bool = True) -> Stat | None: def stat(self, raising: bool = True) -> Stat | None:
"""Return an os.stat() tuple.""" """Return an os.stat() tuple."""
@ -1277,13 +1270,7 @@ class LocalPath:
if rootdir is None: if rootdir is None:
rootdir = cls.get_temproot() rootdir = cls.get_temproot()
# Using type ignore here because of this error: path = error.checked_call(tempfile.mkdtemp, dir=str(rootdir))
# error: Argument 1 has incompatible type overloaded function; expected "Callable[[str], str]" [arg-type]
# Which seems incorrect, given tempfile.mkdtemp supports the given argument types.
path = error.checked_call(
tempfile.mkdtemp,
dir=str(rootdir), # type:ignore[arg-type]
)
return cls(path) return cls(path)
@classmethod @classmethod

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Support for presenting detailed information in failing assertions.""" """Support for presenting detailed information in failing assertions."""
import sys import sys
from typing import Any from typing import Any
from typing import Generator from typing import Generator

View File

@ -289,15 +289,13 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader)
else: else:
from importlib.abc import TraversableResources from importlib.abc import TraversableResources
def get_resource_reader(self, name: str) -> TraversableResources: # type: ignore def get_resource_reader(self, name: str) -> TraversableResources:
if sys.version_info < (3, 11): if sys.version_info < (3, 11):
from importlib.readers import FileReader from importlib.readers import FileReader
else: else:
from importlib.resources.readers import FileReader from importlib.resources.readers import FileReader
return FileReader( # type:ignore[no-any-return] return FileReader(types.SimpleNamespace(path=self._rewritten_names[name]))
types.SimpleNamespace(path=self._rewritten_names[name])
)
def _write_pyc_fp( def _write_pyc_fp(
@ -672,9 +670,9 @@ class AssertionRewriter(ast.NodeVisitor):
self.enable_assertion_pass_hook = False self.enable_assertion_pass_hook = False
self.source = source self.source = source
self.scope: tuple[ast.AST, ...] = () self.scope: tuple[ast.AST, ...] = ()
self.variables_overwrite: defaultdict[ self.variables_overwrite: defaultdict[tuple[ast.AST, ...], Dict[str, str]] = (
tuple[ast.AST, ...], Dict[str, str] defaultdict(dict)
] = defaultdict(dict) )
def run(self, mod: ast.Module) -> None: def run(self, mod: ast.Module) -> None:
"""Find all assert statements in *mod* and rewrite them.""" """Find all assert statements in *mod* and rewrite them."""
@ -975,7 +973,7 @@ class AssertionRewriter(ast.NodeVisitor):
# name if it's a local variable or _should_repr_global_name() # name if it's a local variable or _should_repr_global_name()
# thinks it's acceptable. # thinks it's acceptable.
locs = ast.Call(self.builtin("locals"), [], []) locs = ast.Call(self.builtin("locals"), [], [])
target_id = name.target.id # type: ignore[attr-defined] target_id = name.target.id
inlocs = ast.Compare(ast.Constant(target_id), [ast.In()], [locs]) inlocs = ast.Compare(ast.Constant(target_id), [ast.In()], [locs])
dorepr = self.helper("_should_repr_global_name", name) dorepr = self.helper("_should_repr_global_name", name)
test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) test = ast.BoolOp(ast.Or(), [inlocs, dorepr])

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Utilities for assertion debugging.""" """Utilities for assertion debugging."""
import collections.abc import collections.abc
import os import os
import pprint import pprint
@ -222,10 +223,9 @@ def assertrepr_compare(
except outcomes.Exit: except outcomes.Exit:
raise raise
except Exception: except Exception:
repr_crash = _pytest._code.ExceptionInfo.from_current()._getreprcrash()
explanation = [ explanation = [
"(pytest_assertion plugin: representation of details failed: {}.".format( f"(pytest_assertion plugin: representation of details failed: {repr_crash}.",
_pytest._code.ExceptionInfo.from_current()._getreprcrash()
),
" Probably an object has a faulty __repr__.)", " Probably an object has a faulty __repr__.)",
] ]

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Implementation of the cache provider.""" """Implementation of the cache provider."""
# This plugin was not named "cache" to avoid conflicts with the external # This plugin was not named "cache" to avoid conflicts with the external
# pytest-cache version. # pytest-cache version.
import dataclasses import dataclasses
@ -432,7 +433,7 @@ class NFPlugin:
return res return res
def _get_increasing_order(self, items: Iterable[nodes.Item]) -> List[nodes.Item]: def _get_increasing_order(self, items: Iterable[nodes.Item]) -> List[nodes.Item]:
return sorted(items, key=lambda item: item.path.stat().st_mtime, reverse=True) # type: ignore[no-any-return] return sorted(items, key=lambda item: item.path.stat().st_mtime, reverse=True)
def pytest_sessionfinish(self) -> None: def pytest_sessionfinish(self) -> None:
config = self.config config = self.config

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Per-test stdout/stderr capturing mechanism.""" """Per-test stdout/stderr capturing mechanism."""
import abc import abc
import collections import collections
import contextlib import contextlib
@ -105,17 +106,16 @@ def _windowsconsoleio_workaround(stream: TextIO) -> None:
return return
# Bail out if ``stream`` doesn't seem like a proper ``io`` stream (#2666). # Bail out if ``stream`` doesn't seem like a proper ``io`` stream (#2666).
if not hasattr(stream, "buffer"): # type: ignore[unreachable] if not hasattr(stream, "buffer"): # type: ignore[unreachable,unused-ignore]
return return
buffered = hasattr(stream.buffer, "raw") raw_stdout = stream.buffer.raw if hasattr(stream.buffer, "raw") else stream.buffer
raw_stdout = stream.buffer.raw if buffered else stream.buffer # type: ignore[attr-defined]
if not isinstance(raw_stdout, io._WindowsConsoleIO): # type: ignore[attr-defined] if not isinstance(raw_stdout, io._WindowsConsoleIO): # type: ignore[attr-defined,unused-ignore]
return return
def _reopen_stdio(f, mode): def _reopen_stdio(f, mode):
if not buffered and mode[0] == "w": if not hasattr(stream.buffer, "raw") and mode[0] == "w":
buffering = 0 buffering = 0
else: else:
buffering = -1 buffering = -1
@ -482,12 +482,9 @@ class FDCaptureBase(CaptureBase[AnyStr]):
self._state = "initialized" self._state = "initialized"
def __repr__(self) -> str: def __repr__(self) -> str:
return "<{} {} oldfd={} _state={!r} tmpfile={!r}>".format( return (
self.__class__.__name__, f"<{self.__class__.__name__} {self.targetfd} oldfd={self.targetfd_save} "
self.targetfd, f"_state={self._state!r} tmpfile={self.tmpfile!r}>"
self.targetfd_save,
self._state,
self.tmpfile,
) )
def _assert_state(self, op: str, states: Tuple[str, ...]) -> None: def _assert_state(self, op: str, states: Tuple[str, ...]) -> None:
@ -621,12 +618,9 @@ class MultiCapture(Generic[AnyStr]):
self.err: Optional[CaptureBase[AnyStr]] = err self.err: Optional[CaptureBase[AnyStr]] = err
def __repr__(self) -> str: def __repr__(self) -> str:
return "<MultiCapture out={!r} err={!r} in_={!r} _state={!r} _in_suspended={!r}>".format( return (
self.out, f"<MultiCapture out={self.out!r} err={self.err!r} in_={self.in_!r} "
self.err, f"_state={self._state!r} _in_suspended={self._in_suspended!r}>"
self.in_,
self._state,
self._in_suspended,
) )
def start_capturing(self) -> None: def start_capturing(self) -> None:
@ -735,8 +729,9 @@ class CaptureManager:
self._capture_fixture: Optional[CaptureFixture[Any]] = None self._capture_fixture: Optional[CaptureFixture[Any]] = None
def __repr__(self) -> str: def __repr__(self) -> str:
return "<CaptureManager _method={!r} _global_capturing={!r} _capture_fixture={!r}>".format( return (
self._method, self._global_capturing, self._capture_fixture f"<CaptureManager _method={self._method!r} _global_capturing={self._global_capturing!r} "
f"_capture_fixture={self._capture_fixture!r}>"
) )
def is_capturing(self) -> Union[str, bool]: def is_capturing(self) -> Union[str, bool]:

View File

@ -304,7 +304,7 @@ def get_user_id() -> int | None:
# mypy follows the version and platform checking expectation of PEP 484: # mypy follows the version and platform checking expectation of PEP 484:
# https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks # https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks
# Containment checks are too complex for mypy v1.5.0 and cause failure. # Containment checks are too complex for mypy v1.5.0 and cause failure.
if sys.platform == "win32" or sys.platform == "emscripten": # noqa: PLR1714 if sys.platform == "win32" or sys.platform == "emscripten":
# win32 does not have a getuid() function. # win32 does not have a getuid() function.
# Emscripten has a return 0 stub. # Emscripten has a return 0 stub.
return None return None

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Command line options, ini-file and conftest.py processing.""" """Command line options, ini-file and conftest.py processing."""
import argparse import argparse
import collections.abc import collections.abc
import copy import copy

View File

@ -426,8 +426,7 @@ class MyOptionParser(argparse.ArgumentParser):
msg = f"{self.prog}: error: {message}" msg = f"{self.prog}: error: {message}"
if hasattr(self._parser, "_config_source_hint"): if hasattr(self._parser, "_config_source_hint"):
# Type ignored because the attribute is set dynamically. msg = f"{msg} ({self._parser._config_source_hint})"
msg = f"{msg} ({self._parser._config_source_hint})" # type: ignore
raise UsageError(self.format_usage() + msg) raise UsageError(self.format_usage() + msg)

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Interactive debugging with PDB, the Python Debugger.""" """Interactive debugging with PDB, the Python Debugger."""
import argparse import argparse
import functools import functools
import sys import sys
@ -154,9 +155,7 @@ class pytestPDB:
def _get_pdb_wrapper_class(cls, pdb_cls, capman: Optional["CaptureManager"]): def _get_pdb_wrapper_class(cls, pdb_cls, capman: Optional["CaptureManager"]):
import _pytest.config import _pytest.config
# Type ignored because mypy doesn't support "dynamic" class PytestPdbWrapper(pdb_cls):
# inheritance like this.
class PytestPdbWrapper(pdb_cls): # type: ignore[valid-type,misc]
_pytest_capman = capman _pytest_capman = capman
_continued = False _continued = False

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Discover and run doctests in modules and test files.""" """Discover and run doctests in modules and test files."""
import bdb import bdb
from contextlib import contextmanager from contextlib import contextmanager
import functools import functools

View File

@ -447,7 +447,7 @@ class FixtureRequest(abc.ABC):
@property @property
def config(self) -> Config: def config(self) -> Config:
"""The pytest config object associated with this request.""" """The pytest config object associated with this request."""
return self._pyfuncitem.config # type: ignore[no-any-return] return self._pyfuncitem.config
@property @property
def function(self): def function(self):
@ -499,7 +499,7 @@ class FixtureRequest(abc.ABC):
@property @property
def session(self) -> "Session": def session(self) -> "Session":
"""Pytest session object.""" """Pytest session object."""
return self._pyfuncitem.session # type: ignore[no-any-return] return self._pyfuncitem.session
@abc.abstractmethod @abc.abstractmethod
def addfinalizer(self, finalizer: Callable[[], object]) -> None: def addfinalizer(self, finalizer: Callable[[], object]) -> None:
@ -629,17 +629,14 @@ class FixtureRequest(abc.ABC):
) )
except ValueError: except ValueError:
source_path_str = str(source_path) source_path_str = str(source_path)
location = getlocation(fixturedef.func, funcitem.config.rootpath)
msg = ( msg = (
"The requested fixture has no parameter defined for test:\n" "The requested fixture has no parameter defined for test:\n"
" {}\n\n" f" {funcitem.nodeid}\n\n"
"Requested fixture '{}' defined in:\n{}" f"Requested fixture '{fixturedef.argname}' defined in:\n"
"\n\nRequested here:\n{}:{}".format( f"{location}\n\n"
funcitem.nodeid, f"Requested here:\n"
fixturedef.argname, f"{source_path_str}:{source_lineno}"
getlocation(fixturedef.func, funcitem.config.rootpath),
source_path_str,
source_lineno,
)
) )
fail(msg, pytrace=False) fail(msg, pytrace=False)
@ -1108,12 +1105,12 @@ def resolve_fixture_function(
# (for example a plugin class with a fixture), see #2270. # (for example a plugin class with a fixture), see #2270.
if hasattr(fixturefunc, "__self__") and not isinstance( if hasattr(fixturefunc, "__self__") and not isinstance(
instance, instance,
fixturefunc.__self__.__class__, # type: ignore[union-attr] fixturefunc.__self__.__class__,
): ):
return fixturefunc return fixturefunc
fixturefunc = getimfunc(fixturedef.func) fixturefunc = getimfunc(fixturedef.func)
if fixturefunc != fixturedef.func: if fixturefunc != fixturedef.func:
fixturefunc = fixturefunc.__get__(instance) # type: ignore[union-attr] fixturefunc = fixturefunc.__get__(instance)
return fixturefunc return fixturefunc
@ -1147,12 +1144,13 @@ def wrap_function_to_error_out_if_called_directly(
) -> FixtureFunction: ) -> FixtureFunction:
"""Wrap the given fixture function so we can raise an error about it being called directly, """Wrap the given fixture function so we can raise an error about it being called directly,
instead of used as an argument in a test function.""" instead of used as an argument in a test function."""
name = fixture_marker.name or function.__name__
message = ( message = (
'Fixture "{name}" called directly. Fixtures are not meant to be called directly,\n' f'Fixture "{name}" called directly. Fixtures are not meant to be called directly,\n'
"but are created automatically when test functions request them as parameters.\n" "but are created automatically when test functions request them as parameters.\n"
"See https://docs.pytest.org/en/stable/explanation/fixtures.html for more information about fixtures, and\n" "See https://docs.pytest.org/en/stable/explanation/fixtures.html for more information about fixtures, and\n"
"https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly about how to update your code." "https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly about how to update your code."
).format(name=fixture_marker.name or function.__name__) )
@functools.wraps(function) @functools.wraps(function)
def result(*args, **kwargs): def result(*args, **kwargs):
@ -1219,8 +1217,7 @@ def fixture(
Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
] = ..., ] = ...,
name: Optional[str] = ..., name: Optional[str] = ...,
) -> FixtureFunction: ) -> FixtureFunction: ...
...
@overload @overload
@ -1234,8 +1231,7 @@ def fixture(
Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
] = ..., ] = ...,
name: Optional[str] = None, name: Optional[str] = None,
) -> FixtureFunctionMarker: ) -> FixtureFunctionMarker: ...
...
def fixture( def fixture(

View File

@ -35,7 +35,7 @@ def _iter_all_modules(
else: else:
# Type ignored because typeshed doesn't define ModuleType.__path__ # Type ignored because typeshed doesn't define ModuleType.__path__
# (only defined on packages). # (only defined on packages).
package_path = package.__path__ # type: ignore[attr-defined] package_path = package.__path__
path, prefix = package_path[0], package.__name__ + "." path, prefix = package_path[0], package.__name__ + "."
for _, name, is_package in pkgutil.iter_modules([path]): for _, name, is_package in pkgutil.iter_modules([path]):
if is_package: if is_package:

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Version info, help messages, tracing configuration.""" """Version info, help messages, tracing configuration."""
from argparse import Action from argparse import Action
import os import os
import sys import sys

View File

@ -1,6 +1,7 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Hook specifications for pytest plugins which are invoked by pytest itself """Hook specifications for pytest plugins which are invoked by pytest itself
and by builtin plugins.""" and by builtin plugins."""
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
from typing import Dict from typing import Dict

View File

@ -7,6 +7,7 @@ Based on initial code from Ross Lawley.
Output conforms to Output conforms to
https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
""" """
from datetime import datetime from datetime import datetime
import functools import functools
import os import os
@ -60,7 +61,7 @@ def bin_xml_escape(arg: object) -> str:
# Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] # Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
# For an unknown(?) reason, we disallow #x7F (DEL) as well. # For an unknown(?) reason, we disallow #x7F (DEL) as well.
illegal_xml_re = ( illegal_xml_re = (
"[^\u0009\u000A\u000D\u0020-\u007E\u0080-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]" "[^\u0009\u000a\u000d\u0020-\u007e\u0080-\ud7ff\ue000-\ufffd\u10000-\u10ffff]"
) )
return re.sub(illegal_xml_re, repl, str(arg)) return re.sub(illegal_xml_re, repl, str(arg))
@ -261,7 +262,7 @@ class _NodeReporter:
self.__dict__.clear() self.__dict__.clear()
# Type ignored because mypy doesn't like overriding a method. # Type ignored because mypy doesn't like overriding a method.
# Also the return value doesn't match... # Also the return value doesn't match...
self.to_xml = lambda: data # type: ignore[assignment] self.to_xml = lambda: data # type: ignore[method-assign]
def _warn_incompatibility_with_xunit2( def _warn_incompatibility_with_xunit2(

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Access and control log capturing.""" """Access and control log capturing."""
from contextlib import contextmanager from contextlib import contextmanager
from contextlib import nullcontext from contextlib import nullcontext
from datetime import datetime from datetime import datetime
@ -209,7 +210,7 @@ class PercentStyleMultiline(logging.PercentStyle):
if "\n" in record.message: if "\n" in record.message:
if hasattr(record, "auto_indent"): if hasattr(record, "auto_indent"):
# Passed in from the "extra={}" kwarg on the call to logging.log(). # Passed in from the "extra={}" kwarg on the call to logging.log().
auto_indent = self._get_auto_indent(record.auto_indent) # type: ignore[attr-defined] auto_indent = self._get_auto_indent(record.auto_indent)
else: else:
auto_indent = self._auto_indent auto_indent = self._auto_indent
@ -512,7 +513,7 @@ class LogCaptureFixture:
:return: The original disabled logging level. :return: The original disabled logging level.
""" """
original_disable_level: int = logger_obj.manager.disable # type: ignore[attr-defined] original_disable_level: int = logger_obj.manager.disable
if isinstance(level, str): if isinstance(level, str):
# Try to translate the level string to an int for `logging.disable()` # Try to translate the level string to an int for `logging.disable()`

View File

@ -736,14 +736,12 @@ class Session(nodes.Collector):
@overload @overload
def perform_collect( def perform_collect(
self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ... self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ...
) -> Sequence[nodes.Item]: ) -> Sequence[nodes.Item]: ...
...
@overload @overload
def perform_collect( def perform_collect(
self, args: Optional[Sequence[str]] = ..., genitems: bool = ... self, args: Optional[Sequence[str]] = ..., genitems: bool = ...
) -> Sequence[Union[nodes.Item, nodes.Collector]]: ) -> Sequence[Union[nodes.Item, nodes.Collector]]: ...
...
def perform_collect( def perform_collect(
self, args: Optional[Sequence[str]] = None, genitems: bool = True self, args: Optional[Sequence[str]] = None, genitems: bool = True

View File

@ -342,7 +342,7 @@ class MarkDecorator:
# return type. Not much we can do about that. Thankfully mypy picks # return type. Not much we can do about that. Thankfully mypy picks
# the first match so it works out even if we break the rules. # the first match so it works out even if we break the rules.
@overload @overload
def __call__(self, arg: Markable) -> Markable: # type: ignore[misc] def __call__(self, arg: Markable) -> Markable: # type: ignore[overload-overlap]
pass pass
@overload @overload
@ -433,13 +433,11 @@ if TYPE_CHECKING:
from _pytest.scope import _ScopeName from _pytest.scope import _ScopeName
class _SkipMarkDecorator(MarkDecorator): class _SkipMarkDecorator(MarkDecorator):
@overload # type: ignore[override,misc,no-overload-impl] @overload # type: ignore[override,no-overload-impl]
def __call__(self, arg: Markable) -> Markable: def __call__(self, arg: Markable) -> Markable: ...
...
@overload @overload
def __call__(self, reason: str = ...) -> "MarkDecorator": def __call__(self, reason: str = ...) -> "MarkDecorator": ...
...
class _SkipifMarkDecorator(MarkDecorator): class _SkipifMarkDecorator(MarkDecorator):
def __call__( # type: ignore[override] def __call__( # type: ignore[override]
@ -447,13 +445,11 @@ if TYPE_CHECKING:
condition: Union[str, bool] = ..., condition: Union[str, bool] = ...,
*conditions: Union[str, bool], *conditions: Union[str, bool],
reason: str = ..., reason: str = ...,
) -> MarkDecorator: ) -> MarkDecorator: ...
...
class _XfailMarkDecorator(MarkDecorator): class _XfailMarkDecorator(MarkDecorator):
@overload # type: ignore[override,misc,no-overload-impl] @overload # type: ignore[override,no-overload-impl]
def __call__(self, arg: Markable) -> Markable: def __call__(self, arg: Markable) -> Markable: ...
...
@overload @overload
def __call__( def __call__(
@ -466,8 +462,7 @@ if TYPE_CHECKING:
None, Type[BaseException], Tuple[Type[BaseException], ...] None, Type[BaseException], Tuple[Type[BaseException], ...]
] = ..., ] = ...,
strict: bool = ..., strict: bool = ...,
) -> MarkDecorator: ) -> MarkDecorator: ...
...
class _ParametrizeMarkDecorator(MarkDecorator): class _ParametrizeMarkDecorator(MarkDecorator):
def __call__( # type: ignore[override] def __call__( # type: ignore[override]
@ -483,8 +478,7 @@ if TYPE_CHECKING:
] ]
] = ..., ] = ...,
scope: Optional[_ScopeName] = ..., scope: Optional[_ScopeName] = ...,
) -> MarkDecorator: ) -> MarkDecorator: ...
...
class _UsefixturesMarkDecorator(MarkDecorator): class _UsefixturesMarkDecorator(MarkDecorator):
def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override] def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override]

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Monkeypatching and mocking functionality.""" """Monkeypatching and mocking functionality."""
from contextlib import contextmanager from contextlib import contextmanager
import os import os
import re import re
@ -167,8 +168,7 @@ class MonkeyPatch:
name: object, name: object,
value: Notset = ..., value: Notset = ...,
raising: bool = ..., raising: bool = ...,
) -> None: ) -> None: ...
...
@overload @overload
def setattr( def setattr(
@ -177,8 +177,7 @@ class MonkeyPatch:
name: str, name: str,
value: object, value: object,
raising: bool = ..., raising: bool = ...,
) -> None: ) -> None: ...
...
def setattr( def setattr(
self, self,

View File

@ -363,12 +363,10 @@ class Node(abc.ABC, metaclass=NodeMeta):
yield node, mark yield node, mark
@overload @overload
def get_closest_marker(self, name: str) -> Optional[Mark]: def get_closest_marker(self, name: str) -> Optional[Mark]: ...
...
@overload @overload
def get_closest_marker(self, name: str, default: Mark) -> Mark: def get_closest_marker(self, name: str, default: Mark) -> Mark: ...
...
def get_closest_marker( def get_closest_marker(
self, name: str, default: Optional[Mark] = None self, name: str, default: Optional[Mark] = None

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Submit failure or test session information to a pastebin service.""" """Submit failure or test session information to a pastebin service."""
from io import StringIO from io import StringIO
import tempfile import tempfile
from typing import IO from typing import IO

View File

@ -3,6 +3,7 @@
PYTEST_DONT_REWRITE PYTEST_DONT_REWRITE
""" """
import collections.abc import collections.abc
import contextlib import contextlib
from fnmatch import fnmatch from fnmatch import fnmatch
@ -245,8 +246,7 @@ class RecordedHookCall:
if TYPE_CHECKING: if TYPE_CHECKING:
# The class has undetermined attributes, this tells mypy about it. # The class has undetermined attributes, this tells mypy about it.
def __getattr__(self, key: str): def __getattr__(self, key: str): ...
...
@final @final
@ -327,15 +327,13 @@ class HookRecorder:
def getreports( def getreports(
self, self,
names: "Literal['pytest_collectreport']", names: "Literal['pytest_collectreport']",
) -> Sequence[CollectReport]: ) -> Sequence[CollectReport]: ...
...
@overload @overload
def getreports( def getreports(
self, self,
names: "Literal['pytest_runtest_logreport']", names: "Literal['pytest_runtest_logreport']",
) -> Sequence[TestReport]: ) -> Sequence[TestReport]: ...
...
@overload @overload
def getreports( def getreports(
@ -344,8 +342,7 @@ class HookRecorder:
"pytest_collectreport", "pytest_collectreport",
"pytest_runtest_logreport", "pytest_runtest_logreport",
), ),
) -> Sequence[Union[CollectReport, TestReport]]: ) -> Sequence[Union[CollectReport, TestReport]]: ...
...
def getreports( def getreports(
self, self,
@ -390,15 +387,13 @@ class HookRecorder:
def getfailures( def getfailures(
self, self,
names: "Literal['pytest_collectreport']", names: "Literal['pytest_collectreport']",
) -> Sequence[CollectReport]: ) -> Sequence[CollectReport]: ...
...
@overload @overload
def getfailures( def getfailures(
self, self,
names: "Literal['pytest_runtest_logreport']", names: "Literal['pytest_runtest_logreport']",
) -> Sequence[TestReport]: ) -> Sequence[TestReport]: ...
...
@overload @overload
def getfailures( def getfailures(
@ -407,8 +402,7 @@ class HookRecorder:
"pytest_collectreport", "pytest_collectreport",
"pytest_runtest_logreport", "pytest_runtest_logreport",
), ),
) -> Sequence[Union[CollectReport, TestReport]]: ) -> Sequence[Union[CollectReport, TestReport]]: ...
...
def getfailures( def getfailures(
self, self,

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Python test discovery, setup and run of test functions.""" """Python test discovery, setup and run of test functions."""
import abc import abc
from collections import Counter from collections import Counter
from collections import defaultdict from collections import defaultdict

View File

@ -393,7 +393,7 @@ class ApproxScalar(ApproxBase):
# tolerances, i.e. non-numerics and infinities. Need to call abs to # tolerances, i.e. non-numerics and infinities. Need to call abs to
# handle complex numbers, e.g. (inf + 1j). # handle complex numbers, e.g. (inf + 1j).
if (not isinstance(self.expected, (Complex, Decimal))) or math.isinf( if (not isinstance(self.expected, (Complex, Decimal))) or math.isinf(
abs(self.expected) # type: ignore[arg-type] abs(self.expected)
): ):
return str(self.expected) return str(self.expected)
@ -437,8 +437,8 @@ class ApproxScalar(ApproxBase):
# Allow the user to control whether NaNs are considered equal to each # Allow the user to control whether NaNs are considered equal to each
# other or not. The abs() calls are for compatibility with complex # other or not. The abs() calls are for compatibility with complex
# numbers. # numbers.
if math.isnan(abs(self.expected)): # type: ignore[arg-type] if math.isnan(abs(self.expected)):
return self.nan_ok and math.isnan(abs(actual)) # type: ignore[arg-type] return self.nan_ok and math.isnan(abs(actual))
# Infinity shouldn't be approximately equal to anything but itself, but # Infinity shouldn't be approximately equal to anything but itself, but
# if there's a relative tolerance, it will be infinite and infinity # if there's a relative tolerance, it will be infinite and infinity
@ -446,11 +446,11 @@ class ApproxScalar(ApproxBase):
# case would have been short circuited above, so here we can just # case would have been short circuited above, so here we can just
# return false if the expected value is infinite. The abs() call is # return false if the expected value is infinite. The abs() call is
# for compatibility with complex numbers. # for compatibility with complex numbers.
if math.isinf(abs(self.expected)): # type: ignore[arg-type] if math.isinf(abs(self.expected)):
return False return False
# Return true if the two numbers are within the tolerance. # Return true if the two numbers are within the tolerance.
result: bool = abs(self.expected - actual) <= self.tolerance result: bool = abs(self.expected - actual) <= self.tolerance # type: ignore[arg-type]
return result return result
# Ignore type because of https://github.com/python/mypy/issues/4266. # Ignore type because of https://github.com/python/mypy/issues/4266.
@ -769,8 +769,7 @@ def raises(
expected_exception: Union[Type[E], Tuple[Type[E], ...]], expected_exception: Union[Type[E], Tuple[Type[E], ...]],
*, *,
match: Optional[Union[str, Pattern[str]]] = ..., match: Optional[Union[str, Pattern[str]]] = ...,
) -> "RaisesContext[E]": ) -> "RaisesContext[E]": ...
...
@overload @overload
@ -779,8 +778,7 @@ def raises(
func: Callable[..., Any], func: Callable[..., Any],
*args: Any, *args: Any,
**kwargs: Any, **kwargs: Any,
) -> _pytest._code.ExceptionInfo[E]: ) -> _pytest._code.ExceptionInfo[E]: ...
...
def raises( def raises(

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Record warnings during test function execution.""" """Record warnings during test function execution."""
from pprint import pformat from pprint import pformat
import re import re
from types import TracebackType from types import TracebackType
@ -43,13 +44,11 @@ def recwarn() -> Generator["WarningsRecorder", None, None]:
@overload @overload
def deprecated_call( def deprecated_call(
*, match: Optional[Union[str, Pattern[str]]] = ... *, match: Optional[Union[str, Pattern[str]]] = ...
) -> "WarningsRecorder": ) -> "WarningsRecorder": ...
...
@overload @overload
def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: ...
...
def deprecated_call( def deprecated_call(
@ -91,8 +90,7 @@ def warns(
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ..., expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ...,
*, *,
match: Optional[Union[str, Pattern[str]]] = ..., match: Optional[Union[str, Pattern[str]]] = ...,
) -> "WarningsChecker": ) -> "WarningsChecker": ...
...
@overload @overload
@ -101,8 +99,7 @@ def warns(
func: Callable[..., T], func: Callable[..., T],
*args: Any, *args: Any,
**kwargs: Any, **kwargs: Any,
) -> T: ) -> T: ...
...
def warns( def warns(
@ -184,8 +181,7 @@ class WarningsRecorder(warnings.catch_warnings): # type:ignore[type-arg]
def __init__(self, *, _ispytest: bool = False) -> None: def __init__(self, *, _ispytest: bool = False) -> None:
check_ispytest(_ispytest) check_ispytest(_ispytest)
# Type ignored due to the way typeshed handles warnings.catch_warnings. super().__init__(record=True)
super().__init__(record=True) # type: ignore[call-arg]
self._entered = False self._entered = False
self._list: List[warnings.WarningMessage] = [] self._list: List[warnings.WarningMessage] = []

View File

@ -72,8 +72,7 @@ class BaseReport:
if TYPE_CHECKING: if TYPE_CHECKING:
# Can have arbitrary fields given to __init__(). # Can have arbitrary fields given to __init__().
def __getattr__(self, key: str) -> Any: def __getattr__(self, key: str) -> Any: ...
...
def toterminal(self, out: TerminalWriter) -> None: def toterminal(self, out: TerminalWriter) -> None:
if hasattr(self, "node"): if hasattr(self, "node"):
@ -606,9 +605,9 @@ def _report_kwargs_from_json(reportdict: Dict[str, Any]) -> Dict[str, Any]:
description, description,
) )
) )
exception_info: Union[ exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = (
ExceptionChainRepr, ReprExceptionInfo ExceptionChainRepr(chain)
] = ExceptionChainRepr(chain) )
else: else:
exception_info = ReprExceptionInfo( exception_info = ReprExceptionInfo(
reprtraceback=reprtraceback, reprtraceback=reprtraceback,

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Basic collect and runtest protocol implementations.""" """Basic collect and runtest protocol implementations."""
import bdb import bdb
import dataclasses import dataclasses
import os import os
@ -84,7 +85,7 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None:
dlist.append(rep) dlist.append(rep)
if not dlist: if not dlist:
return return
dlist.sort(key=lambda x: x.duration, reverse=True) # type: ignore[no-any-return] dlist.sort(key=lambda x: x.duration, reverse=True)
if not durations: if not durations:
tr.write_sep("=", "slowest durations") tr.write_sep("=", "slowest durations")
else: else:
@ -395,8 +396,7 @@ def pytest_make_collect_report(collector: Collector) -> CollectReport:
skip_exceptions = [Skipped] skip_exceptions = [Skipped]
unittest = sys.modules.get("unittest") unittest = sys.modules.get("unittest")
if unittest is not None: if unittest is not None:
# Type ignored because unittest is loaded dynamically. skip_exceptions.append(unittest.SkipTest)
skip_exceptions.append(unittest.SkipTest) # type: ignore
if isinstance(call.excinfo.value, tuple(skip_exceptions)): if isinstance(call.excinfo.value, tuple(skip_exceptions)):
outcome = "skipped" outcome = "skipped"
r_ = collector._repr_failure_py(call.excinfo, "line") r_ = collector._repr_failure_py(call.excinfo, "line")

View File

@ -58,7 +58,7 @@ def pytest_fixture_post_finalizer(
if config.option.setupshow: if config.option.setupshow:
_show_fixture_action(fixturedef, request.config, "TEARDOWN") _show_fixture_action(fixturedef, request.config, "TEARDOWN")
if hasattr(fixturedef, "cached_param"): if hasattr(fixturedef, "cached_param"):
del fixturedef.cached_param # type: ignore[attr-defined] del fixturedef.cached_param
def _show_fixture_action( def _show_fixture_action(
@ -87,7 +87,7 @@ def _show_fixture_action(
tw.write(" (fixtures used: {})".format(", ".join(deps))) tw.write(" (fixtures used: {})".format(", ".join(deps)))
if hasattr(fixturedef, "cached_param"): if hasattr(fixturedef, "cached_param"):
tw.write(f"[{saferepr(fixturedef.cached_param, maxsize=42)}]") # type: ignore[attr-defined] tw.write(f"[{saferepr(fixturedef.cached_param, maxsize=42)}]")
tw.flush() tw.flush()

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Support for skip/xfail functions and markers.""" """Support for skip/xfail functions and markers."""
from collections.abc import Mapping from collections.abc import Mapping
import dataclasses import dataclasses
import os import os
@ -109,7 +110,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool,
) )
globals_.update(dictionary) globals_.update(dictionary)
if hasattr(item, "obj"): if hasattr(item, "obj"):
globals_.update(item.obj.__globals__) # type: ignore[attr-defined] globals_.update(item.obj.__globals__)
try: try:
filename = f"<{mark.name} condition>" filename = f"<{mark.name} condition>"
condition_code = compile(condition, filename, "eval") condition_code = compile(condition, filename, "eval")

View File

@ -3,6 +3,7 @@
This is a good source for looking at the various reporting hooks. This is a good source for looking at the various reporting hooks.
""" """
import argparse import argparse
from collections import Counter from collections import Counter
import dataclasses import dataclasses

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Support for providing temporary directories to test functions.""" """Support for providing temporary directories to test functions."""
import dataclasses import dataclasses
import os import os
from pathlib import Path from pathlib import Path

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Discover and run std-library "unittest" style tests.""" """Discover and run std-library "unittest" style tests."""
import sys import sys
import traceback import traceback
import types import types
@ -98,8 +99,7 @@ class UnitTestCase(Class):
runtest = getattr(self.obj, "runTest", None) runtest = getattr(self.obj, "runTest", None)
if runtest is not None: if runtest is not None:
ut = sys.modules.get("twisted.trial.unittest", None) ut = sys.modules.get("twisted.trial.unittest", None)
# Type ignored because `ut` is an opaque module. if ut is None or runtest != ut.TestCase.runTest:
if ut is None or runtest != ut.TestCase.runTest: # type: ignore
yield TestCaseFunction.from_parent(self, name="runTest") yield TestCaseFunction.from_parent(self, name="runTest")
def _register_unittest_setup_class_fixture(self, cls: type) -> None: def _register_unittest_setup_class_fixture(self, cls: type) -> None:
@ -302,8 +302,7 @@ class TestCaseFunction(Function):
# Let the unittest framework handle async functions. # Let the unittest framework handle async functions.
if is_async_function(self.obj): if is_async_function(self.obj):
# Type ignored because self acts as the TestResult, but is not actually one. testcase(result=self)
testcase(result=self) # type: ignore[arg-type]
else: else:
# When --pdb is given, we want to postpone calling tearDown() otherwise # When --pdb is given, we want to postpone calling tearDown() otherwise
# when entering the pdb prompt, tearDown() would have probably cleaned up # when entering the pdb prompt, tearDown() would have probably cleaned up
@ -322,7 +321,7 @@ class TestCaseFunction(Function):
# wrap_pytest_function_for_tracing replaces self.obj by a wrapper. # wrap_pytest_function_for_tracing replaces self.obj by a wrapper.
setattr(testcase, self.name, self.obj) setattr(testcase, self.name, self.obj)
try: try:
testcase(result=self) # type: ignore[arg-type] testcase(result=self)
finally: finally:
delattr(testcase, self.name) delattr(testcase, self.name)
@ -353,9 +352,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None:
# its own nose.SkipTest. For unittest TestCases, SkipTest is already # its own nose.SkipTest. For unittest TestCases, SkipTest is already
# handled internally, and doesn't reach here. # handled internally, and doesn't reach here.
unittest = sys.modules.get("unittest") unittest = sys.modules.get("unittest")
if ( if unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest):
unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined]
):
excinfo = call.excinfo excinfo = call.excinfo
call2 = CallInfo[None].from_call( call2 = CallInfo[None].from_call(
lambda: pytest.skip(str(excinfo.value)), call.when lambda: pytest.skip(str(excinfo.value)), call.when

View File

@ -1,5 +1,6 @@
# PYTHON_ARGCOMPLETE_OK # PYTHON_ARGCOMPLETE_OK
"""pytest: unit and functional testing with Python.""" """pytest: unit and functional testing with Python."""
from _pytest import __version__ from _pytest import __version__
from _pytest import version_tuple from _pytest import version_tuple
from _pytest._code import ExceptionInfo from _pytest._code import ExceptionInfo

View File

@ -16,8 +16,8 @@ import pytest
@contextlib.contextmanager @contextlib.contextmanager
def ignore_encoding_warning(): def ignore_encoding_warning():
with warnings.catch_warnings(): with warnings.catch_warnings():
with contextlib.suppress(NameError): # new in 3.10 if sys.version_info > (3, 10):
warnings.simplefilter("ignore", EncodingWarning) # type: ignore [name-defined] warnings.simplefilter("ignore", EncodingWarning)
yield yield
@ -822,7 +822,7 @@ class TestLocalPath(CommonFSTests):
# depending on how the paths are used), but > 4096 (which is the # depending on how the paths are used), but > 4096 (which is the
# Linux' limitation) - the behaviour of paths with names > 4096 chars # Linux' limitation) - the behaviour of paths with names > 4096 chars
# is undetermined # is undetermined
newfilename = "/test" * 60 # type:ignore[unreachable] newfilename = "/test" * 60 # type:ignore[unreachable,unused-ignore]
l1 = tmpdir.join(newfilename) l1 = tmpdir.join(newfilename)
l1.ensure(file=True) l1.ensure(file=True)
l1.write_text("foo", encoding="utf-8") l1.write_text("foo", encoding="utf-8")
@ -1368,8 +1368,8 @@ class TestPOSIXLocalPath:
assert realpath.basename == "file" assert realpath.basename == "file"
def test_owner(self, path1, tmpdir): def test_owner(self, path1, tmpdir):
from grp import getgrgid # type:ignore[attr-defined] from grp import getgrgid # type:ignore[attr-defined,unused-ignore]
from pwd import getpwuid # type:ignore[attr-defined] from pwd import getpwuid # type:ignore[attr-defined,unused-ignore]
stat = path1.stat() stat = path1.stat()
assert stat.path == path1 assert stat.path == path1

View File

@ -180,7 +180,7 @@ class TestTraceback_f_g_h:
def test_traceback_cut_excludepath(self, pytester: Pytester) -> None: def test_traceback_cut_excludepath(self, pytester: Pytester) -> None:
p = pytester.makepyfile("def f(): raise ValueError") p = pytester.makepyfile("def f(): raise ValueError")
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError) as excinfo:
import_path(p, root=pytester.path, consider_namespace_packages=False).f() # type: ignore[attr-defined] import_path(p, root=pytester.path, consider_namespace_packages=False).f()
basedir = Path(pytest.__file__).parent basedir = Path(pytest.__file__).parent
newtraceback = excinfo.traceback.cut(excludepath=basedir) newtraceback = excinfo.traceback.cut(excludepath=basedir)
for x in newtraceback: for x in newtraceback:

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Reproduces issue #3774""" """Reproduces issue #3774"""
from unittest import mock from unittest import mock
import pytest import pytest

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Skipping an entire subclass with unittest.skip() should *not* call setUp from a base class.""" """Skipping an entire subclass with unittest.skip() should *not* call setUp from a base class."""
import unittest import unittest

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Skipping an entire subclass with unittest.skip() should *not* call setUpClass from a base class.""" """Skipping an entire subclass with unittest.skip() should *not* call setUpClass from a base class."""
import unittest import unittest

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""setUpModule is always called, even if all tests in the module are skipped""" """setUpModule is always called, even if all tests in the module are skipped"""
import unittest import unittest

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Issue #7110""" """Issue #7110"""
import asyncio import asyncio
from typing import List from typing import List

View File

@ -11,8 +11,8 @@ import pytest
("a", 1), ("a", 1),
("1", 1), ("1", 1),
("א", 1), ("א", 1),
("\u200B", 0), ("\u200b", 0),
("\u1ABE", 0), ("\u1abe", 0),
("\u0591", 0), ("\u0591", 0),
("🉐", 2), ("🉐", 2),
("", 2), # noqa: RUF001 ("", 2), # noqa: RUF001

View File

@ -109,7 +109,7 @@ class TestMetafunc:
metafunc = self.Metafunc(func) metafunc = self.Metafunc(func)
# When the input is an iterator, only len(args) are taken, # When the input is an iterator, only len(args) are taken,
# so the bad Exc isn't reached. # so the bad Exc isn't reached.
metafunc.parametrize("x", [1, 2], ids=gen()) # type: ignore[arg-type] metafunc.parametrize("x", [1, 2], ids=gen())
assert [(x.params, x.id) for x in metafunc._calls] == [ assert [(x.params, x.id) for x in metafunc._calls] == [
({"x": 1}, "0"), ({"x": 1}, "0"),
({"x": 2}, "2"), ({"x": 2}, "2"),
@ -121,7 +121,7 @@ class TestMetafunc:
r"Supported types are: .*" r"Supported types are: .*"
), ),
): ):
metafunc.parametrize("x", [1, 2, 3], ids=gen()) # type: ignore[arg-type] metafunc.parametrize("x", [1, 2, 3], ids=gen())
def test_parametrize_bad_scope(self) -> None: def test_parametrize_bad_scope(self) -> None:
def func(x): def func(x):

View File

@ -1243,7 +1243,7 @@ def test_disable_plugin_autoload(
monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1") monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1")
monkeypatch.setattr(importlib.metadata, "distributions", distributions) monkeypatch.setattr(importlib.metadata, "distributions", distributions)
monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin()) # type: ignore[misc] monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin())
config = pytester.parseconfig(*parse_args) config = pytester.parseconfig(*parse_args)
has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None
assert has_loaded == should_load assert has_loaded == should_load

View File

@ -29,7 +29,7 @@ def runpdb_and_get_stdout(pytester: Pytester, source: str):
def runpdb_and_get_report(pytester: Pytester, source: str): def runpdb_and_get_report(pytester: Pytester, source: str):
result = runpdb(pytester, source) result = runpdb(pytester, source)
reports = result.reprec.getreports("pytest_runtest_logreport") # type: ignore[attr-defined] reports = result.reprec.getreports("pytest_runtest_logreport")
assert len(reports) == 3, reports # setup/call/teardown assert len(reports) == 3, reports # setup/call/teardown
return reports[1] return reports[1]

View File

@ -1202,7 +1202,7 @@ def test_unicode_issue368(pytester: Pytester) -> None:
node_reporter.append_skipped(test_report) node_reporter.append_skipped(test_report)
test_report.longrepr = "filename", 1, "Skipped: 卡嘣嘣" test_report.longrepr = "filename", 1, "Skipped: 卡嘣嘣"
node_reporter.append_skipped(test_report) node_reporter.append_skipped(test_report)
test_report.wasxfail = ustr # type: ignore[attr-defined] test_report.wasxfail = ustr
node_reporter.append_skipped(test_report) node_reporter.append_skipped(test_report)
log.pytest_sessionfinish() log.pytest_sessionfinish()

View File

@ -18,7 +18,7 @@ class TestMark:
@pytest.mark.parametrize("attr", ["mark", "param"]) @pytest.mark.parametrize("attr", ["mark", "param"])
def test_pytest_exists_in_namespace_all(self, attr: str) -> None: def test_pytest_exists_in_namespace_all(self, attr: str) -> None:
module = sys.modules["pytest"] module = sys.modules["pytest"]
assert attr in module.__all__ # type: ignore assert attr in module.__all__
def test_pytest_mark_notcallable(self) -> None: def test_pytest_mark_notcallable(self) -> None:
mark = MarkGenerator(_ispytest=True) mark = MarkGenerator(_ispytest=True)
@ -34,7 +34,7 @@ class TestMark:
assert pytest.mark.foo(some_function) is some_function assert pytest.mark.foo(some_function) is some_function
marked_with_args = pytest.mark.foo.with_args(some_function) marked_with_args = pytest.mark.foo.with_args(some_function)
assert marked_with_args is not some_function # type: ignore[comparison-overlap] assert marked_with_args is not some_function
assert pytest.mark.foo(SomeClass) is SomeClass assert pytest.mark.foo(SomeClass) is SomeClass
assert pytest.mark.foo.with_args(SomeClass) is not SomeClass # type: ignore[comparison-overlap] assert pytest.mark.foo.with_args(SomeClass) is not SomeClass # type: ignore[comparison-overlap]

View File

@ -183,7 +183,7 @@ class TestImportPath:
obj = import_path( obj = import_path(
path1 / "execfile.py", root=path1, consider_namespace_packages=ns_param path1 / "execfile.py", root=path1, consider_namespace_packages=ns_param
) )
assert obj.x == 42 # type: ignore[attr-defined] assert obj.x == 42
assert obj.__name__ == "execfile" assert obj.__name__ == "execfile"
def test_import_path_missing_file(self, path1: Path, ns_param: bool) -> None: def test_import_path_missing_file(self, path1: Path, ns_param: bool) -> None:
@ -246,7 +246,7 @@ class TestImportPath:
mod = import_path( mod = import_path(
otherdir / "a.py", root=path1, consider_namespace_packages=ns_param otherdir / "a.py", root=path1, consider_namespace_packages=ns_param
) )
assert mod.result == "got it" # type: ignore[attr-defined] assert mod.result == "got it"
assert mod.__name__ == "otherdir.a" assert mod.__name__ == "otherdir.a"
def test_b(self, path1: Path, ns_param: bool) -> None: def test_b(self, path1: Path, ns_param: bool) -> None:
@ -254,7 +254,7 @@ class TestImportPath:
mod = import_path( mod = import_path(
otherdir / "b.py", root=path1, consider_namespace_packages=ns_param otherdir / "b.py", root=path1, consider_namespace_packages=ns_param
) )
assert mod.stuff == "got it" # type: ignore[attr-defined] assert mod.stuff == "got it"
assert mod.__name__ == "otherdir.b" assert mod.__name__ == "otherdir.b"
def test_c(self, path1: Path, ns_param: bool) -> None: def test_c(self, path1: Path, ns_param: bool) -> None:
@ -262,14 +262,14 @@ class TestImportPath:
mod = import_path( mod = import_path(
otherdir / "c.py", root=path1, consider_namespace_packages=ns_param otherdir / "c.py", root=path1, consider_namespace_packages=ns_param
) )
assert mod.value == "got it" # type: ignore[attr-defined] assert mod.value == "got it"
def test_d(self, path1: Path, ns_param: bool) -> None: def test_d(self, path1: Path, ns_param: bool) -> None:
otherdir = path1 / "otherdir" otherdir = path1 / "otherdir"
mod = import_path( mod = import_path(
otherdir / "d.py", root=path1, consider_namespace_packages=ns_param otherdir / "d.py", root=path1, consider_namespace_packages=ns_param
) )
assert mod.value2 == "got it" # type: ignore[attr-defined] assert mod.value2 == "got it"
def test_import_after(self, tmp_path: Path, ns_param: bool) -> None: def test_import_after(self, tmp_path: Path, ns_param: bool) -> None:
tmp_path.joinpath("xxxpackage").mkdir() tmp_path.joinpath("xxxpackage").mkdir()
@ -360,7 +360,7 @@ class TestImportPath:
root=tmp_path, root=tmp_path,
consider_namespace_packages=ns_param, consider_namespace_packages=ns_param,
) )
assert module.foo(2) == 42 # type: ignore[attr-defined] assert module.foo(2) == 42
assert str(simple_module.parent) not in sys.path assert str(simple_module.parent) not in sys.path
assert module.__name__ in sys.modules assert module.__name__ in sys.modules
assert module.__name__ == f"_src.tests.mymod_{request.node.name}" assert module.__name__ == f"_src.tests.mymod_{request.node.name}"
@ -400,7 +400,7 @@ class TestImportPath:
root=tmp_path, root=tmp_path,
consider_namespace_packages=ns_param, consider_namespace_packages=ns_param,
) )
assert module.foo(2) == 42 # type: ignore[attr-defined] assert module.foo(2) == 42
# mode='importlib' fails if no spec is found to load the module # mode='importlib' fails if no spec is found to load the module
import importlib.util import importlib.util

View File

@ -294,9 +294,9 @@ class TestReportSerialization:
reprec = pytester.inline_run() reprec = pytester.inline_run()
if report_class is TestReport: if report_class is TestReport:
reports: Union[ reports: Union[Sequence[TestReport], Sequence[CollectReport]] = (
Sequence[TestReport], Sequence[CollectReport] reprec.getreports("pytest_runtest_logreport")
] = reprec.getreports("pytest_runtest_logreport") )
# we have 3 reports: setup/call/teardown # we have 3 reports: setup/call/teardown
assert len(reports) == 3 assert len(reports) == 3
# get the call report # get the call report

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Test correct setup/teardowns at module, class, and instance level.""" """Test correct setup/teardowns at module, class, and instance level."""
from typing import List from typing import List
from _pytest.pytester import Pytester from _pytest.pytester import Pytester

View File

@ -1,5 +1,6 @@
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
"""Terminal reporting of the full testing process.""" """Terminal reporting of the full testing process."""
from io import StringIO from io import StringIO
import os import os
from pathlib import Path from pathlib import Path

View File

@ -4,6 +4,7 @@
This file is not executed, it is only checked by mypy to ensure that This file is not executed, it is only checked by mypy to ensure that
none of the code triggers any mypy errors. none of the code triggers any mypy errors.
""" """
import contextlib import contextlib
from typing import Optional from typing import Optional