Merge pull request #7472 from bluetech/cleanups-4

Some minor fixes & type annotations
This commit is contained in:
Ran Benita 2020-07-11 19:05:07 +03:00 committed by GitHub
commit 7b65b2337b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 360 additions and 349 deletions

View File

@ -0,0 +1 @@
The ``exec_()`` and ``is_true()`` methods of ``_pytest._code.Frame`` have been removed.

View File

@ -51,7 +51,7 @@ if TYPE_CHECKING:
class Code:
""" wrapper around Python code objects """
"""Wrapper around Python code objects."""
def __init__(self, rawcode) -> None:
if not hasattr(rawcode, "co_filename"):
@ -69,12 +69,9 @@ class Code:
# Ignore type because of https://github.com/python/mypy/issues/4266.
__hash__ = None # type: ignore
def __ne__(self, other):
return not self == other
@property
def path(self) -> Union[py.path.local, str]:
""" return a path object pointing to source code (or a str in case
"""Return a path object pointing to source code (or a str in case
of OSError / non-existing file).
"""
if not self.raw.co_filename:
@ -92,24 +89,22 @@ class Code:
@property
def fullsource(self) -> Optional["Source"]:
""" return a _pytest._code.Source object for the full source file of the code
"""
"""Return a _pytest._code.Source object for the full source file of the code."""
full, _ = findsource(self.raw)
return full
def source(self) -> "Source":
""" return a _pytest._code.Source object for the code object's source only
"""
"""Return a _pytest._code.Source object for the code object's source only."""
# return source only for that part of code
return Source(self.raw)
def getargs(self, var: bool = False) -> Tuple[str, ...]:
""" return a tuple with the argument names for the code object
"""Return a tuple with the argument names for the code object.
if 'var' is set True also return the names of the variable and
keyword arguments when present
If 'var' is set True also return the names of the variable and
keyword arguments when present.
"""
# handfull shortcut for getting args
# Handy shortcut for getting args.
raw = self.raw
argcount = raw.co_argcount
if var:
@ -131,44 +126,31 @@ class Frame:
@property
def statement(self) -> "Source":
""" statement this frame is at """
"""Statement this frame is at."""
if self.code.fullsource is None:
return Source("")
return self.code.fullsource.getstatement(self.lineno)
def eval(self, code, **vars):
""" evaluate 'code' in the frame
"""Evaluate 'code' in the frame.
'vars' are optional additional local variables
'vars' are optional additional local variables.
returns the result of the evaluation
Returns the result of the evaluation.
"""
f_locals = self.f_locals.copy()
f_locals.update(vars)
return eval(code, self.f_globals, f_locals)
def exec_(self, code, **vars) -> None:
""" exec 'code' in the frame
'vars' are optional; additional local variables
"""
f_locals = self.f_locals.copy()
f_locals.update(vars)
exec(code, self.f_globals, f_locals)
def repr(self, object: object) -> str:
""" return a 'safe' (non-recursive, one-line) string repr for 'object'
"""
"""Return a 'safe' (non-recursive, one-line) string repr for 'object'."""
return saferepr(object)
def is_true(self, object):
return object
def getargs(self, var: bool = False):
""" return a list of tuples (name, value) for all arguments
"""Return a list of tuples (name, value) for all arguments.
if 'var' is set True also include the variable and keyword
arguments when present
If 'var' is set True, also include the variable and keyword arguments
when present.
"""
retval = []
for arg in self.code.getargs(var):
@ -180,12 +162,16 @@ class Frame:
class TracebackEntry:
""" a single entry in a traceback """
"""A single entry in a Traceback."""
_repr_style = None # type: Optional[Literal["short", "long"]]
exprinfo = None
def __init__(self, rawentry: TracebackType, excinfo=None) -> None:
def __init__(
self,
rawentry: TracebackType,
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
) -> None:
self._excinfo = excinfo
self._rawentry = rawentry
self.lineno = rawentry.tb_lineno - 1
@ -207,26 +193,26 @@ class TracebackEntry:
@property
def statement(self) -> "Source":
""" _pytest._code.Source object for the current statement """
"""_pytest._code.Source object for the current statement."""
source = self.frame.code.fullsource
assert source is not None
return source.getstatement(self.lineno)
@property
def path(self) -> Union[py.path.local, str]:
""" path to the source code """
"""Path to the source code."""
return self.frame.code.path
@property
def locals(self) -> Dict[str, Any]:
""" locals of underlying frame """
"""Locals of underlying frame."""
return self.frame.f_locals
def getfirstlinesource(self) -> int:
return self.frame.code.firstlineno
def getsource(self, astcache=None) -> Optional["Source"]:
""" return failing source code. """
"""Return failing source code."""
# we use the passed in astcache to not reparse asttrees
# within exception info printing
source = self.frame.code.fullsource
@ -251,19 +237,19 @@ class TracebackEntry:
source = property(getsource)
def ishidden(self):
""" return True if the current frame has a var __tracebackhide__
resolving to True.
def ishidden(self) -> bool:
"""Return True if the current frame has a var __tracebackhide__
resolving to True.
If __tracebackhide__ is a callable, it gets called with the
ExceptionInfo instance and can decide whether to hide the traceback.
If __tracebackhide__ is a callable, it gets called with the
ExceptionInfo instance and can decide whether to hide the traceback.
mostly for internal use
Mostly for internal use.
"""
f = self.frame
tbh = f.f_locals.get(
"__tracebackhide__", f.f_globals.get("__tracebackhide__", False)
)
) # type: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]]
if tbh and callable(tbh):
return tbh(None if self._excinfo is None else self._excinfo())
return tbh
@ -280,21 +266,19 @@ class TracebackEntry:
@property
def name(self) -> str:
""" co_name of underlying code """
"""co_name of underlying code."""
return self.frame.code.raw.co_name
class Traceback(List[TracebackEntry]):
""" Traceback objects encapsulate and offer higher level
access to Traceback entries.
"""
"""Traceback objects encapsulate and offer higher level access to Traceback entries."""
def __init__(
self,
tb: Union[TracebackType, Iterable[TracebackEntry]],
excinfo: Optional["ReferenceType[ExceptionInfo]"] = None,
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
) -> None:
""" initialize from given python traceback object and ExceptionInfo """
"""Initialize from given python traceback object and ExceptionInfo."""
self._excinfo = excinfo
if isinstance(tb, TracebackType):
@ -313,16 +297,16 @@ class Traceback(List[TracebackEntry]):
path=None,
lineno: Optional[int] = None,
firstlineno: Optional[int] = None,
excludepath=None,
excludepath: Optional[py.path.local] = None,
) -> "Traceback":
""" return a Traceback instance wrapping part of this Traceback
"""Return a Traceback instance wrapping part of this Traceback.
by providing any combination of path, lineno and firstlineno, the
first frame to start the to-be-returned traceback is determined
By providing any combination of path, lineno and firstlineno, the
first frame to start the to-be-returned traceback is determined.
this allows cutting the first part of a Traceback instance e.g.
for formatting reasons (removing some uninteresting bits that deal
with handling of the exception/traceback)
This allows cutting the first part of a Traceback instance e.g.
for formatting reasons (removing some uninteresting bits that deal
with handling of the exception/traceback).
"""
for x in self:
code = x.frame.code
@ -359,21 +343,19 @@ class Traceback(List[TracebackEntry]):
def filter(
self, fn: Callable[[TracebackEntry], bool] = lambda x: not x.ishidden()
) -> "Traceback":
""" return a Traceback instance with certain items removed
"""Return a Traceback instance with certain items removed
fn is a function that gets a single argument, a TracebackEntry
instance, and should return True when the item should be added
to the Traceback, False when not
fn is a function that gets a single argument, a TracebackEntry
instance, and should return True when the item should be added
to the Traceback, False when not.
by default this removes all the TracebackEntries which are hidden
(see ishidden() above)
By default this removes all the TracebackEntries which are hidden
(see ishidden() above).
"""
return Traceback(filter(fn, self), self._excinfo)
def getcrashentry(self) -> TracebackEntry:
""" return last non-hidden traceback entry that lead
to the exception of a traceback.
"""
"""Return last non-hidden traceback entry that lead to the exception of a traceback."""
for i in range(-1, -len(self) - 1, -1):
entry = self[i]
if not entry.ishidden():
@ -381,9 +363,8 @@ class Traceback(List[TracebackEntry]):
return self[-1]
def recursionindex(self) -> Optional[int]:
""" return the index of the frame/TracebackEntry where recursion
originates if appropriate, None if no recursion occurred
"""
"""Return the index of the frame/TracebackEntry where recursion originates if
appropriate, None if no recursion occurred."""
cache = {} # type: Dict[Tuple[Any, int, int], List[Dict[str, Any]]]
for i, entry in enumerate(self):
# id for the code.raw is needed to work around
@ -397,12 +378,10 @@ class Traceback(List[TracebackEntry]):
f = entry.frame
loc = f.f_locals
for otherloc in values:
if f.is_true(
f.eval(
co_equal,
__recursioncache_locals_1=loc,
__recursioncache_locals_2=otherloc,
)
if f.eval(
co_equal,
__recursioncache_locals_1=loc,
__recursioncache_locals_2=otherloc,
):
return i
values.append(entry.frame.f_locals)
@ -414,14 +393,12 @@ co_equal = compile(
)
_E = TypeVar("_E", bound=BaseException)
_E = TypeVar("_E", bound=BaseException, covariant=True)
@attr.s(repr=False)
class ExceptionInfo(Generic[_E]):
""" wraps sys.exc_info() objects and offers
help for navigating the traceback.
"""
"""Wraps sys.exc_info() objects and offers help for navigating the traceback."""
_assert_start_repr = "AssertionError('assert "
@ -435,13 +412,12 @@ class ExceptionInfo(Generic[_E]):
exc_info: Tuple["Type[_E]", "_E", TracebackType],
exprinfo: Optional[str] = None,
) -> "ExceptionInfo[_E]":
"""returns an ExceptionInfo for an existing exc_info tuple.
"""Returns an ExceptionInfo for an existing exc_info tuple.
.. warning::
Experimental API
:param exprinfo: a text string helping to determine if we should
strip ``AssertionError`` from the output, defaults
to the exception message/``__str__()``
@ -460,13 +436,12 @@ class ExceptionInfo(Generic[_E]):
def from_current(
cls, exprinfo: Optional[str] = None
) -> "ExceptionInfo[BaseException]":
"""returns an ExceptionInfo matching the current traceback
"""Returns an ExceptionInfo matching the current traceback.
.. warning::
Experimental API
:param exprinfo: a text string helping to determine if we should
strip ``AssertionError`` from the output, defaults
to the exception message/``__str__()``
@ -480,8 +455,7 @@ class ExceptionInfo(Generic[_E]):
@classmethod
def for_later(cls) -> "ExceptionInfo[_E]":
"""return an unfilled ExceptionInfo
"""
"""Return an unfilled ExceptionInfo."""
return cls(None)
def fill_unfilled(self, exc_info: Tuple["Type[_E]", _E, TracebackType]) -> None:
@ -491,7 +465,7 @@ class ExceptionInfo(Generic[_E]):
@property
def type(self) -> "Type[_E]":
"""the exception class"""
"""The exception class."""
assert (
self._excinfo is not None
), ".type can only be used after the context manager exits"
@ -499,7 +473,7 @@ class ExceptionInfo(Generic[_E]):
@property
def value(self) -> _E:
"""the exception value"""
"""The exception value."""
assert (
self._excinfo is not None
), ".value can only be used after the context manager exits"
@ -507,7 +481,7 @@ class ExceptionInfo(Generic[_E]):
@property
def tb(self) -> TracebackType:
"""the exception raw traceback"""
"""The exception raw traceback."""
assert (
self._excinfo is not None
), ".tb can only be used after the context manager exits"
@ -515,7 +489,7 @@ class ExceptionInfo(Generic[_E]):
@property
def typename(self) -> str:
"""the type name of the exception"""
"""The type name of the exception."""
assert (
self._excinfo is not None
), ".typename can only be used after the context manager exits"
@ -523,7 +497,7 @@ class ExceptionInfo(Generic[_E]):
@property
def traceback(self) -> Traceback:
"""the traceback"""
"""The traceback."""
if self._traceback is None:
self._traceback = Traceback(self.tb, excinfo=ref(self))
return self._traceback
@ -540,12 +514,12 @@ class ExceptionInfo(Generic[_E]):
)
def exconly(self, tryshort: bool = False) -> str:
""" return the exception as a string
"""Return the exception as a string.
when 'tryshort' resolves to True, and the exception is a
_pytest._code._AssertionError, only the actual exception part of
the exception representation is returned (so 'AssertionError: ' is
removed from the beginning)
When 'tryshort' resolves to True, and the exception is a
_pytest._code._AssertionError, only the actual exception part of
the exception representation is returned (so 'AssertionError: ' is
removed from the beginning).
"""
lines = format_exception_only(self.type, self.value)
text = "".join(lines)
@ -558,7 +532,10 @@ class ExceptionInfo(Generic[_E]):
def errisinstance(
self, exc: Union["Type[BaseException]", Tuple["Type[BaseException]", ...]]
) -> bool:
""" return True if the exception is an instance of exc """
"""Return True if the exception is an instance of exc.
Consider using ``isinstance(excinfo.value, exc)`` instead.
"""
return isinstance(self.value, exc)
def _getreprcrash(self) -> "ReprFileLocation":
@ -577,8 +554,7 @@ class ExceptionInfo(Generic[_E]):
truncate_locals: bool = True,
chain: bool = True,
) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]:
"""
Return str()able representation of this exception info.
"""Return str()able representation of this exception info.
:param bool showlocals:
Show locals per traceback entry.
@ -627,11 +603,10 @@ class ExceptionInfo(Generic[_E]):
return fmt.repr_excinfo(self)
def match(self, regexp: "Union[str, Pattern]") -> "Literal[True]":
"""
Check whether the regular expression `regexp` matches the string
"""Check whether the regular expression `regexp` matches the string
representation of the exception using :func:`python:re.search`.
If it matches `True` is returned.
If it doesn't match an `AssertionError` is raised.
If it matches `True` is returned, otherwise an `AssertionError` is raised.
"""
__tracebackhide__ = True
assert re.search(
@ -643,7 +618,7 @@ class ExceptionInfo(Generic[_E]):
@attr.s
class FormattedExcinfo:
""" presenting information about failing Functions and Generators. """
"""Presenting information about failing Functions and Generators."""
# for traceback entries
flow_marker = ">"
@ -694,7 +669,7 @@ class FormattedExcinfo:
excinfo: Optional[ExceptionInfo] = None,
short: bool = False,
) -> List[str]:
""" return formatted and marked up source lines. """
"""Return formatted and marked up source lines."""
lines = []
if source is None or line_index >= len(source.lines):
source = Source("???")
@ -804,7 +779,7 @@ class FormattedExcinfo:
if self.tbfilter:
traceback = traceback.filter()
if excinfo.errisinstance(RecursionError):
if isinstance(excinfo.value, RecursionError):
traceback, extraline = self._truncate_recursive_traceback(traceback)
else:
extraline = None
@ -935,7 +910,7 @@ class ExceptionRepr(TerminalRepr):
reprcrash = None # type: Optional[ReprFileLocation]
reprtraceback = None # type: ReprTraceback
def __attrs_post_init__(self):
def __attrs_post_init__(self) -> None:
self.sections = [] # type: List[Tuple[str, str, str]]
def addsection(self, name: str, content: str, sep: str = "-") -> None:
@ -955,7 +930,7 @@ class ExceptionChainRepr(ExceptionRepr):
]
)
def __attrs_post_init__(self):
def __attrs_post_init__(self) -> None:
super().__attrs_post_init__()
# reprcrash and reprtraceback of the outermost (the newest) exception
# in the chain
@ -1157,8 +1132,9 @@ class ReprFuncArgs(TerminalRepr):
tw.line("")
def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
""" Return source location (path, lineno) for the given object.
def getfslineno(obj: object) -> Tuple[Union[str, py.path.local], int]:
"""Return source location (path, lineno) for the given object.
If the source cannot be determined return ("", -1).
The line number is 0-based.
@ -1168,13 +1144,13 @@ def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], 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
obj = obj.place_as # type: ignore[attr-defined]
try:
code = Code(obj)
except TypeError:
try:
fn = inspect.getsourcefile(obj) or inspect.getfile(obj)
fn = inspect.getsourcefile(obj) or inspect.getfile(obj) # type: ignore[arg-type]
except TypeError:
return "", -1
@ -1186,8 +1162,8 @@ def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
except OSError:
pass
return fspath, lineno
else:
return code.path, code.firstlineno
return code.path, code.firstlineno
# relative paths that we use to filter traceback entries from appearing to the user;

