diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 78cf36bae4c..deb187fec13 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.2.2" + rev: "v0.3.2" hooks: - id: ruff args: ["--fix"] @@ -26,7 +26,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 + rev: v1.9.0 hooks: - id: mypy files: ^(src/|testing/|scripts/) diff --git a/pyproject.toml b/pyproject.toml index e14556f2ff0..7d1b8a22df9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -281,6 +281,7 @@ template = "changelog/_template.rst" showcontent = true [tool.mypy] +files = ["src", "testing", "scripts"] mypy_path = ["src"] check_untyped_defs = true disallow_any_generics = true @@ -293,3 +294,4 @@ warn_return_any = true warn_unreachable = true warn_unused_configs = true no_implicit_reexport = true +warn_unused_ignores = true diff --git a/scripts/generate-gh-release-notes.py b/scripts/generate-gh-release-notes.py index c27f5774b6e..4222702d5d4 100644 --- a/scripts/generate-gh-release-notes.py +++ b/scripts/generate-gh-release-notes.py @@ -8,6 +8,7 @@ Requires Python3.6+. """ + from pathlib import Path import re import sys diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index 8a9f0aa0f3b..7dabbd3b328 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -13,6 +13,7 @@ **Token**: currently the token from the GitHub Actions is used, pushed with `pytest bot ` commit author. """ + import argparse from pathlib import Path import re diff --git a/scripts/release.py b/scripts/release.py index 73f5f52b1b0..bcbc4262d08 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -1,5 +1,6 @@ # mypy: disallow-untyped-defs """Invoke development tasks.""" + import argparse import os from pathlib import Path diff --git a/src/_pytest/__init__.py b/src/_pytest/__init__.py index 9062768eae3..b694a5f244a 100644 --- a/src/_pytest/__init__.py +++ b/src/_pytest/__init__.py @@ -7,4 +7,4 @@ # broken installation, we don't even try # unknown only works because we do poor mans version compare __version__ = "unknown" - version_tuple = (0, 0, "unknown") # type:ignore[assignment] + version_tuple = (0, 0, "unknown") diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 12168be607c..64a8f243a2d 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -279,9 +279,9 @@ def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool: Mostly for internal use. """ - tbh: Union[ - bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool] - ] = False + tbh: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]] = ( + False + ) for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals): # in normal cases, f_locals and f_globals are dictionaries # however via `exec(...)` / `eval(...)` they can be other types @@ -378,12 +378,10 @@ def cut( return self @overload - def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: - ... + def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: ... @overload - def __getitem__(self, key: slice) -> "Traceback": - ... + def __getitem__(self, key: slice) -> "Traceback": ... def __getitem__( self, key: Union["SupportsIndex", slice] @@ -1051,13 +1049,13 @@ def repr_excinfo( # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 if isinstance(e, BaseExceptionGroup): - reprtraceback: Union[ - ReprTracebackNative, ReprTraceback - ] = ReprTracebackNative( - traceback.format_exception( - type(excinfo_.value), - excinfo_.value, - excinfo_.traceback[0]._rawentry, + reprtraceback: Union[ReprTracebackNative, ReprTraceback] = ( + ReprTracebackNative( + traceback.format_exception( + type(excinfo_.value), + excinfo_.value, + excinfo_.traceback[0]._rawentry, + ) ) ) 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. obj = get_real_func(obj) if hasattr(obj, "place_as"): - obj = obj.place_as # type: ignore[attr-defined] + obj = obj.place_as try: code = Code.from_function(obj) diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index dac3c3867d8..7fa577e03b3 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -47,12 +47,10 @@ def __eq__(self, other: object) -> bool: __hash__ = None # type: ignore @overload - def __getitem__(self, key: int) -> str: - ... + def __getitem__(self, key: int) -> str: ... @overload - def __getitem__(self, key: slice) -> "Source": - ... + def __getitem__(self, key: slice) -> "Source": ... def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]: if isinstance(key, int): diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index badbb7e4a5f..deb6ecc3c94 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -9,6 +9,7 @@ from typing import Sequence from typing import TextIO +from ..compat import assert_never from .wcwidth import wcswidth @@ -209,6 +210,8 @@ def _highlight( from pygments.lexers.python import PythonLexer as Lexer elif lexer == "diff": from pygments.lexers.diff import DiffLexer as Lexer + else: + assert_never(lexer) from pygments import highlight import pygments.util except ImportError: diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 7701561d90e..7bb3693f938 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """local path implementation.""" + from __future__ import annotations import atexit @@ -205,12 +206,10 @@ class Stat: if TYPE_CHECKING: @property - def size(self) -> int: - ... + def size(self) -> int: ... @property - def mtime(self) -> float: - ... + def mtime(self) -> float: ... def __getattr__(self, name: str) -> Any: return getattr(self._osstatresult, "st_" + name) @@ -225,7 +224,7 @@ def owner(self): raise NotImplementedError("XXX win32") 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] @property @@ -235,7 +234,7 @@ def group(self): raise NotImplementedError("XXX win32") 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] def isdir(self): @@ -253,7 +252,7 @@ def getuserid(user): import pwd 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 @@ -261,7 +260,7 @@ def getgroupid(group): import grp 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 @@ -318,7 +317,7 @@ def chown(self, user, group, rec=0): def readlink(self) -> str: """Return value of a symbolic link.""" # 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): """Posix style hard link to another name.""" @@ -757,15 +756,11 @@ def open(self, mode="r", ensure=False, encoding=None): if ensure: self.dirpath().ensure(dir=1) 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( io.open, self.strpath, mode, - encoding=encoding, # type:ignore[arg-type] + encoding=encoding, ) return error.checked_call(open, self.strpath, mode) @@ -966,12 +961,10 @@ def ensure(self, *args, **kwargs): return p @overload - def stat(self, raising: Literal[True] = ...) -> Stat: - ... + def stat(self, raising: Literal[True] = ...) -> Stat: ... @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: """Return an os.stat() tuple.""" @@ -1277,13 +1270,7 @@ def mkdtemp(cls, rootdir=None): if rootdir is None: rootdir = cls.get_temproot() - # Using type ignore here because of this error: - # 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] - ) + path = error.checked_call(tempfile.mkdtemp, dir=str(rootdir)) return cls(path) @classmethod diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index ea71230e129..21dd4a4a4bb 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Support for presenting detailed information in failing assertions.""" + import sys from typing import Any from typing import Generator diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index ddae34c7326..678471ee992 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -289,15 +289,13 @@ def get_data(self, pathname: Union[str, bytes]) -> bytes: else: 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): from importlib.readers import FileReader else: from importlib.resources.readers import FileReader - return FileReader( # type:ignore[no-any-return] - types.SimpleNamespace(path=self._rewritten_names[name]) - ) + return FileReader(types.SimpleNamespace(path=self._rewritten_names[name])) def _write_pyc_fp( @@ -672,9 +670,9 @@ def __init__( self.enable_assertion_pass_hook = False self.source = source self.scope: tuple[ast.AST, ...] = () - self.variables_overwrite: defaultdict[ - tuple[ast.AST, ...], Dict[str, str] - ] = defaultdict(dict) + self.variables_overwrite: defaultdict[tuple[ast.AST, ...], Dict[str, str]] = ( + defaultdict(dict) + ) def run(self, mod: ast.Module) -> None: """Find all assert statements in *mod* and rewrite them.""" @@ -975,7 +973,7 @@ def visit_NamedExpr(self, name: ast.NamedExpr) -> Tuple[ast.NamedExpr, str]: # name if it's a local variable or _should_repr_global_name() # thinks it's acceptable. 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]) dorepr = self.helper("_should_repr_global_name", name) test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index ca3df74903d..cb671641041 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Utilities for assertion debugging.""" + import collections.abc import os import pprint @@ -222,10 +223,9 @@ def assertrepr_compare( except outcomes.Exit: raise except Exception: + repr_crash = _pytest._code.ExceptionInfo.from_current()._getreprcrash() explanation = [ - "(pytest_assertion plugin: representation of details failed: {}.".format( - _pytest._code.ExceptionInfo.from_current()._getreprcrash() - ), + f"(pytest_assertion plugin: representation of details failed: {repr_crash}.", " Probably an object has a faulty __repr__.)", ] diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 5ccd2168ddf..81703ddac44 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Implementation of the cache provider.""" + # This plugin was not named "cache" to avoid conflicts with the external # pytest-cache version. import dataclasses @@ -432,7 +433,7 @@ def pytest_collection_modifyitems( return res 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: config = self.config diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index dce431c3db4..3f6a2510348 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Per-test stdout/stderr capturing mechanism.""" + import abc import collections import contextlib @@ -105,17 +106,16 @@ def _windowsconsoleio_workaround(stream: TextIO) -> None: return # 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 - buffered = hasattr(stream.buffer, "raw") - raw_stdout = stream.buffer.raw if buffered else stream.buffer # type: ignore[attr-defined] + raw_stdout = stream.buffer.raw if hasattr(stream.buffer, "raw") else stream.buffer - 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 def _reopen_stdio(f, mode): - if not buffered and mode[0] == "w": + if not hasattr(stream.buffer, "raw") and mode[0] == "w": buffering = 0 else: buffering = -1 @@ -482,12 +482,9 @@ def __init__(self, targetfd: int) -> None: self._state = "initialized" def __repr__(self) -> str: - return "<{} {} oldfd={} _state={!r} tmpfile={!r}>".format( - self.__class__.__name__, - self.targetfd, - self.targetfd_save, - self._state, - self.tmpfile, + return ( + f"<{self.__class__.__name__} {self.targetfd} oldfd={self.targetfd_save} " + f"_state={self._state!r} tmpfile={self.tmpfile!r}>" ) def _assert_state(self, op: str, states: Tuple[str, ...]) -> None: @@ -621,12 +618,9 @@ def __init__( self.err: Optional[CaptureBase[AnyStr]] = err def __repr__(self) -> str: - return "".format( - self.out, - self.err, - self.in_, - self._state, - self._in_suspended, + return ( + f"" ) def start_capturing(self) -> None: @@ -735,8 +729,9 @@ def __init__(self, method: _CaptureMethod) -> None: self._capture_fixture: Optional[CaptureFixture[Any]] = None def __repr__(self) -> str: - return "".format( - self._method, self._global_capturing, self._capture_fixture + return ( + f"" ) def is_capturing(self) -> Union[str, bool]: diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 8d49d6fb631..9d9411818ac 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -304,7 +304,7 @@ def get_user_id() -> int | None: # 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 # 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. # Emscripten has a return 0 stub. return None diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index bf2cfc3996d..7ff27643f10 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Command line options, ini-file and conftest.py processing.""" + import argparse import collections.abc import copy diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 441d79e902c..95dc28d4a16 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -426,8 +426,7 @@ def error(self, message: str) -> NoReturn: msg = f"{self.prog}: error: {message}" if hasattr(self._parser, "_config_source_hint"): - # Type ignored because the attribute is set dynamically. - msg = f"{msg} ({self._parser._config_source_hint})" # type: ignore + msg = f"{msg} ({self._parser._config_source_hint})" raise UsageError(self.format_usage() + msg) diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index cb157cd6724..6ed0c5c7aee 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Interactive debugging with PDB, the Python Debugger.""" + import argparse import functools import sys @@ -154,9 +155,7 @@ def _import_pdb_cls(cls, capman: Optional["CaptureManager"]): def _get_pdb_wrapper_class(cls, pdb_cls, capman: Optional["CaptureManager"]): import _pytest.config - # Type ignored because mypy doesn't support "dynamic" - # inheritance like this. - class PytestPdbWrapper(pdb_cls): # type: ignore[valid-type,misc] + class PytestPdbWrapper(pdb_cls): _pytest_capman = capman _continued = False diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index ced3b82f5ea..7fff99f37b5 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Discover and run doctests in modules and test files.""" + import bdb from contextlib import contextmanager import functools diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index daf3145aaac..8b25d743ca4 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -447,7 +447,7 @@ def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": @property def config(self) -> Config: """The pytest config object associated with this request.""" - return self._pyfuncitem.config # type: ignore[no-any-return] + return self._pyfuncitem.config @property def function(self): @@ -499,7 +499,7 @@ def keywords(self) -> MutableMapping[str, Any]: @property def session(self) -> "Session": """Pytest session object.""" - return self._pyfuncitem.session # type: ignore[no-any-return] + return self._pyfuncitem.session @abc.abstractmethod def addfinalizer(self, finalizer: Callable[[], object]) -> None: @@ -629,17 +629,14 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: ) except ValueError: source_path_str = str(source_path) + location = getlocation(fixturedef.func, funcitem.config.rootpath) msg = ( "The requested fixture has no parameter defined for test:\n" - " {}\n\n" - "Requested fixture '{}' defined in:\n{}" - "\n\nRequested here:\n{}:{}".format( - funcitem.nodeid, - fixturedef.argname, - getlocation(fixturedef.func, funcitem.config.rootpath), - source_path_str, - source_lineno, - ) + f" {funcitem.nodeid}\n\n" + f"Requested fixture '{fixturedef.argname}' defined in:\n" + f"{location}\n\n" + f"Requested here:\n" + f"{source_path_str}:{source_lineno}" ) fail(msg, pytrace=False) @@ -1108,12 +1105,12 @@ def resolve_fixture_function( # (for example a plugin class with a fixture), see #2270. if hasattr(fixturefunc, "__self__") and not isinstance( instance, - fixturefunc.__self__.__class__, # type: ignore[union-attr] + fixturefunc.__self__.__class__, ): return fixturefunc fixturefunc = getimfunc(fixturedef.func) if fixturefunc != fixturedef.func: - fixturefunc = fixturefunc.__get__(instance) # type: ignore[union-attr] + fixturefunc = fixturefunc.__get__(instance) return fixturefunc @@ -1147,12 +1144,13 @@ def wrap_function_to_error_out_if_called_directly( ) -> FixtureFunction: """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.""" + name = fixture_marker.name or function.__name__ 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" "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." - ).format(name=fixture_marker.name or function.__name__) + ) @functools.wraps(function) def result(*args, **kwargs): @@ -1219,8 +1217,7 @@ def fixture( Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] ] = ..., name: Optional[str] = ..., -) -> FixtureFunction: - ... +) -> FixtureFunction: ... @overload @@ -1234,8 +1231,7 @@ def fixture( Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] ] = ..., name: Optional[str] = None, -) -> FixtureFunctionMarker: - ... +) -> FixtureFunctionMarker: ... def fixture( diff --git a/src/_pytest/freeze_support.py b/src/_pytest/freeze_support.py index d028058e365..e03a6d1753d 100644 --- a/src/_pytest/freeze_support.py +++ b/src/_pytest/freeze_support.py @@ -35,7 +35,7 @@ def _iter_all_modules( else: # Type ignored because typeshed doesn't define ModuleType.__path__ # (only defined on packages). - package_path = package.__path__ # type: ignore[attr-defined] + package_path = package.__path__ path, prefix = package_path[0], package.__name__ + "." for _, name, is_package in pkgutil.iter_modules([path]): if is_package: diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index aa8bf65c73f..37fbdf04d7e 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Version info, help messages, tracing configuration.""" + from argparse import Action import os import sys diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 4bee76f1e39..db55bd82d04 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs """Hook specifications for pytest plugins which are invoked by pytest itself and by builtin plugins.""" + from pathlib import Path from typing import Any from typing import Dict diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 4ca356f31f2..e6ccebc2020 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -7,6 +7,7 @@ Output conforms to 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 import functools import os @@ -60,7 +61,7 @@ def repl(matchobj: Match[str]) -> str: # Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] # For an unknown(?) reason, we disallow #x7F (DEL) as well. 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)) @@ -261,7 +262,7 @@ def finalize(self) -> None: self.__dict__.clear() # Type ignored because mypy doesn't like overriding a method. # 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( diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index e9a3234fdec..af5e443ced1 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Access and control log capturing.""" + from contextlib import contextmanager from contextlib import nullcontext from datetime import datetime @@ -209,7 +210,7 @@ def format(self, record: logging.LogRecord) -> str: if "\n" in record.message: if hasattr(record, "auto_indent"): # 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: auto_indent = self._auto_indent @@ -512,7 +513,7 @@ def _force_enable_logging( :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): # Try to translate the level string to an int for `logging.disable()` diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 3b9ac93cf3f..716d5cf783b 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -736,14 +736,12 @@ def _collect_path( @overload def perform_collect( self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ... - ) -> Sequence[nodes.Item]: - ... + ) -> Sequence[nodes.Item]: ... @overload def perform_collect( self, args: Optional[Sequence[str]] = ..., genitems: bool = ... - ) -> Sequence[Union[nodes.Item, nodes.Collector]]: - ... + ) -> Sequence[Union[nodes.Item, nodes.Collector]]: ... def perform_collect( self, args: Optional[Sequence[str]] = None, genitems: bool = True diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 1da300c8213..a6503bf1d46 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -342,7 +342,7 @@ def with_args(self, *args: object, **kwargs: object) -> "MarkDecorator": # 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. @overload - def __call__(self, arg: Markable) -> Markable: # type: ignore[misc] + def __call__(self, arg: Markable) -> Markable: # type: ignore[overload-overlap] pass @overload @@ -433,13 +433,11 @@ def store_mark(obj, mark: Mark, *, stacklevel: int = 2) -> None: from _pytest.scope import _ScopeName class _SkipMarkDecorator(MarkDecorator): - @overload # type: ignore[override,misc,no-overload-impl] - def __call__(self, arg: Markable) -> Markable: - ... + @overload # type: ignore[override,no-overload-impl] + def __call__(self, arg: Markable) -> Markable: ... @overload - def __call__(self, reason: str = ...) -> "MarkDecorator": - ... + def __call__(self, reason: str = ...) -> "MarkDecorator": ... class _SkipifMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] @@ -447,13 +445,11 @@ def __call__( # type: ignore[override] condition: Union[str, bool] = ..., *conditions: Union[str, bool], reason: str = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _XfailMarkDecorator(MarkDecorator): - @overload # type: ignore[override,misc,no-overload-impl] - def __call__(self, arg: Markable) -> Markable: - ... + @overload # type: ignore[override,no-overload-impl] + def __call__(self, arg: Markable) -> Markable: ... @overload def __call__( @@ -466,8 +462,7 @@ def __call__( None, Type[BaseException], Tuple[Type[BaseException], ...] ] = ..., strict: bool = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _ParametrizeMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] @@ -483,8 +478,7 @@ def __call__( # type: ignore[override] ] ] = ..., scope: Optional[_ScopeName] = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _UsefixturesMarkDecorator(MarkDecorator): def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override] diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index e96a938681f..3f398df76b1 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Monkeypatching and mocking functionality.""" + from contextlib import contextmanager import os import re @@ -167,8 +168,7 @@ def setattr( name: object, value: Notset = ..., raising: bool = ..., - ) -> None: - ... + ) -> None: ... @overload def setattr( @@ -177,8 +177,7 @@ def setattr( name: str, value: object, raising: bool = ..., - ) -> None: - ... + ) -> None: ... def setattr( self, diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index cff15001c93..1b91bdb6e43 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -363,12 +363,10 @@ def iter_markers_with_node( yield node, mark @overload - def get_closest_marker(self, name: str) -> Optional[Mark]: - ... + def get_closest_marker(self, name: str) -> Optional[Mark]: ... @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( self, name: str, default: Optional[Mark] = None diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 98ba5c9c154..533d78c9a2a 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Submit failure or test session information to a pastebin service.""" + from io import StringIO import tempfile from typing import IO diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 8002528b965..23f44da69ca 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -3,6 +3,7 @@ PYTEST_DONT_REWRITE """ + import collections.abc import contextlib from fnmatch import fnmatch @@ -245,8 +246,7 @@ def __repr__(self) -> str: if TYPE_CHECKING: # The class has undetermined attributes, this tells mypy about it. - def __getattr__(self, key: str): - ... + def __getattr__(self, key: str): ... @final @@ -327,15 +327,13 @@ def getcall(self, name: str) -> RecordedHookCall: def getreports( self, names: "Literal['pytest_collectreport']", - ) -> Sequence[CollectReport]: - ... + ) -> Sequence[CollectReport]: ... @overload def getreports( self, names: "Literal['pytest_runtest_logreport']", - ) -> Sequence[TestReport]: - ... + ) -> Sequence[TestReport]: ... @overload def getreports( @@ -344,8 +342,7 @@ def getreports( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: - ... + ) -> Sequence[Union[CollectReport, TestReport]]: ... def getreports( self, @@ -390,15 +387,13 @@ def matchreport( def getfailures( self, names: "Literal['pytest_collectreport']", - ) -> Sequence[CollectReport]: - ... + ) -> Sequence[CollectReport]: ... @overload def getfailures( self, names: "Literal['pytest_runtest_logreport']", - ) -> Sequence[TestReport]: - ... + ) -> Sequence[TestReport]: ... @overload def getfailures( @@ -407,8 +402,7 @@ def getfailures( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: - ... + ) -> Sequence[Union[CollectReport, TestReport]]: ... def getfailures( self, diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 7b0683b6ec5..3242d517ea0 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Python test discovery, setup and run of test functions.""" + import abc from collections import Counter from collections import defaultdict diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 7e51da3194a..0ba86e816d3 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -393,7 +393,7 @@ def __repr__(self) -> str: # tolerances, i.e. non-numerics and infinities. Need to call abs to # handle complex numbers, e.g. (inf + 1j). if (not isinstance(self.expected, (Complex, Decimal))) or math.isinf( - abs(self.expected) # type: ignore[arg-type] + abs(self.expected) ): return str(self.expected) @@ -437,8 +437,8 @@ def __eq__(self, actual) -> bool: # Allow the user to control whether NaNs are considered equal to each # other or not. The abs() calls are for compatibility with complex # numbers. - if math.isnan(abs(self.expected)): # type: ignore[arg-type] - return self.nan_ok and math.isnan(abs(actual)) # type: ignore[arg-type] + if math.isnan(abs(self.expected)): + return self.nan_ok and math.isnan(abs(actual)) # Infinity shouldn't be approximately equal to anything but itself, but # if there's a relative tolerance, it will be infinite and infinity @@ -446,11 +446,11 @@ def __eq__(self, actual) -> bool: # case would have been short circuited above, so here we can just # return false if the expected value is infinite. The abs() call is # for compatibility with complex numbers. - if math.isinf(abs(self.expected)): # type: ignore[arg-type] + if math.isinf(abs(self.expected)): return False # 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 # 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], ...]], *, match: Optional[Union[str, Pattern[str]]] = ..., -) -> "RaisesContext[E]": - ... +) -> "RaisesContext[E]": ... @overload @@ -779,8 +778,7 @@ def raises( func: Callable[..., Any], *args: Any, **kwargs: Any, -) -> _pytest._code.ExceptionInfo[E]: - ... +) -> _pytest._code.ExceptionInfo[E]: ... def raises( diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index bcf9f1466c5..63e7a4bd6dc 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Record warnings during test function execution.""" + from pprint import pformat import re from types import TracebackType @@ -43,13 +44,11 @@ def recwarn() -> Generator["WarningsRecorder", None, None]: @overload def deprecated_call( *, match: Optional[Union[str, Pattern[str]]] = ... -) -> "WarningsRecorder": - ... +) -> "WarningsRecorder": ... @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( @@ -91,8 +90,7 @@ def warns( expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ..., *, match: Optional[Union[str, Pattern[str]]] = ..., -) -> "WarningsChecker": - ... +) -> "WarningsChecker": ... @overload @@ -101,8 +99,7 @@ def warns( func: Callable[..., T], *args: Any, **kwargs: Any, -) -> T: - ... +) -> T: ... def warns( @@ -184,8 +181,7 @@ class WarningsRecorder(warnings.catch_warnings): # type:ignore[type-arg] def __init__(self, *, _ispytest: bool = False) -> None: check_ispytest(_ispytest) - # Type ignored due to the way typeshed handles warnings.catch_warnings. - super().__init__(record=True) # type: ignore[call-arg] + super().__init__(record=True) self._entered = False self._list: List[warnings.WarningMessage] = [] diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 7cdb70e324b..70f3212ce7b 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -72,8 +72,7 @@ def __init__(self, **kw: Any) -> None: if TYPE_CHECKING: # 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: if hasattr(self, "node"): @@ -606,9 +605,9 @@ def deserialize_repr_crash(repr_crash_dict: Optional[Dict[str, Any]]): description, ) ) - exception_info: Union[ - ExceptionChainRepr, ReprExceptionInfo - ] = ExceptionChainRepr(chain) + exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = ( + ExceptionChainRepr(chain) + ) else: exception_info = ReprExceptionInfo( reprtraceback=reprtraceback, diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 16abb895d58..3f706b927c8 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Basic collect and runtest protocol implementations.""" + import bdb import dataclasses import os @@ -84,7 +85,7 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None: dlist.append(rep) if not dlist: 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: tr.write_sep("=", "slowest durations") else: @@ -395,8 +396,7 @@ def collect() -> List[Union[Item, Collector]]: skip_exceptions = [Skipped] unittest = sys.modules.get("unittest") if unittest is not None: - # Type ignored because unittest is loaded dynamically. - skip_exceptions.append(unittest.SkipTest) # type: ignore + skip_exceptions.append(unittest.SkipTest) if isinstance(call.excinfo.value, tuple(skip_exceptions)): outcome = "skipped" r_ = collector._repr_failure_py(call.excinfo, "line") diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index c87de1e32fb..39ab28b466b 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -58,7 +58,7 @@ def pytest_fixture_post_finalizer( if config.option.setupshow: _show_fixture_action(fixturedef, request.config, "TEARDOWN") if hasattr(fixturedef, "cached_param"): - del fixturedef.cached_param # type: ignore[attr-defined] + del fixturedef.cached_param def _show_fixture_action( @@ -87,7 +87,7 @@ def _show_fixture_action( tw.write(" (fixtures used: {})".format(", ".join(deps))) 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() diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 4799ae6496a..188dcae3f1c 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Support for skip/xfail functions and markers.""" + from collections.abc import Mapping import dataclasses import os @@ -109,7 +110,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool, ) globals_.update(dictionary) if hasattr(item, "obj"): - globals_.update(item.obj.__globals__) # type: ignore[attr-defined] + globals_.update(item.obj.__globals__) try: filename = f"<{mark.name} condition>" condition_code = compile(condition, filename, "eval") diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 75d57197aac..2c9c0d3b1cf 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -3,6 +3,7 @@ This is a good source for looking at the various reporting hooks. """ + import argparse from collections import Counter import dataclasses diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 1cb9fbbe0e0..72efed3e87a 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Support for providing temporary directories to test functions.""" + import dataclasses import os from pathlib import Path diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 32eb361c6fd..5099904fd41 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Discover and run std-library "unittest" style tests.""" + import sys import traceback import types @@ -98,8 +99,7 @@ def collect(self) -> Iterable[Union[Item, Collector]]: runtest = getattr(self.obj, "runTest", None) if runtest is not 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: # type: ignore + if ut is None or runtest != ut.TestCase.runTest: yield TestCaseFunction.from_parent(self, name="runTest") def _register_unittest_setup_class_fixture(self, cls: type) -> None: @@ -302,8 +302,7 @@ def runtest(self) -> None: # Let the unittest framework handle async functions. if is_async_function(self.obj): - # Type ignored because self acts as the TestResult, but is not actually one. - testcase(result=self) # type: ignore[arg-type] + testcase(result=self) else: # When --pdb is given, we want to postpone calling tearDown() otherwise # when entering the pdb prompt, tearDown() would have probably cleaned up @@ -322,7 +321,7 @@ def runtest(self) -> None: # wrap_pytest_function_for_tracing replaces self.obj by a wrapper. setattr(testcase, self.name, self.obj) try: - testcase(result=self) # type: ignore[arg-type] + testcase(result=self) finally: 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 # handled internally, and doesn't reach here. unittest = sys.modules.get("unittest") - if ( - unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined] - ): + if unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest): excinfo = call.excinfo call2 = CallInfo[None].from_call( lambda: pytest.skip(str(excinfo.value)), call.when diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 20829aa585f..c6b6de827e9 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -1,5 +1,6 @@ # PYTHON_ARGCOMPLETE_OK """pytest: unit and functional testing with Python.""" + from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 0c8575c4ec7..ad2526571e6 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -16,8 +16,8 @@ @contextlib.contextmanager def ignore_encoding_warning(): with warnings.catch_warnings(): - with contextlib.suppress(NameError): # new in 3.10 - warnings.simplefilter("ignore", EncodingWarning) # type: ignore [name-defined] + if sys.version_info > (3, 10): + warnings.simplefilter("ignore", EncodingWarning) yield @@ -822,7 +822,7 @@ def test_long_filenames(self, tmpdir): # depending on how the paths are used), but > 4096 (which is the # Linux' limitation) - the behaviour of paths with names > 4096 chars # is undetermined - newfilename = "/test" * 60 # type:ignore[unreachable] + newfilename = "/test" * 60 # type:ignore[unreachable,unused-ignore] l1 = tmpdir.join(newfilename) l1.ensure(file=True) l1.write_text("foo", encoding="utf-8") @@ -1368,8 +1368,8 @@ def test_realpath_file(self, tmpdir): assert realpath.basename == "file" def test_owner(self, path1, tmpdir): - from grp import getgrgid # type:ignore[attr-defined] - from pwd import getpwuid # type:ignore[attr-defined] + from grp import getgrgid # type:ignore[attr-defined,unused-ignore] + from pwd import getpwuid # type:ignore[attr-defined,unused-ignore] stat = path1.stat() assert stat.path == path1 diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 49c5dd3715b..419c11abcc0 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -180,7 +180,7 @@ def test_traceback_cut(self) -> None: def test_traceback_cut_excludepath(self, pytester: Pytester) -> None: p = pytester.makepyfile("def f(): raise ValueError") 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 newtraceback = excinfo.traceback.cut(excludepath=basedir) for x in newtraceback: diff --git a/testing/example_scripts/acceptance/fixture_mock_integration.py b/testing/example_scripts/acceptance/fixture_mock_integration.py index 36e711f40eb..d802a7f8728 100644 --- a/testing/example_scripts/acceptance/fixture_mock_integration.py +++ b/testing/example_scripts/acceptance/fixture_mock_integration.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Reproduces issue #3774""" + from unittest import mock import pytest diff --git a/testing/example_scripts/unittest/test_setup_skip.py b/testing/example_scripts/unittest/test_setup_skip.py index 4681cda0352..7550a097576 100644 --- a/testing/example_scripts/unittest/test_setup_skip.py +++ b/testing/example_scripts/unittest/test_setup_skip.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Skipping an entire subclass with unittest.skip() should *not* call setUp from a base class.""" + import unittest diff --git a/testing/example_scripts/unittest/test_setup_skip_class.py b/testing/example_scripts/unittest/test_setup_skip_class.py index eae98287f91..48f7e476f40 100644 --- a/testing/example_scripts/unittest/test_setup_skip_class.py +++ b/testing/example_scripts/unittest/test_setup_skip_class.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Skipping an entire subclass with unittest.skip() should *not* call setUpClass from a base class.""" + import unittest diff --git a/testing/example_scripts/unittest/test_setup_skip_module.py b/testing/example_scripts/unittest/test_setup_skip_module.py index 43c24136edf..eee4263d22b 100644 --- a/testing/example_scripts/unittest/test_setup_skip_module.py +++ b/testing/example_scripts/unittest/test_setup_skip_module.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """setUpModule is always called, even if all tests in the module are skipped""" + import unittest diff --git a/testing/example_scripts/unittest/test_unittest_asynctest.py b/testing/example_scripts/unittest/test_unittest_asynctest.py index b3f03e3256b..e9b10171e8d 100644 --- a/testing/example_scripts/unittest/test_unittest_asynctest.py +++ b/testing/example_scripts/unittest/test_unittest_asynctest.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Issue #7110""" + import asyncio from typing import List diff --git a/testing/io/test_wcwidth.py b/testing/io/test_wcwidth.py index 0989af00d07..82503b8300c 100644 --- a/testing/io/test_wcwidth.py +++ b/testing/io/test_wcwidth.py @@ -11,8 +11,8 @@ ("a", 1), ("1", 1), ("א", 1), - ("\u200B", 0), - ("\u1ABE", 0), + ("\u200b", 0), + ("\u1abe", 0), ("\u0591", 0), ("🉐", 2), ("$", 2), # noqa: RUF001 diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index ed22c2b5a1c..3d0058fa0a7 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -109,7 +109,7 @@ def gen() -> Iterator[Union[int, None, Exc]]: metafunc = self.Metafunc(func) # When the input is an iterator, only len(args) are taken, # 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] == [ ({"x": 1}, "0"), ({"x": 2}, "2"), @@ -121,7 +121,7 @@ def gen() -> Iterator[Union[int, None, Exc]]: 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 func(x): diff --git a/testing/test_config.py b/testing/test_config.py index 88470ff2d49..147c2cb851c 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1243,7 +1243,7 @@ def distributions(): monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1") 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) has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None assert has_loaded == should_load diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 91a0be48108..53ebadbdba4 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -29,7 +29,7 @@ def runpdb_and_get_stdout(pytester: Pytester, source: str): def runpdb_and_get_report(pytester: Pytester, source: str): 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 return reports[1] diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 42104255b28..3b92d65bdb9 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1202,7 +1202,7 @@ class Report(BaseReport): node_reporter.append_skipped(test_report) test_report.longrepr = "filename", 1, "Skipped: 卡嘣嘣" node_reporter.append_skipped(test_report) - test_report.wasxfail = ustr # type: ignore[attr-defined] + test_report.wasxfail = ustr node_reporter.append_skipped(test_report) log.pytest_sessionfinish() diff --git a/testing/test_mark.py b/testing/test_mark.py index 6e183a17887..2896afa4532 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -18,7 +18,7 @@ class TestMark: @pytest.mark.parametrize("attr", ["mark", "param"]) def test_pytest_exists_in_namespace_all(self, attr: str) -> None: module = sys.modules["pytest"] - assert attr in module.__all__ # type: ignore + assert attr in module.__all__ def test_pytest_mark_notcallable(self) -> None: mark = MarkGenerator(_ispytest=True) @@ -34,7 +34,7 @@ class SomeClass: assert pytest.mark.foo(some_function) is 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.with_args(SomeClass) is not SomeClass # type: ignore[comparison-overlap] diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index a4bccb1b2ac..7f740a0607b 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -183,7 +183,7 @@ def test_smoke_test(self, path1: Path, ns_param: bool) -> None: obj = import_path( 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" def test_import_path_missing_file(self, path1: Path, ns_param: bool) -> None: @@ -246,7 +246,7 @@ def test_a(self, path1: Path, ns_param: bool) -> None: mod = import_path( 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" def test_b(self, path1: Path, ns_param: bool) -> None: @@ -254,7 +254,7 @@ def test_b(self, path1: Path, ns_param: bool) -> None: mod = import_path( 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" def test_c(self, path1: Path, ns_param: bool) -> None: @@ -262,14 +262,14 @@ def test_c(self, path1: Path, ns_param: bool) -> None: mod = import_path( 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: otherdir = path1 / "otherdir" mod = import_path( 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: tmp_path.joinpath("xxxpackage").mkdir() @@ -360,7 +360,7 @@ def test_importmode_importlib( root=tmp_path, 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 module.__name__ in sys.modules assert module.__name__ == f"_src.tests.mymod_{request.node.name}" @@ -400,7 +400,7 @@ def test_no_meta_path_found( root=tmp_path, 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 import importlib.util diff --git a/testing/test_reports.py b/testing/test_reports.py index 2de5ae60090..c6baeebc9dd 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -294,9 +294,9 @@ def test_a(): reprec = pytester.inline_run() if report_class is TestReport: - reports: Union[ - Sequence[TestReport], Sequence[CollectReport] - ] = reprec.getreports("pytest_runtest_logreport") + reports: Union[Sequence[TestReport], Sequence[CollectReport]] = ( + reprec.getreports("pytest_runtest_logreport") + ) # we have 3 reports: setup/call/teardown assert len(reports) == 3 # get the call report diff --git a/testing/test_runner_xunit.py b/testing/test_runner_xunit.py index 8076e20bc40..587c9eb9fef 100644 --- a/testing/test_runner_xunit.py +++ b/testing/test_runner_xunit.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Test correct setup/teardowns at module, class, and instance level.""" + from typing import List from _pytest.pytester import Pytester diff --git a/testing/test_terminal.py b/testing/test_terminal.py index b311d6c9b14..f4942510991 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Terminal reporting of the full testing process.""" + from io import StringIO import os from pathlib import Path diff --git a/testing/typing_checks.py b/testing/typing_checks.py index a2ceabcbd67..4b146a25110 100644 --- a/testing/typing_checks.py +++ b/testing/typing_checks.py @@ -4,6 +4,7 @@ This file is not executed, it is only checked by mypy to ensure that none of the code triggers any mypy errors. """ + import contextlib from typing import Optional