Fixes & improvements

This commit is contained in:
Ran Benita 2024-03-13 13:52:57 +02:00
parent 03fd05ad05
commit f934ce49bf
30 changed files with 91 additions and 94 deletions

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

@ -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

@ -1346,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

@ -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

@ -224,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
@ -234,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):
@ -252,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
@ -260,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
@ -317,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."""
@ -756,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)
@ -1274,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

@ -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(
@ -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

@ -223,8 +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 = [
f"(pytest_assertion plugin: representation of details failed: {_pytest._code.ExceptionInfo.from_current()._getreprcrash()}.", f"(pytest_assertion plugin: representation of details failed: {repr_crash}.",
" Probably an object has a faulty __repr__.)", " Probably an object has a faulty __repr__.)",
] ]

View File

@ -433,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

@ -106,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
@ -483,7 +482,10 @@ class FDCaptureBase(CaptureBase[AnyStr]):
self._state = "initialized" self._state = "initialized"
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<{self.__class__.__name__} {self.targetfd} oldfd={self.targetfd_save} _state={self._state!r} tmpfile={self.tmpfile!r}>" 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: def _assert_state(self, op: str, states: Tuple[str, ...]) -> None:
assert ( assert (
@ -616,7 +618,10 @@ 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 f"<MultiCapture out={self.out!r} err={self.err!r} in_={self.in_!r} _state={self._state!r} _in_suspended={self._in_suspended!r}>" return (
f"<MultiCapture out={self.out!r} err={self.err!r} in_={self.in_!r} "
f"_state={self._state!r} _in_suspended={self._in_suspended!r}>"
)
def start_capturing(self) -> None: def start_capturing(self) -> None:
self._state = "started" self._state = "started"
@ -724,7 +729,10 @@ 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 f"<CaptureManager _method={self._method!r} _global_capturing={self._global_capturing!r} _capture_fixture={self._capture_fixture!r}>" return (
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]:
if self.is_globally_capturing(): if self.is_globally_capturing():

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

@ -155,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

@ -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,11 +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"
f" {funcitem.nodeid}\n\n" f" {funcitem.nodeid}\n\n"
f"Requested fixture '{fixturedef.argname}' defined in:\n{getlocation(fixturedef.func, funcitem.config.rootpath)}" f"Requested fixture '{fixturedef.argname}' defined in:\n"
f"\n\nRequested here:\n{source_path_str}:{source_lineno}" f"{location}\n\n"
f"Requested here:\n"
f"{source_path_str}:{source_lineno}"
) )
fail(msg, pytrace=False) fail(msg, pytrace=False)
@ -1102,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
@ -1141,8 +1144,9 @@ 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 = (
f'Fixture "{fixture_marker.name or function.__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."

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

@ -262,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

@ -210,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
@ -513,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

@ -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,7 +433,7 @@ 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
@ -448,7 +448,7 @@ if TYPE_CHECKING:
) -> 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

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.

View File

@ -181,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

@ -85,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:
@ -396,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

@ -110,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

@ -99,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:
@ -303,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
@ -323,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)
@ -354,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

@ -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

@ -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