View File

@ -98,12 +98,12 @@ class AlwaysDispatchingPrettyPrinter(pprint.PrettyPrinter):
level: int,
) -> None:
# Type ignored because _dispatch is private.
p = self._dispatch.get(type(object).__repr__, None) # type: ignore[attr-defined] # noqa: F821
p = self._dispatch.get(type(object).__repr__, None) # type: ignore[attr-defined]
objid = id(object)
if objid in context or p is None:
# Type ignored because _format is private.
super()._format( # type: ignore[misc] # noqa: F821
super()._format( # type: ignore[misc]
object, stream, indent, allowance, context, level,
)
return

View File

@ -80,7 +80,7 @@ class Cache:
rm_rf(d)
@staticmethod
def cache_dir_from_config(config: Config):
def cache_dir_from_config(config: Config) -> Path:
return resolve_from_str(config.getini("cache_dir"), config.rootdir)
def warn(self, fmt: str, **args: object) -> None:
@ -113,7 +113,7 @@ class Cache:
def _getvaluepath(self, key: str) -> Path:
return self._cachedir.joinpath(self._CACHE_PREFIX_VALUES, Path(key))
def get(self, key, default):
def get(self, key: str, default):
""" return cached value for the given key. If no value
was yet cached or the value cannot be read, the specified
default is returned.
@ -131,7 +131,7 @@ class Cache:
except (ValueError, OSError):
return default
def set(self, key, value) -> None:
def set(self, key: str, value: object) -> None:
""" save value for the given key.
:param key: must be a ``/`` separated value. Usually the first
@ -522,7 +522,7 @@ def cacheshow(config: Config, session: Session) -> int:
vdir = basedir / Cache._CACHE_PREFIX_VALUES
tw.sep("-", "cache values for %r" % glob)
for valpath in sorted(x for x in vdir.rglob(glob) if x.is_file()):
key = valpath.relative_to(vdir)
key = str(valpath.relative_to(vdir))
val = config.cache.get(key, dummy)
if val is dummy:
tw.line("%s contains unreadable content, will be ignored" % key)
@ -539,6 +539,6 @@ def cacheshow(config: Config, session: Session) -> int:
# if p.check(dir=1):
# print("%s/" % p.relto(basedir))
if p.is_file():
key = p.relative_to(basedir)
key = str(p.relative_to(basedir))
tw.line("{} is a file of length {:d}".format(key, p.stat().st_size))
return 0

View File

@ -821,7 +821,7 @@ class CaptureFixture:
@pytest.fixture
def capsys(request: SubRequest):
def capsys(request: SubRequest) -> Generator[CaptureFixture, None, None]:
"""Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
The captured output is made available via ``capsys.readouterr()`` method
@ -838,7 +838,7 @@ def capsys(request: SubRequest):
@pytest.fixture
def capsysbinary(request: SubRequest):
def capsysbinary(request: SubRequest) -> Generator[CaptureFixture, None, None]:
"""Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
The captured output is made available via ``capsysbinary.readouterr()``
@ -855,7 +855,7 @@ def capsysbinary(request: SubRequest):
@pytest.fixture
def capfd(request: SubRequest):
def capfd(request: SubRequest) -> Generator[CaptureFixture, None, None]:
"""Enable text capturing of writes to file descriptors ``1`` and ``2``.
The captured output is made available via ``capfd.readouterr()`` method
@ -872,7 +872,7 @@ def capfd(request: SubRequest):
@pytest.fixture
def capfdbinary(request: SubRequest):
def capfdbinary(request: SubRequest) -> Generator[CaptureFixture, None, None]:
"""Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
The captured output is made available via ``capfd.readouterr()`` method

View File

@ -146,7 +146,7 @@ class pytestPDB:
# Type ignored because mypy doesn't support "dynamic"
# inheritance like this.
class PytestPdbWrapper(pdb_cls): # type: ignore[valid-type,misc] # noqa: F821
class PytestPdbWrapper(pdb_cls): # type: ignore[valid-type,misc]
_pytest_capman = capman
_continued = False
@ -349,7 +349,7 @@ def _enter_pdb(
rep.toterminal(tw)
tw.sep(">", "entering PDB")
tb = _postmortem_traceback(excinfo)
rep._pdbshown = True # type: ignore[attr-defined] # noqa: F821
rep._pdbshown = True # type: ignore[attr-defined]
post_mortem(tb)
return rep

View File

@ -284,7 +284,7 @@ class DoctestItem(pytest.Item):
failures = [] # type: List[doctest.DocTestFailure]
# Type ignored because we change the type of `out` from what
# doctest expects.
self.runner.run(self.dtest, out=failures) # type: ignore[arg-type] # noqa: F821
self.runner.run(self.dtest, out=failures) # type: ignore[arg-type]
if failures:
raise MultipleDoctestFailures(failures)
@ -302,7 +302,7 @@ class DoctestItem(pytest.Item):
sys.stderr.write(err)
# TODO: Type ignored -- breaks Liskov Substitution.
def repr_failure( # type: ignore[override] # noqa: F821
def repr_failure( # type: ignore[override]
self, excinfo: ExceptionInfo[BaseException],
) -> Union[str, TerminalRepr]:
import doctest
@ -329,7 +329,7 @@ class DoctestItem(pytest.Item):
lineno = test.lineno + example.lineno + 1
message = type(failure).__name__
# TODO: ReprFileLocation doesn't expect a None lineno.
reprlocation = ReprFileLocation(filename, lineno, message) # type: ignore[arg-type] # noqa: F821
reprlocation = ReprFileLocation(filename, lineno, message) # type: ignore[arg-type]
checker = _get_checker()
report_choice = _get_report_choice(
self.config.getoption("doctestreport")
@ -567,9 +567,9 @@ def _setup_fixtures(doctest_item: DoctestItem) -> FixtureRequest:
def func() -> None:
pass
doctest_item.funcargs = {} # type: ignore[attr-defined] # noqa: F821
doctest_item.funcargs = {} # type: ignore[attr-defined]
fm = doctest_item.session._fixturemanager
doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined] # noqa: F821
doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined]
node=doctest_item, func=func, cls=None, funcargs=False
)
fixture_request = FixtureRequest(doctest_item)

View File

@ -248,7 +248,7 @@ def get_parametrized_fixture_keys(item: "nodes.Item", scopenum: int) -> Iterator
the specified scope. """
assert scopenum < scopenum_function # function
try:
callspec = item.callspec # type: ignore[attr-defined] # noqa: F821
callspec = item.callspec # type: ignore[attr-defined]
except AttributeError:
pass
else:
@ -266,7 +266,7 @@ def get_parametrized_fixture_keys(item: "nodes.Item", scopenum: int) -> Iterator
elif scopenum == 2: # module
key = (argname, param_index, item.fspath)
elif scopenum == 3: # class
item_cls = item.cls # type: ignore[attr-defined] # noqa: F821
item_cls = item.cls # type: ignore[attr-defined]
key = (argname, param_index, item.fspath, item_cls)
yield key
@ -477,7 +477,7 @@ class FixtureRequest:
fixturedefs = self._fixturemanager.getfixturedefs(argname, parentid)
# TODO: Fix this type ignore. Either add assert or adjust types.
# Can this be None here?
self._arg2fixturedefs[argname] = fixturedefs # type: ignore[assignment] # noqa: F821
self._arg2fixturedefs[argname] = fixturedefs # type: ignore[assignment]
# fixturedefs list is immutable so we maintain a decreasing index
index = self._arg2index.get(argname, 0) - 1
if fixturedefs is None or (-index > len(fixturedefs)):
@ -723,7 +723,7 @@ class FixtureRequest:
if scope == "package":
# FIXME: _fixturedef is not defined on FixtureRequest (this class),
# but on FixtureRequest (a subclass).
node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] # noqa: F821
node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined]
else:
node = get_scope_node(self._pyfuncitem, scope)
if node is None and scope == "class":
@ -809,7 +809,9 @@ def scope2index(scope: str, descr: str, where: Optional[str] = None) -> int:
class FixtureLookupError(LookupError):
""" could not return a requested Fixture (missing or invalid). """
def __init__(self, argname, request, msg: Optional[str] = None) -> None:
def __init__(
self, argname: Optional[str], request: FixtureRequest, msg: Optional[str] = None
) -> None:
self.argname = argname
self.request = request
self.fixturestack = request._get_fixturestack()
@ -861,7 +863,14 @@ class FixtureLookupError(LookupError):
class FixtureLookupErrorRepr(TerminalRepr):
def __init__(self, filename, firstlineno, tblines, errorstring, argname):
def __init__(
self,
filename: Union[str, py.path.local],
firstlineno: int,
tblines: Sequence[str],
errorstring: str,
argname: Optional[str],
) -> None:
self.tblines = tblines
self.errorstring = errorstring
self.filename = filename
@ -935,7 +944,7 @@ def _eval_scope_callable(
try:
# Type ignored because there is no typing mechanism to specify
# keyword arguments, currently.
result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg] # noqa: F821
result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg]
except Exception as e:
raise TypeError(
"Error evaluating {} while defining fixture '{}'.\n"
@ -1072,7 +1081,7 @@ def resolve_fixture_function(
if fixturedef.unittest:
if request.instance is not None:
# bind the unbound method to the TestCase instance
fixturefunc = fixturedef.func.__get__(request.instance) # type: ignore[union-attr] # noqa: F821
fixturefunc = fixturedef.func.__get__(request.instance) # type: ignore[union-attr]
else:
# the fixture function needs to be bound to the actual
# request.instance so that code working with "fixturedef" behaves
@ -1081,12 +1090,12 @@ def resolve_fixture_function(
# handle the case where fixture is defined not in a test class, but some other class
# (for example a plugin class with a fixture), see #2270
if hasattr(fixturefunc, "__self__") and not isinstance(
request.instance, fixturefunc.__self__.__class__ # type: ignore[union-attr] # noqa: F821
request.instance, fixturefunc.__self__.__class__ # type: ignore[union-attr]
):
return fixturefunc
fixturefunc = getimfunc(fixturedef.func)
if fixturefunc != fixturedef.func:
fixturefunc = fixturefunc.__get__(request.instance) # type: ignore[union-attr] # noqa: F821
fixturefunc = fixturefunc.__get__(request.instance) # type: ignore[union-attr]
return fixturefunc
@ -1158,7 +1167,7 @@ def wrap_function_to_error_out_if_called_directly(function, fixture_marker):
# keep reference to the original function in our own custom attribute so we don't unwrap
# further than this point and lose useful wrappings like @mock.patch (#3774)
result.__pytest_wrapped__ = _PytestWrapper(function) # type: ignore[attr-defined] # noqa: F821
result.__pytest_wrapped__ = _PytestWrapper(function) # type: ignore[attr-defined]
return result
@ -1200,7 +1209,7 @@ class FixtureFunctionMarker:
)
# Type ignored because https://github.com/python/mypy/issues/2087.
function._pytestfixturefunction = self # type: ignore[attr-defined] # noqa: F821
function._pytestfixturefunction = self # type: ignore[attr-defined]
return function
@ -1493,7 +1502,7 @@ class FixtureManager:
def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None:
nodeid = None
try:
p = py.path.local(plugin.__file__) # type: ignore[attr-defined] # noqa: F821
p = py.path.local(plugin.__file__) # type: ignore[attr-defined]
except AttributeError:
pass
else:

View File

@ -32,7 +32,6 @@ if TYPE_CHECKING:
from _pytest.main import Session
from _pytest.nodes import Collector
from _pytest.nodes import Item
from _pytest.nodes import Node
from _pytest.outcomes import Exit
from _pytest.python import Function
from _pytest.python import Metafunc
@ -827,7 +826,7 @@ def pytest_keyboard_interrupt(
def pytest_exception_interact(
node: "Node",
node: Union["Item", "Collector"],
call: "CallInfo[object]",
report: Union["CollectReport", "TestReport"],
) -> None:

View File

@ -14,6 +14,7 @@ import platform
import re
import sys
from datetime import datetime
from typing import Callable
from typing import Dict
from typing import List
from typing import Match
@ -70,7 +71,7 @@ del _legal_xml_re
_py_ext_re = re.compile(r"\.py$")
def bin_xml_escape(arg: str) -> py.xml.raw:
def bin_xml_escape(arg: object) -> py.xml.raw:
def repl(matchobj: Match[str]) -> str:
i = ord(matchobj.group())
if i <= 0xFF:
@ -78,7 +79,7 @@ def bin_xml_escape(arg: str) -> py.xml.raw:
else:
return "#x%04X" % i
return py.xml.raw(illegal_xml_re.sub(repl, py.xml.escape(arg)))
return py.xml.raw(illegal_xml_re.sub(repl, py.xml.escape(str(arg))))
def merge_family(left, right) -> None:
@ -118,10 +119,10 @@ class _NodeReporter:
self.xml.add_stats(type(node).__name__)
self.nodes.append(node)
def add_property(self, name: str, value: str) -> None:
def add_property(self, name: str, value: object) -> None:
self.properties.append((str(name), bin_xml_escape(value)))
def add_attribute(self, name: str, value: str) -> None:
def add_attribute(self, name: str, value: object) -> None:
self.attrs[str(name)] = bin_xml_escape(value)
def make_properties_node(self) -> Union[py.xml.Tag, str]:
@ -280,7 +281,7 @@ class _NodeReporter:
self.__dict__.clear()
# Type ignored becuase mypy doesn't like overriding a method.
# Also the return value doesn't match...
self.to_xml = lambda: py.xml.raw(data) # type: ignore # noqa: F821
self.to_xml = lambda: py.xml.raw(data) # type: ignore
def _warn_incompatibility_with_xunit2(
@ -301,12 +302,14 @@ def _warn_incompatibility_with_xunit2(
@pytest.fixture
def record_property(request: FixtureRequest):
"""Add an extra properties the calling test.
def record_property(request: FixtureRequest) -> Callable[[str, object], None]:
"""Add extra properties to the calling test.
User properties become part of the test report and are available to the
configured reporters, like JUnit XML.
The fixture is callable with ``(name, value)``, with value being automatically
xml-encoded.
The fixture is callable with ``name, value``. The value is automatically
XML-encoded.
Example::
@ -322,10 +325,11 @@ def record_property(request: FixtureRequest):
@pytest.fixture
def record_xml_attribute(request: FixtureRequest):
def record_xml_attribute(request: FixtureRequest) -> Callable[[str, object], None]:
"""Add extra xml attributes to the tag for the calling test.
The fixture is callable with ``(name, value)``, with value being
automatically xml-encoded
The fixture is callable with ``name, value``. The value is
automatically XML-encoded.
"""
from _pytest.warning_types import PytestExperimentalApiWarning
@ -336,7 +340,7 @@ def record_xml_attribute(request: FixtureRequest):
_warn_incompatibility_with_xunit2(request, "record_xml_attribute")
# Declare noop
def add_attr_noop(name: str, value: str) -> None:
def add_attr_noop(name: str, value: object) -> None:
pass
attr_func = add_attr_noop
@ -359,7 +363,7 @@ def _check_record_param_type(param: str, v: str) -> None:
@pytest.fixture(scope="session")
def record_testsuite_property(request: FixtureRequest):
def record_testsuite_property(request: FixtureRequest) -> Callable[[str, object], None]:
"""
Records a new ``<property>`` tag as child of the root ``<testsuite>``. This is suitable to
writing global information regarding the entire test suite, and is compatible with ``xunit2`` JUnit family.
@ -377,7 +381,7 @@ def record_testsuite_property(request: FixtureRequest):
__tracebackhide__ = True
def record_func(name: str, value: str):
def record_func(name: str, value: object) -> None:
"""noop function in case --junitxml was not passed in the command-line"""
__tracebackhide__ = True
_check_record_param_type("name", name)
@ -693,7 +697,7 @@ class LogXML:
def pytest_terminal_summary(self, terminalreporter: TerminalReporter) -> None:
terminalreporter.write_sep("-", "generated xml file: {}".format(self.logfile))
def add_global_property(self, name: str, value: str) -> None:
def add_global_property(self, name: str, value: object) -> None:
__tracebackhide__ = True
_check_record_param_type("name", name)
self.global_properties.append((name, bin_xml_escape(value)))

View File

@ -165,7 +165,7 @@ class PercentStyleMultiline(logging.PercentStyle):
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] # noqa: F821
auto_indent = self._get_auto_indent(record.auto_indent) # type: ignore[attr-defined]
else:
auto_indent = self._auto_indent
@ -755,7 +755,7 @@ class _LiveLoggingStreamHandler(logging.StreamHandler):
:param _pytest.terminal.TerminalReporter terminal_reporter:
:param _pytest.capture.CaptureManager capture_manager:
"""
logging.StreamHandler.__init__(self, stream=terminal_reporter) # type: ignore[arg-type] # noqa: F821
logging.StreamHandler.__init__(self, stream=terminal_reporter) # type: ignore[arg-type]
self.capture_manager = capture_manager
self.reset()
self.set_when(None)

View File

@ -265,7 +265,7 @@ def wrap_session(
session.exitstatus = exc.returncode
sys.stderr.write("{}: {}\n".format(type(exc).__name__, exc))
else:
if excinfo.errisinstance(SystemExit):
if isinstance(excinfo.value, SystemExit):
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")
finally:

View File

@ -125,7 +125,7 @@ class ParameterSet(
#
# @pytest.mark.parametrize(('x', 'y'), [1, 2])
# def test_foo(x, y): pass
return cls(parameterset, marks=[], id=None) # type: ignore[arg-type] # noqa: F821
return cls(parameterset, marks=[], id=None) # type: ignore[arg-type]
@staticmethod
def _parse_parametrize_args(
@ -321,7 +321,7 @@ class 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] # noqa: F821
def __call__(self, arg: _Markable) -> _Markable: # type: ignore[misc]
raise NotImplementedError()
@overload # noqa: F811

View File

@ -457,7 +457,7 @@ class Collector(Node):
raise NotImplementedError("abstract")
# TODO: This omits the style= parameter which breaks Liskov Substitution.
def repr_failure( # type: ignore[override] # noqa: F821
def repr_failure( # type: ignore[override]
self, excinfo: ExceptionInfo[BaseException]
) -> Union[str, TerminalRepr]:
"""
@ -600,7 +600,7 @@ class FSCollector(Collector):
else:
duplicate_paths.add(path)
return ihook.pytest_collect_file(path=path, parent=self) # type: ignore[no-any-return] # noqa: F723
return ihook.pytest_collect_file(path=path, parent=self) # type: ignore[no-any-return]
class File(FSCollector):

View File

@ -363,15 +363,15 @@ def make_numbered_dir_with_cleanup(
raise e
def resolve_from_str(input: str, root):
def resolve_from_str(input: str, root: py.path.local) -> Path:
assert not isinstance(input, Path), "would break on py2"
root = Path(root)
rootpath = Path(root)
input = expanduser(input)
input = expandvars(input)
if isabs(input):
return Path(input)
else:
return root.joinpath(input)
return rootpath.joinpath(input)
def fnmatch_ex(pattern: str, path) -> bool:

View File

@ -32,6 +32,7 @@ from _pytest.compat import TYPE_CHECKING
from _pytest.config import _PluggyPlugin
from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config import PytestPluginManager
from _pytest.config.argparsing import Parser
from _pytest.fixtures import FixtureRequest
from _pytest.main import Session
@ -210,7 +211,7 @@ class HookRecorder:
"""
def __init__(self, pluginmanager) -> None:
def __init__(self, pluginmanager: PytestPluginManager) -> None:
self._pluginmanager = pluginmanager
self.calls = [] # type: List[ParsedCall]
@ -376,7 +377,7 @@ def LineMatcher_fixture(request: FixtureRequest) -> "Type[LineMatcher]":
@pytest.fixture
def testdir(request: FixtureRequest, tmpdir_factory) -> "Testdir":
def testdir(request: FixtureRequest, tmpdir_factory: TempdirFactory) -> "Testdir":
"""
A :class: `TestDir` instance, that can be used to run and test pytest itself.
@ -388,7 +389,7 @@ def testdir(request: FixtureRequest, tmpdir_factory) -> "Testdir":
@pytest.fixture
def _sys_snapshot():
def _sys_snapshot() -> Generator[None, None, None]:
snappaths = SysPathsSnapshot()
snapmods = SysModulesSnapshot()
yield
@ -526,7 +527,7 @@ class CwdSnapshot:
class SysModulesSnapshot:
def __init__(self, preserve: Optional[Callable[[str], bool]] = None):
def __init__(self, preserve: Optional[Callable[[str], bool]] = None) -> None:
self.__preserve = preserve
self.__saved = dict(sys.modules)
@ -605,13 +606,13 @@ class Testdir:
# Do not use colors for inner runs by default.
mp.setenv("PY_COLORS", "0")
def __repr__(self):
def __repr__(self) -> str:
return "<Testdir {!r}>".format(self.tmpdir)
def __str__(self):
def __str__(self) -> str:
return str(self.tmpdir)
def finalize(self):
def finalize(self) -> None:
"""Clean up global state artifacts.
Some methods modify the global interpreter state and this tries to
@ -624,7 +625,7 @@ class Testdir:
self._cwd_snapshot.restore()
self.monkeypatch.undo()
def __take_sys_modules_snapshot(self):
def __take_sys_modules_snapshot(self) -> SysModulesSnapshot:
# some zope modules used by twisted-related tests keep internal state
# and can't be deleted; we had some trouble in the past with
# `zope.interface` for example
@ -633,13 +634,13 @@ class Testdir:
return SysModulesSnapshot(preserve=preserve_module)
def make_hook_recorder(self, pluginmanager):
def make_hook_recorder(self, pluginmanager: PytestPluginManager) -> HookRecorder:
"""Create a new :py:class:`HookRecorder` for a PluginManager."""
pluginmanager.reprec = reprec = HookRecorder(pluginmanager)
self.request.addfinalizer(reprec.finish_recording)
return reprec
def chdir(self):
def chdir(self) -> None:
"""Cd into the temporary directory.
This is done automatically upon instantiation.
@ -647,7 +648,7 @@ class Testdir:
"""
self.tmpdir.chdir()
def _makefile(self, ext, lines, files, encoding="utf-8"):
def _makefile(self, ext: str, lines, files, encoding: str = "utf-8"):
items = list(files.items())
def to_text(s):
@ -669,7 +670,7 @@ class Testdir:
ret = p
return ret
def makefile(self, ext, *args, **kwargs):
def makefile(self, ext: str, *args: str, **kwargs):
r"""Create new file(s) in the testdir.
:param str ext: The extension the file(s) should use, including the dot, e.g. `.py`.
@ -698,7 +699,7 @@ class Testdir:
"""Write a tox.ini file with 'source' as contents."""
return self.makefile(".ini", tox=source)
def getinicfg(self, source):
def getinicfg(self, source) -> IniConfig:
"""Return the pytest section from the tox.ini config file."""
p = self.makeini(source)
return IniConfig(p)["pytest"]
@ -748,7 +749,7 @@ class Testdir:
"""
return self._makefile(".txt", args, kwargs)
def syspathinsert(self, path=None):
def syspathinsert(self, path=None) -> None:
"""Prepend a directory to sys.path, defaults to :py:attr:`tmpdir`.
This is undone automatically when this object dies at the end of each
@ -759,11 +760,11 @@ class Testdir:
self.monkeypatch.syspath_prepend(str(path))
def mkdir(self, name):
def mkdir(self, name) -> py.path.local:
"""Create a new (sub)directory."""
return self.tmpdir.mkdir(name)
def mkpydir(self, name):
def mkpydir(self, name) -> py.path.local:
"""Create a new python package.
This creates a (sub)directory with an empty ``__init__.py`` file so it
@ -774,7 +775,7 @@ class Testdir:
p.ensure("__init__.py")
return p
def copy_example(self, name=None):
def copy_example(self, name=None) -> py.path.local:
"""Copy file from project's directory into the testdir.
:param str name: The name of the file to copy.
@ -826,7 +827,7 @@ class Testdir:
Session = Session
def getnode(self, config, arg):
def getnode(self, config: Config, arg):
"""Return the collection node of a file.
:param config: :py:class:`_pytest.config.Config` instance, see
@ -861,7 +862,7 @@ class Testdir:
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK)
return res
def genitems(self, colitems: List[Union[Item, Collector]]) -> List[Item]:
def genitems(self, colitems: Sequence[Union[Item, Collector]]) -> List[Item]:
"""Generate all test items from a collection node.
This recurses into the collection node and returns a list of all the
@ -974,7 +975,7 @@ class Testdir:
class reprec: # type: ignore
pass
reprec.ret = ret
reprec.ret = ret # type: ignore[attr-defined]
# typically we reraise keyboard interrupts from the child run
# because it's our user requesting interruption of the testing
@ -1083,7 +1084,7 @@ class Testdir:
config._do_configure()
return config
def getitem(self, source, funcname="test_func"):
def getitem(self, source, funcname: str = "test_func") -> Item:
"""Return the test item for a test function.
This writes the source to a python file and runs pytest's collection on
@ -1104,7 +1105,7 @@ class Testdir:
funcname, source, items
)
def getitems(self, source):
def getitems(self, source) -> List[Item]:
"""Return all test items collected from the module.
This writes the source to a python file and runs pytest's collection on
@ -1114,7 +1115,7 @@ class Testdir:
modcol = self.getmodulecol(source)
return self.genitems([modcol])
def getmodulecol(self, source, configargs=(), withinit=False):
def getmodulecol(self, source, configargs=(), withinit: bool = False):
"""Return the module collection node for ``source``.
This writes ``source`` to a file using :py:meth:`makepyfile` and then
@ -1199,7 +1200,9 @@ class Testdir:
return popen
def run(self, *cmdargs, timeout=None, stdin=CLOSE_STDIN) -> RunResult:
def run(
self, *cmdargs, timeout: Optional[float] = None, stdin=CLOSE_STDIN
) -> RunResult:
"""Run a command with arguments.
Run a process using subprocess.Popen saving the stdout and stderr.
@ -1238,7 +1241,7 @@ class Testdir:
if isinstance(stdin, bytes):
popen.stdin.close()
def handle_timeout():
def handle_timeout() -> None:
__tracebackhide__ = True
timeout_message = (
@ -1283,7 +1286,7 @@ class Testdir:
except UnicodeEncodeError:
print("couldn't print to {} because of encoding".format(fp))
def _getpytestargs(self):
def _getpytestargs(self) -> Tuple[str, ...]:
return sys.executable, "-mpytest"
def runpython(self, script) -> RunResult:
@ -1298,7 +1301,7 @@ class Testdir:
"""Run python -c "command", return a :py:class:`RunResult`."""
return self.run(sys.executable, "-c", command)
def runpytest_subprocess(self, *args, timeout=None) -> RunResult:
def runpytest_subprocess(self, *args, timeout: Optional[float] = None) -> RunResult:
"""Run pytest as a subprocess with given arguments.
Any plugins added to the :py:attr:`plugins` list will be added using the

View File

@ -13,7 +13,9 @@ from collections.abc import Sequence
from functools import partial
from typing import Callable
from typing import Dict
from typing import Generator
from typing import Iterable
from typing import Iterator
from typing import List
from typing import Mapping
from typing import Optional
@ -196,8 +198,8 @@ def pytest_collect_file(path: py.path.local, parent) -> Optional["Module"]:
return None
def path_matches_patterns(path, patterns):
"""Returns True if the given py.path.local matches one of the patterns in the list of globs given"""
def path_matches_patterns(path: py.path.local, patterns: Iterable[str]) -> bool:
"""Returns True if path matches any of the patterns in the list of globs given."""
return any(path.fnmatch(pattern) for pattern in patterns)
@ -297,10 +299,10 @@ class PyobjMixin:
"""Gets the underlying Python object. May be overwritten by subclasses."""
# TODO: Improve the type of `parent` such that assert/ignore aren't needed.
assert self.parent is not None
obj = self.parent.obj # type: ignore[attr-defined] # noqa: F821
obj = self.parent.obj # type: ignore[attr-defined]
return getattr(obj, self.name)
def getmodpath(self, stopatmodule=True, includemodule=False):
def getmodpath(self, stopatmodule: bool = True, includemodule: bool = False) -> str:
""" return python path relative to the containing module. """
chain = self.listchain()
chain.reverse()
@ -338,10 +340,10 @@ class PyobjMixin:
class PyCollector(PyobjMixin, nodes.Collector):
def funcnamefilter(self, name):
def funcnamefilter(self, name: str) -> bool:
return self._matches_prefix_or_glob_option("python_functions", name)
def isnosetest(self, obj):
def isnosetest(self, obj: object) -> bool:
""" Look for the __test__ attribute, which is applied by the
@nose.tools.istest decorator
"""
@ -350,10 +352,10 @@ class PyCollector(PyobjMixin, nodes.Collector):
# function) as test classes.
return safe_getattr(obj, "__test__", False) is True
def classnamefilter(self, name):
def classnamefilter(self, name: str) -> bool:
return self._matches_prefix_or_glob_option("python_classes", name)
def istestfunction(self, obj, name):
def istestfunction(self, obj: object, name: str) -> bool:
if self.funcnamefilter(name) or self.isnosetest(obj):
if isinstance(obj, staticmethod):
# static methods need to be unwrapped
@ -365,10 +367,10 @@ class PyCollector(PyobjMixin, nodes.Collector):
else:
return False
def istestclass(self, obj, name):
def istestclass(self, obj: object, name: str) -> bool:
return self.classnamefilter(name) or self.isnosetest(obj)
def _matches_prefix_or_glob_option(self, option_name, name):
def _matches_prefix_or_glob_option(self, option_name: str, name: str) -> bool:
"""
checks if the given name matches the prefix or glob-pattern defined
in ini configuration.
@ -428,7 +430,7 @@ class PyCollector(PyobjMixin, nodes.Collector):
) # type: Union[None, nodes.Item, nodes.Collector, List[Union[nodes.Item, nodes.Collector]]]
return item
def _genfunctions(self, name, funcobj):
def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]:
modulecol = self.getparent(Module)
assert modulecol is not None
module = modulecol.obj
@ -486,7 +488,7 @@ class Module(nodes.File, PyCollector):
self.session._fixturemanager.parsefactories(self)
return super().collect()
def _inject_setup_module_fixture(self):
def _inject_setup_module_fixture(self) -> None:
"""Injects a hidden autouse, module scoped fixture into the collected module object
that invokes setUpModule/tearDownModule if either or both are available.
@ -504,7 +506,7 @@ class Module(nodes.File, PyCollector):
return
@fixtures.fixture(autouse=True, scope="module")
def xunit_setup_module_fixture(request):
def xunit_setup_module_fixture(request) -> Generator[None, None, None]:
if setup_module is not None:
_call_with_optional_argument(setup_module, request.module)
yield
@ -513,7 +515,7 @@ class Module(nodes.File, PyCollector):
self.obj.__pytest_setup_module = xunit_setup_module_fixture
def _inject_setup_function_fixture(self):
def _inject_setup_function_fixture(self) -> None:
"""Injects a hidden autouse, function scoped fixture into the collected module object
that invokes setup_function/teardown_function if either or both are available.
@ -528,7 +530,7 @@ class Module(nodes.File, PyCollector):
return
@fixtures.fixture(autouse=True, scope="function")
def xunit_setup_function_fixture(request):
def xunit_setup_function_fixture(request) -> Generator[None, None, None]:
if request.instance is not None:
# in this case we are bound to an instance, so we need to let
# setup_method handle this
@ -608,7 +610,7 @@ class Package(Module):
)
self.name = os.path.basename(str(fspath.dirname))
def setup(self):
def setup(self) -> None:
# not using fixtures to call setup_module here because autouse fixtures
# from packages are not called automatically (#4085)
setup_module = _get_first_non_fixture_func(
@ -661,7 +663,7 @@ class Package(Module):
pkg_prefixes.add(path)
def _call_with_optional_argument(func, arg):
def _call_with_optional_argument(func, arg) -> None:
"""Call the given function with the given argument if func accepts one argument, otherwise
calls func without arguments"""
arg_count = func.__code__.co_argcount
@ -673,7 +675,7 @@ def _call_with_optional_argument(func, arg):
func()
def _get_first_non_fixture_func(obj, names):
def _get_first_non_fixture_func(obj: object, names: Iterable[str]):
"""Return the attribute from the given object to be used as a setup/teardown
xunit-style function, but only if not marked as a fixture to
avoid calling it twice.
@ -723,7 +725,7 @@ class Class(PyCollector):
return [Instance.from_parent(self, name="()")]
def _inject_setup_class_fixture(self):
def _inject_setup_class_fixture(self) -> None:
"""Injects a hidden autouse, class scoped fixture into the collected class object
that invokes setup_class/teardown_class if either or both are available.
@ -736,7 +738,7 @@ class Class(PyCollector):
return
@fixtures.fixture(autouse=True, scope="class")
def xunit_setup_class_fixture(cls):
def xunit_setup_class_fixture(cls) -> Generator[None, None, None]:
if setup_class is not None:
func = getimfunc(setup_class)
_call_with_optional_argument(func, self.obj)
@ -747,7 +749,7 @@ class Class(PyCollector):
self.obj.__pytest_setup_class = xunit_setup_class_fixture
def _inject_setup_method_fixture(self):
def _inject_setup_method_fixture(self) -> None:
"""Injects a hidden autouse, function scoped fixture into the collected class object
that invokes setup_method/teardown_method if either or both are available.
@ -760,7 +762,7 @@ class Class(PyCollector):
return
@fixtures.fixture(autouse=True, scope="function")
def xunit_setup_method_fixture(self, request):
def xunit_setup_method_fixture(self, request) -> Generator[None, None, None]:
method = request.function
if setup_method is not None:
func = getattr(self, "setup_method")
@ -782,7 +784,7 @@ class Instance(PyCollector):
def _getobj(self):
# TODO: Improve the type of `parent` such that assert/ignore aren't needed.
assert self.parent is not None
obj = self.parent.obj # type: ignore[attr-defined] # noqa: F821
obj = self.parent.obj # type: ignore[attr-defined]
return obj()
def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:
@ -794,16 +796,18 @@ class Instance(PyCollector):
return self.obj
def hasinit(obj):
init = getattr(obj, "__init__", None)
def hasinit(obj: object) -> bool:
init = getattr(obj, "__init__", None) # type: object
if init:
return init != object.__init__
return False
def hasnew(obj):
new = getattr(obj, "__new__", None)
def hasnew(obj: object) -> bool:
new = getattr(obj, "__new__", None) # type: object
if new:
return new != object.__new__
return False
class CallSpec2:
@ -843,7 +847,7 @@ class CallSpec2:
def setmulti2(
self,
valtypes: "Mapping[str, Literal['params', 'funcargs']]",
valtypes: Mapping[str, "Literal['params', 'funcargs']"],
argnames: typing.Sequence[str],
valset: Iterable[object],
id: str,
@ -903,7 +907,7 @@ class Metafunc:
self._arg2fixturedefs = fixtureinfo.name2fixturedefs
@property
def funcargnames(self):
def funcargnames(self) -> List[str]:
""" alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
warnings.warn(FUNCARGNAMES, stacklevel=2)
return self.fixturenames
@ -1170,7 +1174,11 @@ class Metafunc:
)
def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
def _find_parametrized_scope(
argnames: typing.Sequence[str],
arg2fixturedefs: Mapping[str, typing.Sequence[fixtures.FixtureDef]],
indirect: Union[bool, typing.Sequence[str]],
) -> "fixtures._Scope":
"""Find the most appropriate scope for a parametrized call based on its arguments.
When there's at least one direct argument, always use "function" scope.
@ -1180,9 +1188,7 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
Related to issue #1832, based on code posted by @Kingdread.
"""
from _pytest.fixtures import scopes
if isinstance(indirect, (list, tuple)):
if isinstance(indirect, Sequence):
all_arguments_are_fixtures = len(indirect) == len(argnames)
else:
all_arguments_are_fixtures = bool(indirect)
@ -1196,7 +1202,7 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
]
if used_scopes:
# Takes the most narrow scope from used fixtures
for scope in reversed(scopes):
for scope in reversed(fixtures.scopes):
if scope in used_scopes:
return scope
@ -1264,7 +1270,7 @@ def _idvalset(
ids: Optional[List[Union[None, str]]],
nodeid: Optional[str],
config: Optional[Config],
):
) -> str:
if parameterset.id is not None:
return parameterset.id
id = None if ids is None or idx >= len(ids) else ids[idx]
@ -1318,7 +1324,7 @@ def show_fixtures_per_test(config):
return wrap_session(config, _show_fixtures_per_test)
def _show_fixtures_per_test(config, session):
def _show_fixtures_per_test(config: Config, session: Session) -> None:
import _pytest.config
session.perform_collect()
@ -1330,7 +1336,7 @@ def _show_fixtures_per_test(config, session):
loc = getlocation(func, curdir)
return curdir.bestrelpath(py.path.local(loc))
def write_fixture(fixture_def):
def write_fixture(fixture_def: fixtures.FixtureDef[object]) -> None:
argname = fixture_def.argname
if verbose <= 0 and argname.startswith("_"):
return
@ -1346,18 +1352,16 @@ def _show_fixtures_per_test(config, session):
else:
tw.line(" no docstring available", red=True)
def write_item(item):
try:
info = item._fixtureinfo
except AttributeError:
# doctests items have no _fixtureinfo attribute
return
if not info.name2fixturedefs:
# this test item does not use any fixtures
def write_item(item: nodes.Item) -> None:
# Not all items have _fixtureinfo attribute.
info = getattr(item, "_fixtureinfo", None) # type: Optional[FuncFixtureInfo]
if info is None or not info.name2fixturedefs:
# This test item does not use any fixtures.
return
tw.line()
tw.sep("-", "fixtures used by {}".format(item.name))
tw.sep("-", "({})".format(get_best_relpath(item.function)))
# TODO: Fix this type ignore.
tw.sep("-", "({})".format(get_best_relpath(item.function))) # type: ignore[attr-defined]
# dict key not used in loop but needed for sorting
for _, fixturedefs in sorted(info.name2fixturedefs.items()):
assert fixturedefs is not None
@ -1448,15 +1452,15 @@ class Function(PyobjMixin, nodes.Item):
def __init__(
self,
name,
name: str,
parent,
config=None,
config: Optional[Config] = None,
callspec: Optional[CallSpec2] = None,
callobj=NOTSET,
keywords=None,
session=None,
session: Optional[Session] = None,
fixtureinfo: Optional[FuncFixtureInfo] = None,
originalname=None,
originalname: Optional[str] = None,
) -> None:
"""
param name: the full function name, including any decorations like those
@ -1533,8 +1537,8 @@ class Function(PyobjMixin, nodes.Item):
"""
return super().from_parent(parent=parent, **kw)
def _initrequest(self):
self.funcargs = {}
def _initrequest(self) -> None:
self.funcargs = {} # type: Dict[str, object]
self._request = fixtures.FixtureRequest(self)
@property
@ -1552,7 +1556,7 @@ class Function(PyobjMixin, nodes.Item):
return self
@property
def funcargnames(self):
def funcargnames(self) -> List[str]:
""" alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
warnings.warn(FUNCARGNAMES, stacklevel=2)
return self.fixturenames
@ -1589,7 +1593,7 @@ class Function(PyobjMixin, nodes.Item):
entry.set_repr_style("short")
# TODO: Type ignored -- breaks Liskov Substitution.
def repr_failure( # type: ignore[override] # noqa: F821
def repr_failure( # type: ignore[override]
self, excinfo: ExceptionInfo[BaseException],
) -> Union[str, TerminalRepr]:
style = self.config.getoption("tbstyle", "auto")

View File

@ -165,7 +165,7 @@ class WarningsRecorder(warnings.catch_warnings):
def __init__(self) -> None:
# Type ignored due to the way typeshed handles warnings.catch_warnings.
super().__init__(record=True) # type: ignore[call-arg] # noqa: F821
super().__init__(record=True) # type: ignore[call-arg]
self._entered = False
self._list = [] # type: List[warnings.WarningMessage]

View File

@ -308,7 +308,7 @@ class TestReport(BaseReport):
if not isinstance(excinfo, ExceptionInfo):
outcome = "failed"
longrepr = excinfo
elif excinfo.errisinstance(skip.Exception):
elif isinstance(excinfo.value, skip.Exception):
outcome = "skipped"
r = excinfo._getreprcrash()
longrepr = (str(r.path), r.lineno, r.message)

View File

@ -106,8 +106,8 @@ def runtestprotocol(
item: Item, log: bool = True, nextitem: Optional[Item] = None
) -> List[TestReport]:
hasrequest = hasattr(item, "_request")
if hasrequest and not item._request: # type: ignore[attr-defined] # noqa: F821
item._initrequest() # type: ignore[attr-defined] # noqa: F821
if hasrequest and not item._request: # type: ignore[attr-defined]
item._initrequest() # type: ignore[attr-defined]
rep = call_and_report(item, "setup", log)
reports = [rep]
if rep.passed:
@ -119,8 +119,8 @@ def runtestprotocol(
# after all teardown hooks have been called
# want funcargs and request info to go away
if hasrequest:
item._request = False # type: ignore[attr-defined] # noqa: F821
item.funcargs = None # type: ignore[attr-defined] # noqa: F821
item._request = False # type: ignore[attr-defined]
item.funcargs = None # type: ignore[attr-defined]
return reports
@ -215,11 +215,18 @@ def call_and_report(
def check_interactive_exception(call: "CallInfo", report: BaseReport) -> bool:
return call.excinfo is not None and not (
hasattr(report, "wasxfail")
or call.excinfo.errisinstance(Skipped)
or call.excinfo.errisinstance(bdb.BdbQuit)
)
"""Check whether the call raised an exception that should be reported as
interactive."""
if call.excinfo is None:
# Didn't raise.
return False
if hasattr(report, "wasxfail"):
# Exception was expected.
return False
if isinstance(call.excinfo.value, (Skipped, bdb.BdbQuit)):
# Special control flow exception.
return False
return True
def call_runtest_hook(
@ -287,7 +294,7 @@ class CallInfo(Generic[_T]):
result = func() # type: Optional[_T]
except BaseException:
excinfo = ExceptionInfo.from_current()
if reraise is not None and excinfo.errisinstance(reraise):
if reraise is not None and isinstance(excinfo.value, reraise):
raise
result = None
# use the perf counter
@ -325,7 +332,7 @@ def pytest_make_collect_report(collector: Collector) -> CollectReport:
if unittest is not None:
# Type ignored because unittest is loaded dynamically.
skip_exceptions.append(unittest.SkipTest) # type: ignore
if call.excinfo.errisinstance(tuple(skip_exceptions)):
if isinstance(call.excinfo.value, tuple(skip_exceptions)):
outcome = "skipped"
r_ = collector._repr_failure_py(call.excinfo, "line")
assert isinstance(r_, ExceptionChainRepr), repr(r_)
@ -415,7 +422,7 @@ class SetupState:
# check if the last collection node has raised an error
for col in self.stack:
if hasattr(col, "_prepare_exc"):
exc = col._prepare_exc # type: ignore[attr-defined] # noqa: F821
exc = col._prepare_exc # type: ignore[attr-defined]
raise exc
needed_collectors = colitem.listchain()
@ -424,7 +431,7 @@ class SetupState:
try:
col.setup()
except TEST_OUTCOME as e:
col._prepare_exc = e # type: ignore[attr-defined] # noqa: F821
col._prepare_exc = e # type: ignore[attr-defined]
raise e

View File

@ -43,7 +43,7 @@ def pytest_fixture_setup(
param = fixturedef.ids[request.param_index]
else:
param = request.param
fixturedef.cached_param = param # type: ignore[attr-defined] # noqa: F821
fixturedef.cached_param = param # type: ignore[attr-defined]
_show_fixture_action(fixturedef, "SETUP")
@ -53,7 +53,7 @@ def pytest_fixture_post_finalizer(fixturedef: FixtureDef) -> None:
if config.option.setupshow:
_show_fixture_action(fixturedef, "TEARDOWN")
if hasattr(fixturedef, "cached_param"):
del fixturedef.cached_param # type: ignore[attr-defined] # noqa: F821
del fixturedef.cached_param # type: ignore[attr-defined]
def _show_fixture_action(fixturedef: FixtureDef, msg: str) -> None:

View File

@ -56,7 +56,7 @@ def pytest_configure(config: Config) -> None:
def nop(*args, **kwargs):
pass
nop.Exception = xfail.Exception # type: ignore[attr-defined] # noqa: F821
nop.Exception = xfail.Exception # type: ignore[attr-defined]
setattr(pytest, "xfail", nop)
config.addinivalue_line(

View File

@ -1219,7 +1219,7 @@ def _get_line_with_reprcrash_message(
try:
# Type ignored intentionally -- possible AttributeError expected.
msg = rep.longrepr.reprcrash.message # type: ignore[union-attr] # noqa: F821
msg = rep.longrepr.reprcrash.message # type: ignore[union-attr]
except AttributeError:
pass
else:

View File

@ -46,7 +46,7 @@ class TempPathFactory:
given_basetemp=config.option.basetemp, trace=config.trace.get("tmpdir")
)
def _ensure_relative_to_basetemp(self, basename: str):
def _ensure_relative_to_basetemp(self, basename: str) -> str:
basename = os.path.normpath(basename)
if (self.getbasetemp() / basename).resolve().parent != self.getbasetemp():
raise ValueError(
@ -119,7 +119,7 @@ class TempdirFactory:
"""
return py.path.local(self._tmppath_factory.mktemp(basename, numbered).resolve())
def getbasetemp(self):
def getbasetemp(self) -> py.path.local:
"""backward compat wrapper for ``_tmppath_factory.getbasetemp``"""
return py.path.local(self._tmppath_factory.getbasetemp().resolve())
@ -176,7 +176,7 @@ def _mk_tmp(request: FixtureRequest, factory: TempPathFactory) -> Path:
@pytest.fixture
def tmpdir(tmp_path):
def tmpdir(tmp_path: Path) -> py.path.local:
"""Return a temporary directory path object
which is unique to each test function invocation,
created as a sub directory of the base temporary

View File

@ -102,13 +102,13 @@ class UnitTestCase(Class):
cls, "setUpClass", "tearDownClass", scope="class", pass_self=False
)
if class_fixture:
cls.__pytest_class_setup = class_fixture # type: ignore[attr-defined] # noqa: F821
cls.__pytest_class_setup = class_fixture # type: ignore[attr-defined]
method_fixture = _make_xunit_fixture(
cls, "setup_method", "teardown_method", scope="function", pass_self=True
)
if method_fixture:
cls.__pytest_method_setup = method_fixture # type: ignore[attr-defined] # noqa: F821
cls.__pytest_method_setup = method_fixture # type: ignore[attr-defined]
def _make_xunit_fixture(
@ -148,7 +148,7 @@ class TestCaseFunction(Function):
# a bound method to be called during teardown() if set (see 'runtest()')
self._explicit_tearDown = None # type: Optional[Callable[[], None]]
assert self.parent is not None
self._testcase = self.parent.obj(self.name) # type: ignore[attr-defined] # noqa: F821
self._testcase = self.parent.obj(self.name) # type: ignore[attr-defined]
self._obj = getattr(self._testcase, self.name)
if hasattr(self, "_request"):
self._request._fillfixtures()
@ -167,7 +167,7 @@ class TestCaseFunction(Function):
# unwrap potential exception info (see twisted trial support below)
rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo)
try:
excinfo = _pytest._code.ExceptionInfo(rawexcinfo) # type: ignore[arg-type] # noqa: F821
excinfo = _pytest._code.ExceptionInfo(rawexcinfo) # type: ignore[arg-type]
# invoke the attributes to trigger storing the traceback
# trial causes some issue there
excinfo.value
@ -259,7 +259,7 @@ class TestCaseFunction(Function):
# 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.
self._testcase(result=self) # type: ignore[arg-type] # noqa: F821
self._testcase(result=self) # type: ignore[arg-type]
else:
# when --pdb is given, we want to postpone calling tearDown() otherwise
# when entering the pdb prompt, tearDown() would have probably cleaned up
@ -275,7 +275,7 @@ class TestCaseFunction(Function):
# wrap_pytest_function_for_tracing replaces self.obj by a wrapper
setattr(self._testcase, self.name, self.obj)
try:
self._testcase(result=self) # type: ignore[arg-type] # noqa: F821
self._testcase(result=self) # type: ignore[arg-type]
finally:
delattr(self._testcase, self.name)
@ -302,9 +302,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None:
if (
unittest
and call.excinfo
and call.excinfo.errisinstance(
unittest.SkipTest # type: ignore[attr-defined] # noqa: F821
)
and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined]
):
excinfo = call.excinfo
# let's substitute the excinfo with a pytest.skip one

View File

@ -752,7 +752,7 @@ raise ValueError()
from _pytest._code.code import Code
monkeypatch.setattr(Code, "path", "bogus")
excinfo.traceback[0].frame.code.path = "bogus" # type: ignore[misc] # noqa: F821
excinfo.traceback[0].frame.code.path = "bogus" # type: ignore[misc]
p = FormattedExcinfo(style="short")
reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
lines = reprtb.lines

View File

@ -16,4 +16,4 @@ def test_comparing_two_different_data_classes() -> None:
left = SimpleDataObjectOne(1, "b")
right = SimpleDataObjectTwo(1, "c")
assert left != right # type: ignore[comparison-overlap] # noqa: F821
assert left != right # type: ignore[comparison-overlap]

View File

@ -34,8 +34,8 @@ def test_exceptions() -> None:
raise self.ex
class BrokenReprException(Exception):
__str__ = None # type: ignore[assignment] # noqa: F821
__repr__ = None # type: ignore[assignment] # noqa: F821
__str__ = None # type: ignore[assignment]
__repr__ = None # type: ignore[assignment]
assert "Exception" in saferepr(BrokenRepr(Exception("broken")))
s = saferepr(BrokenReprException("really broken"))
@ -44,7 +44,7 @@ def test_exceptions() -> None:
none = None
try:
none() # type: ignore[misc] # noqa: F821
none() # type: ignore[misc]
except BaseException as exc:
exp_exc = repr(exc)
obj = BrokenRepr(BrokenReprException("omg even worse"))
@ -139,7 +139,7 @@ def test_big_repr():
def test_repr_on_newstyle() -> None:
class Function:
def __repr__(self):
return "<%s>" % (self.name) # type: ignore[attr-defined] # noqa: F821
return "<%s>" % (self.name) # type: ignore[attr-defined]
assert saferepr(Function())

View File

@ -675,7 +675,11 @@ class TestFunction:
pass
"""
)
assert [x.originalname for x in items] == [
originalnames = []
for x in items:
assert isinstance(x, pytest.Function)
originalnames.append(x.originalname)
assert originalnames == [
"test_func",
"test_func",
"test_no_param",
@ -720,10 +724,10 @@ class TestSorting:
assert fn1 != fn3
for fn in fn1, fn2, fn3:
assert fn != 3 # type: ignore[comparison-overlap] # noqa: F821
assert fn != 3 # type: ignore[comparison-overlap]
assert fn != modcol
assert fn != [1, 2, 3] # type: ignore[comparison-overlap] # noqa: F821
assert [1, 2, 3] != fn # type: ignore[comparison-overlap] # noqa: F821
assert fn != [1, 2, 3] # type: ignore[comparison-overlap]
assert [1, 2, 3] != fn # type: ignore[comparison-overlap]
assert modcol != fn
def test_allow_sane_sorting_for_decorators(self, testdir):

View File

@ -3850,7 +3850,7 @@ class TestScopeOrdering:
)
testdir.runpytest()
# actual fixture execution differs: dependent fixtures must be created first ("my_tmpdir")
FIXTURE_ORDER = pytest.FIXTURE_ORDER # type: ignore[attr-defined] # noqa: F821
FIXTURE_ORDER = pytest.FIXTURE_ORDER # type: ignore[attr-defined]
assert FIXTURE_ORDER == "s1 my_tmpdir_factory p1 m1 my_tmpdir f1 f2".split()
def test_func_closure_module(self, testdir):
@ -4159,7 +4159,7 @@ def test_fixture_duplicated_arguments() -> None:
"""Raise error if there are positional and keyword arguments for the same parameter (#1682)."""
with pytest.raises(TypeError) as excinfo:
@pytest.fixture("session", scope="session") # type: ignore[call-overload] # noqa: F821
@pytest.fixture("session", scope="session") # type: ignore[call-overload]
def arg(arg):
pass
@ -4171,7 +4171,7 @@ def test_fixture_duplicated_arguments() -> None:
with pytest.raises(TypeError) as excinfo:
@pytest.fixture( # type: ignore[call-overload] # noqa: F821
@pytest.fixture( # type: ignore[call-overload]
"function",
["p1"],
True,
@ -4199,7 +4199,7 @@ def test_fixture_with_positionals() -> None:
with pytest.warns(pytest.PytestDeprecationWarning) as warnings:
@pytest.fixture("function", [0], True) # type: ignore[call-overload] # noqa: F821
@pytest.fixture("function", [0], True) # type: ignore[call-overload]
def fixture_with_positionals():
pass
@ -4213,7 +4213,7 @@ def test_fixture_with_positionals() -> None:
def test_fixture_with_too_many_positionals() -> None:
with pytest.raises(TypeError) as excinfo:
@pytest.fixture("function", [0], True, ["id"], "name", "extra") # type: ignore[call-overload] # noqa: F821
@pytest.fixture("function", [0], True, ["id"], "name", "extra") # type: ignore[call-overload]
def fixture_with_positionals():
pass

View File

@ -3,9 +3,12 @@ import re
import sys
import textwrap
from typing import Any
from typing import cast
from typing import Dict
from typing import Iterator
from typing import List
from typing import Optional
from typing import Sequence
from typing import Tuple
from typing import Union
@ -74,7 +77,7 @@ class TestMetafunc:
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
with pytest.raises(TypeError, match="^ids must be a callable or an iterable$"):
metafunc.parametrize("y", [5, 6], ids=42) # type: ignore[arg-type] # noqa: F821
metafunc.parametrize("y", [5, 6], ids=42) # type: ignore[arg-type]
def test_parametrize_error_iterator(self) -> None:
def func(x):
@ -92,7 +95,7 @@ class TestMetafunc:
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] # noqa: F821
metafunc.parametrize("x", [1, 2], ids=gen()) # type: ignore[arg-type]
assert [(x.funcargs, x.id) for x in metafunc._calls] == [
({"x": 1}, "0"),
({"x": 2}, "2"),
@ -104,7 +107,7 @@ class TestMetafunc:
r" Exc\(from_gen\) \(type: <class .*Exc'>\) at index 2"
),
):
metafunc.parametrize("x", [1, 2, 3], ids=gen()) # type: ignore[arg-type] # noqa: F821
metafunc.parametrize("x", [1, 2, 3], ids=gen()) # type: ignore[arg-type]
def test_parametrize_bad_scope(self) -> None:
def func(x):
@ -115,7 +118,7 @@ class TestMetafunc:
fail.Exception,
match=r"parametrize\(\) call in func got an unexpected scope value 'doggy'",
):
metafunc.parametrize("x", [1], scope="doggy") # type: ignore[arg-type] # noqa: F821
metafunc.parametrize("x", [1], scope="doggy") # type: ignore[arg-type]
def test_parametrize_request_name(self, testdir: Testdir) -> None:
"""Show proper error when 'request' is used as a parameter name in parametrize (#6183)"""
@ -138,12 +141,15 @@ class TestMetafunc:
class DummyFixtureDef:
scope = attr.ib()
fixtures_defs = dict(
session_fix=[DummyFixtureDef("session")],
package_fix=[DummyFixtureDef("package")],
module_fix=[DummyFixtureDef("module")],
class_fix=[DummyFixtureDef("class")],
func_fix=[DummyFixtureDef("function")],
fixtures_defs = cast(
Dict[str, Sequence[fixtures.FixtureDef]],
dict(
session_fix=[DummyFixtureDef("session")],
package_fix=[DummyFixtureDef("package")],
module_fix=[DummyFixtureDef("module")],
class_fix=[DummyFixtureDef("class")],
func_fix=[DummyFixtureDef("function")],
),
)
# use arguments to determine narrow scope; the cause of the bug is that it would look on all
@ -669,7 +675,7 @@ class TestMetafunc:
fail.Exception,
match="In func: expected Sequence or boolean for indirect, got dict",
):
metafunc.parametrize("x, y", [("a", "b")], indirect={}) # type: ignore[arg-type] # noqa: F821
metafunc.parametrize("x, y", [("a", "b")], indirect={}) # type: ignore[arg-type]
def test_parametrize_indirect_list_functional(self, testdir: Testdir) -> None:
"""

View File

@ -8,7 +8,7 @@ from _pytest.outcomes import Failed
class TestRaises:
def test_check_callable(self) -> None:
with pytest.raises(TypeError, match=r".* must be callable"):
pytest.raises(RuntimeError, "int('qwe')") # type: ignore[call-overload] # noqa: F821
pytest.raises(RuntimeError, "int('qwe')") # type: ignore[call-overload]
def test_raises(self):
excinfo = pytest.raises(ValueError, int, "qwe")
@ -30,7 +30,7 @@ class TestRaises:
def test_raises_falsey_type_error(self) -> None:
with pytest.raises(TypeError):
with pytest.raises(AssertionError, match=0): # type: ignore[call-overload] # noqa: F821
with pytest.raises(AssertionError, match=0): # type: ignore[call-overload]
raise AssertionError("ohai")
def test_raises_repr_inflight(self):
@ -128,11 +128,11 @@ class TestRaises:
def test_noclass(self) -> None:
with pytest.raises(TypeError):
pytest.raises("wrong", lambda: None) # type: ignore[call-overload] # noqa: F821
pytest.raises("wrong", lambda: None) # type: ignore[call-overload]
def test_invalid_arguments_to_raises(self) -> None:
with pytest.raises(TypeError, match="unknown"):
with pytest.raises(TypeError, unknown="bogus"): # type: ignore[call-overload] # noqa: F821
with pytest.raises(TypeError, unknown="bogus"): # type: ignore[call-overload]
raise ValueError()
def test_tuple(self):
@ -262,12 +262,12 @@ class TestRaises:
assert False, "via __class__"
with pytest.raises(AssertionError) as excinfo:
with pytest.raises(CrappyClass()): # type: ignore[call-overload] # noqa: F821
with pytest.raises(CrappyClass()): # type: ignore[call-overload]
pass
assert "via __class__" in excinfo.value.args[0]
def test_raises_context_manager_with_kwargs(self):
with pytest.raises(TypeError) as excinfo:
with pytest.raises(Exception, foo="bar"): # type: ignore[call-overload] # noqa: F821
with pytest.raises(Exception, foo="bar"): # type: ignore[call-overload]
pass
assert "Unexpected keyword arguments" in str(excinfo.value)

View File

@ -51,7 +51,7 @@ def getmsg(
exec(code, ns)
func = ns[f.__name__]
try:
func() # type: ignore[operator] # noqa: F821
func() # type: ignore[operator]
except AssertionError:
if must_pass:
pytest.fail("shouldn't have raised")
@ -174,7 +174,7 @@ class TestAssertionRewrite:
assert getmsg(f3, {"a_global": False}) == "assert False"
def f4() -> None:
assert sys == 42 # type: ignore[comparison-overlap] # noqa: F821
assert sys == 42 # type: ignore[comparison-overlap]
verbose = request.config.getoption("verbose")
msg = getmsg(f4, {"sys": sys})
@ -188,7 +188,7 @@ class TestAssertionRewrite:
assert msg == "assert sys == 42"
def f5() -> None:
assert cls == 42 # type: ignore[name-defined] # noqa: F821
assert cls == 42 # type: ignore[name-defined] # noqa: F821
class X:
pass
@ -684,7 +684,7 @@ class TestAssertionRewrite:
def test_formatchar(self) -> None:
def f() -> None:
assert "%test" == "test" # type: ignore[comparison-overlap] # noqa: F821
assert "%test" == "test" # type: ignore[comparison-overlap]
msg = getmsg(f)
assert msg is not None
@ -1264,7 +1264,7 @@ class TestEarlyRewriteBailout:
# use default patterns, otherwise we inherit pytest's testing config
hook.fnpats[:] = ["test_*.py", "*_test.py"]
monkeypatch.setattr(hook, "_find_spec", spy_find_spec)
hook.set_session(StubSession()) # type: ignore[arg-type] # noqa: F821
hook.set_session(StubSession()) # type: ignore[arg-type]
testdir.syspathinsert()
return hook

View File

@ -1537,7 +1537,7 @@ def test_encodedfile_writelines(tmpfile: BinaryIO) -> None:
ef = capture.EncodedFile(tmpfile, encoding="utf-8")
with pytest.raises(TypeError):
ef.writelines([b"line1", b"line2"])
assert ef.writelines(["line3", "line4"]) is None # type: ignore[func-returns-value] # noqa: F821
assert ef.writelines(["line3", "line4"]) is None # type: ignore[func-returns-value]
ef.flush()
tmpfile.seek(0)
assert tmpfile.read() == b"line3line4"

View File

@ -41,10 +41,10 @@ class TestCollector:
for fn in fn1, fn2, fn3:
assert isinstance(fn, pytest.Function)
assert fn != 3 # type: ignore[comparison-overlap] # noqa: F821
assert fn != 3 # type: ignore[comparison-overlap]
assert fn != modcol
assert fn != [1, 2, 3] # type: ignore[comparison-overlap] # noqa: F821
assert [1, 2, 3] != fn # type: ignore[comparison-overlap] # noqa: F821
assert fn != [1, 2, 3] # type: ignore[comparison-overlap]
assert [1, 2, 3] != fn # type: ignore[comparison-overlap]
assert modcol != fn
assert testdir.collect_by_name(modcol, "doesnotexist") is None

View File

@ -1602,7 +1602,7 @@ def test_invocation_args(testdir):
# args cannot be None
with pytest.raises(TypeError):
Config.InvocationParams(args=None, plugins=None, dir=Path()) # type: ignore[arg-type] # noqa: F821
Config.InvocationParams(args=None, plugins=None, dir=Path()) # type: ignore[arg-type]
@pytest.mark.parametrize(

View File

@ -1490,7 +1490,7 @@ def test_warning_on_unwrap_of_broken_object(
pytest.PytestWarning, match="^Got KeyError.* when unwrapping"
):
with pytest.raises(KeyError):
inspect.unwrap(bad_instance, stop=stop) # type: ignore[arg-type] # noqa: F821
inspect.unwrap(bad_instance, stop=stop) # type: ignore[arg-type]
assert inspect.unwrap.__module__ == "inspect"

View File

@ -1124,7 +1124,7 @@ def test_unicode_issue368(testdir) -> None:
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] # noqa: F821
test_report.wasxfail = ustr # type: ignore[attr-defined]
node_reporter.append_skipped(test_report)
log.pytest_sessionfinish()

View File

@ -20,7 +20,7 @@ class TestMark:
def test_pytest_mark_notcallable(self) -> None:
mark = Mark()
with pytest.raises(TypeError):
mark() # type: ignore[operator] # noqa: F821
mark() # type: ignore[operator]
def test_mark_with_param(self):
def some_function(abc):
@ -31,10 +31,10 @@ class TestMark:
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] # noqa: F821
assert marked_with_args is not some_function # type: ignore[comparison-overlap]
assert pytest.mark.foo(SomeClass) is SomeClass
assert pytest.mark.foo.with_args(SomeClass) is not SomeClass # type: ignore[comparison-overlap] # noqa: F821
assert pytest.mark.foo.with_args(SomeClass) is not SomeClass # type: ignore[comparison-overlap]
def test_pytest_mark_name_starts_with_underscore(self):
mark = Mark()
@ -1077,7 +1077,7 @@ def test_markers_from_parametrize(testdir):
def test_pytest_param_id_requires_string() -> None:
with pytest.raises(TypeError) as excinfo:
pytest.param(id=True) # type: ignore[arg-type] # noqa: F821
pytest.param(id=True) # type: ignore[arg-type]
(msg,) = excinfo.value.args
assert msg == "Expected id to be a string, got <class 'bool'>: True"

View File

@ -25,9 +25,9 @@ def test_ischildnode(baseid: str, nodeid: str, expected: bool) -> None:
def test_node_from_parent_disallowed_arguments() -> None:
with pytest.raises(TypeError, match="session is"):
nodes.Node.from_parent(None, session=None) # type: ignore[arg-type] # noqa: F821
nodes.Node.from_parent(None, session=None) # type: ignore[arg-type]
with pytest.raises(TypeError, match="config is"):
nodes.Node.from_parent(None, config=None) # type: ignore[arg-type] # noqa: F821
nodes.Node.from_parent(None, config=None) # type: ignore[arg-type]
def test_std_warn_not_pytestwarning(testdir: Testdir) -> None:
@ -38,7 +38,7 @@ def test_std_warn_not_pytestwarning(testdir: Testdir) -> None:
"""
)
with pytest.raises(ValueError, match=".*instance of PytestWarning.*"):
items[0].warn(UserWarning("some warning"))
items[0].warn(UserWarning("some warning")) # type: ignore[arg-type]
def test__check_initialpaths_for_relpath() -> None:

View File

@ -484,20 +484,20 @@ def test_linematcher_with_nonlist() -> None:
lm = LineMatcher([])
with pytest.raises(TypeError, match="invalid type for lines2: set"):
lm.fnmatch_lines(set()) # type: ignore[arg-type] # noqa: F821
lm.fnmatch_lines(set()) # type: ignore[arg-type]
with pytest.raises(TypeError, match="invalid type for lines2: dict"):
lm.fnmatch_lines({}) # type: ignore[arg-type] # noqa: F821
lm.fnmatch_lines({}) # type: ignore[arg-type]
with pytest.raises(TypeError, match="invalid type for lines2: set"):
lm.re_match_lines(set()) # type: ignore[arg-type] # noqa: F821
lm.re_match_lines(set()) # type: ignore[arg-type]
with pytest.raises(TypeError, match="invalid type for lines2: dict"):
lm.re_match_lines({}) # type: ignore[arg-type] # noqa: F821
lm.re_match_lines({}) # type: ignore[arg-type]
with pytest.raises(TypeError, match="invalid type for lines2: Source"):
lm.fnmatch_lines(Source()) # type: ignore[arg-type] # noqa: F821
lm.fnmatch_lines(Source()) # type: ignore[arg-type]
lm.fnmatch_lines([])
lm.fnmatch_lines(())
lm.fnmatch_lines("")
assert lm._getlines({}) == {} # type: ignore[arg-type,comparison-overlap] # noqa: F821
assert lm._getlines(set()) == set() # type: ignore[arg-type,comparison-overlap] # noqa: F821
assert lm._getlines({}) == {} # type: ignore[arg-type,comparison-overlap]
assert lm._getlines(set()) == set() # type: ignore[arg-type,comparison-overlap]
assert lm._getlines(Source()) == []
assert lm._getlines(Source("pass\npass")) == ["pass", "pass"]

View File

@ -884,7 +884,7 @@ def test_store_except_info_on_error() -> None:
raise IndexError("TEST")
try:
runner.pytest_runtest_call(ItemMightRaise()) # type: ignore[arg-type] # noqa: F821
runner.pytest_runtest_call(ItemMightRaise()) # type: ignore[arg-type]
except IndexError:
pass
# Check that exception info is stored on sys
@ -895,7 +895,7 @@ def test_store_except_info_on_error() -> None:
# The next run should clear the exception info stored by the previous run
ItemMightRaise.raise_error = False
runner.pytest_runtest_call(ItemMightRaise()) # type: ignore[arg-type] # noqa: F821
runner.pytest_runtest_call(ItemMightRaise()) # type: ignore[arg-type]
assert not hasattr(sys, "last_type")
assert not hasattr(sys, "last_value")
assert not hasattr(sys, "last_traceback")

View File

@ -47,7 +47,7 @@ def test_store() -> None:
# Can't accidentally add attributes to store object itself.
with pytest.raises(AttributeError):
store.foo = "nope" # type: ignore[attr-defined] # noqa: F821
store.foo = "nope" # type: ignore[attr-defined]
# No interaction with anoter store.
store2 = Store()

View File

@ -1699,7 +1699,7 @@ def test_summary_stats(
class fake_session:
testscollected = 0
tr._session = fake_session # type: ignore[assignment] # noqa: F821
tr._session = fake_session # type: ignore[assignment]
assert tr._is_last_item
# Reset cache.