Merge pull request #7472 from bluetech/cleanups-4
Some minor fixes & type annotations
This commit is contained in:
commit
7b65b2337b
|
@ -0,0 +1 @@
|
||||||
|
The ``exec_()`` and ``is_true()`` methods of ``_pytest._code.Frame`` have been removed.
|
|
@ -51,7 +51,7 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
class Code:
|
class Code:
|
||||||
""" wrapper around Python code objects """
|
"""Wrapper around Python code objects."""
|
||||||
|
|
||||||
def __init__(self, rawcode) -> None:
|
def __init__(self, rawcode) -> None:
|
||||||
if not hasattr(rawcode, "co_filename"):
|
if not hasattr(rawcode, "co_filename"):
|
||||||
|
@ -69,12 +69,9 @@ class Code:
|
||||||
# Ignore type because of https://github.com/python/mypy/issues/4266.
|
# Ignore type because of https://github.com/python/mypy/issues/4266.
|
||||||
__hash__ = None # type: ignore
|
__hash__ = None # type: ignore
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return not self == other
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self) -> Union[py.path.local, str]:
|
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).
|
of OSError / non-existing file).
|
||||||
"""
|
"""
|
||||||
if not self.raw.co_filename:
|
if not self.raw.co_filename:
|
||||||
|
@ -92,24 +89,22 @@ class Code:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fullsource(self) -> Optional["Source"]:
|
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)
|
full, _ = findsource(self.raw)
|
||||||
return full
|
return full
|
||||||
|
|
||||||
def source(self) -> "Source":
|
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 only for that part of code
|
||||||
return Source(self.raw)
|
return Source(self.raw)
|
||||||
|
|
||||||
def getargs(self, var: bool = False) -> Tuple[str, ...]:
|
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
|
If 'var' is set True also return the names of the variable and
|
||||||
keyword arguments when present
|
keyword arguments when present.
|
||||||
"""
|
"""
|
||||||
# handfull shortcut for getting args
|
# Handy shortcut for getting args.
|
||||||
raw = self.raw
|
raw = self.raw
|
||||||
argcount = raw.co_argcount
|
argcount = raw.co_argcount
|
||||||
if var:
|
if var:
|
||||||
|
@ -131,44 +126,31 @@ class Frame:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def statement(self) -> "Source":
|
def statement(self) -> "Source":
|
||||||
""" statement this frame is at """
|
"""Statement this frame is at."""
|
||||||
if self.code.fullsource is None:
|
if self.code.fullsource is None:
|
||||||
return Source("")
|
return Source("")
|
||||||
return self.code.fullsource.getstatement(self.lineno)
|
return self.code.fullsource.getstatement(self.lineno)
|
||||||
|
|
||||||
def eval(self, code, **vars):
|
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 = self.f_locals.copy()
|
||||||
f_locals.update(vars)
|
f_locals.update(vars)
|
||||||
return eval(code, self.f_globals, f_locals)
|
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:
|
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)
|
return saferepr(object)
|
||||||
|
|
||||||
def is_true(self, object):
|
|
||||||
return object
|
|
||||||
|
|
||||||
def getargs(self, var: bool = False):
|
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
|
If 'var' is set True, also include the variable and keyword arguments
|
||||||
arguments when present
|
when present.
|
||||||
"""
|
"""
|
||||||
retval = []
|
retval = []
|
||||||
for arg in self.code.getargs(var):
|
for arg in self.code.getargs(var):
|
||||||
|
@ -180,12 +162,16 @@ class Frame:
|
||||||
|
|
||||||
|
|
||||||
class TracebackEntry:
|
class TracebackEntry:
|
||||||
""" a single entry in a traceback """
|
"""A single entry in a Traceback."""
|
||||||
|
|
||||||
_repr_style = None # type: Optional[Literal["short", "long"]]
|
_repr_style = None # type: Optional[Literal["short", "long"]]
|
||||||
exprinfo = None
|
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._excinfo = excinfo
|
||||||
self._rawentry = rawentry
|
self._rawentry = rawentry
|
||||||
self.lineno = rawentry.tb_lineno - 1
|
self.lineno = rawentry.tb_lineno - 1
|
||||||
|
@ -207,26 +193,26 @@ class TracebackEntry:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def statement(self) -> "Source":
|
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
|
source = self.frame.code.fullsource
|
||||||
assert source is not None
|
assert source is not None
|
||||||
return source.getstatement(self.lineno)
|
return source.getstatement(self.lineno)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self) -> Union[py.path.local, str]:
|
def path(self) -> Union[py.path.local, str]:
|
||||||
""" path to the source code """
|
"""Path to the source code."""
|
||||||
return self.frame.code.path
|
return self.frame.code.path
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def locals(self) -> Dict[str, Any]:
|
def locals(self) -> Dict[str, Any]:
|
||||||
""" locals of underlying frame """
|
"""Locals of underlying frame."""
|
||||||
return self.frame.f_locals
|
return self.frame.f_locals
|
||||||
|
|
||||||
def getfirstlinesource(self) -> int:
|
def getfirstlinesource(self) -> int:
|
||||||
return self.frame.code.firstlineno
|
return self.frame.code.firstlineno
|
||||||
|
|
||||||
def getsource(self, astcache=None) -> Optional["Source"]:
|
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
|
# we use the passed in astcache to not reparse asttrees
|
||||||
# within exception info printing
|
# within exception info printing
|
||||||
source = self.frame.code.fullsource
|
source = self.frame.code.fullsource
|
||||||
|
@ -251,19 +237,19 @@ class TracebackEntry:
|
||||||
|
|
||||||
source = property(getsource)
|
source = property(getsource)
|
||||||
|
|
||||||
def ishidden(self):
|
def ishidden(self) -> bool:
|
||||||
""" return True if the current frame has a var __tracebackhide__
|
"""Return True if the current frame has a var __tracebackhide__
|
||||||
resolving to True.
|
resolving to True.
|
||||||
|
|
||||||
If __tracebackhide__ is a callable, it gets called with the
|
If __tracebackhide__ is a callable, it gets called with the
|
||||||
ExceptionInfo instance and can decide whether to hide the traceback.
|
ExceptionInfo instance and can decide whether to hide the traceback.
|
||||||
|
|
||||||
mostly for internal use
|
Mostly for internal use.
|
||||||
"""
|
"""
|
||||||
f = self.frame
|
f = self.frame
|
||||||
tbh = f.f_locals.get(
|
tbh = f.f_locals.get(
|
||||||
"__tracebackhide__", f.f_globals.get("__tracebackhide__", False)
|
"__tracebackhide__", f.f_globals.get("__tracebackhide__", False)
|
||||||
)
|
) # type: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]]
|
||||||
if tbh and callable(tbh):
|
if tbh and callable(tbh):
|
||||||
return tbh(None if self._excinfo is None else self._excinfo())
|
return tbh(None if self._excinfo is None else self._excinfo())
|
||||||
return tbh
|
return tbh
|
||||||
|
@ -280,21 +266,19 @@ class TracebackEntry:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
""" co_name of underlying code """
|
"""co_name of underlying code."""
|
||||||
return self.frame.code.raw.co_name
|
return self.frame.code.raw.co_name
|
||||||
|
|
||||||
|
|
||||||
class Traceback(List[TracebackEntry]):
|
class Traceback(List[TracebackEntry]):
|
||||||
""" Traceback objects encapsulate and offer higher level
|
"""Traceback objects encapsulate and offer higher level access to Traceback entries."""
|
||||||
access to Traceback entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
tb: Union[TracebackType, Iterable[TracebackEntry]],
|
tb: Union[TracebackType, Iterable[TracebackEntry]],
|
||||||
excinfo: Optional["ReferenceType[ExceptionInfo]"] = None,
|
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
""" initialize from given python traceback object and ExceptionInfo """
|
"""Initialize from given python traceback object and ExceptionInfo."""
|
||||||
self._excinfo = excinfo
|
self._excinfo = excinfo
|
||||||
if isinstance(tb, TracebackType):
|
if isinstance(tb, TracebackType):
|
||||||
|
|
||||||
|
@ -313,16 +297,16 @@ class Traceback(List[TracebackEntry]):
|
||||||
path=None,
|
path=None,
|
||||||
lineno: Optional[int] = None,
|
lineno: Optional[int] = None,
|
||||||
firstlineno: Optional[int] = None,
|
firstlineno: Optional[int] = None,
|
||||||
excludepath=None,
|
excludepath: Optional[py.path.local] = None,
|
||||||
) -> "Traceback":
|
) -> "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
|
By providing any combination of path, lineno and firstlineno, the
|
||||||
first frame to start the to-be-returned traceback is determined
|
first frame to start the to-be-returned traceback is determined.
|
||||||
|
|
||||||
this allows cutting the first part of a Traceback instance e.g.
|
This allows cutting the first part of a Traceback instance e.g.
|
||||||
for formatting reasons (removing some uninteresting bits that deal
|
for formatting reasons (removing some uninteresting bits that deal
|
||||||
with handling of the exception/traceback)
|
with handling of the exception/traceback).
|
||||||
"""
|
"""
|
||||||
for x in self:
|
for x in self:
|
||||||
code = x.frame.code
|
code = x.frame.code
|
||||||
|
@ -359,21 +343,19 @@ class Traceback(List[TracebackEntry]):
|
||||||
def filter(
|
def filter(
|
||||||
self, fn: Callable[[TracebackEntry], bool] = lambda x: not x.ishidden()
|
self, fn: Callable[[TracebackEntry], bool] = lambda x: not x.ishidden()
|
||||||
) -> "Traceback":
|
) -> "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
|
fn is a function that gets a single argument, a TracebackEntry
|
||||||
instance, and should return True when the item should be added
|
instance, and should return True when the item should be added
|
||||||
to the Traceback, False when not
|
to the Traceback, False when not.
|
||||||
|
|
||||||
by default this removes all the TracebackEntries which are hidden
|
By default this removes all the TracebackEntries which are hidden
|
||||||
(see ishidden() above)
|
(see ishidden() above).
|
||||||
"""
|
"""
|
||||||
return Traceback(filter(fn, self), self._excinfo)
|
return Traceback(filter(fn, self), self._excinfo)
|
||||||
|
|
||||||
def getcrashentry(self) -> TracebackEntry:
|
def getcrashentry(self) -> TracebackEntry:
|
||||||
""" return last non-hidden traceback entry that lead
|
"""Return last non-hidden traceback entry that lead to the exception of a traceback."""
|
||||||
to the exception of a traceback.
|
|
||||||
"""
|
|
||||||
for i in range(-1, -len(self) - 1, -1):
|
for i in range(-1, -len(self) - 1, -1):
|
||||||
entry = self[i]
|
entry = self[i]
|
||||||
if not entry.ishidden():
|
if not entry.ishidden():
|
||||||
|
@ -381,9 +363,8 @@ class Traceback(List[TracebackEntry]):
|
||||||
return self[-1]
|
return self[-1]
|
||||||
|
|
||||||
def recursionindex(self) -> Optional[int]:
|
def recursionindex(self) -> Optional[int]:
|
||||||
""" return the index of the frame/TracebackEntry where recursion
|
"""Return the index of the frame/TracebackEntry where recursion originates if
|
||||||
originates if appropriate, None if no recursion occurred
|
appropriate, None if no recursion occurred."""
|
||||||
"""
|
|
||||||
cache = {} # type: Dict[Tuple[Any, int, int], List[Dict[str, Any]]]
|
cache = {} # type: Dict[Tuple[Any, int, int], List[Dict[str, Any]]]
|
||||||
for i, entry in enumerate(self):
|
for i, entry in enumerate(self):
|
||||||
# id for the code.raw is needed to work around
|
# id for the code.raw is needed to work around
|
||||||
|
@ -397,12 +378,10 @@ class Traceback(List[TracebackEntry]):
|
||||||
f = entry.frame
|
f = entry.frame
|
||||||
loc = f.f_locals
|
loc = f.f_locals
|
||||||
for otherloc in values:
|
for otherloc in values:
|
||||||
if f.is_true(
|
if f.eval(
|
||||||
f.eval(
|
co_equal,
|
||||||
co_equal,
|
__recursioncache_locals_1=loc,
|
||||||
__recursioncache_locals_1=loc,
|
__recursioncache_locals_2=otherloc,
|
||||||
__recursioncache_locals_2=otherloc,
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
return i
|
return i
|
||||||
values.append(entry.frame.f_locals)
|
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)
|
@attr.s(repr=False)
|
||||||
class ExceptionInfo(Generic[_E]):
|
class ExceptionInfo(Generic[_E]):
|
||||||
""" wraps sys.exc_info() objects and offers
|
"""Wraps sys.exc_info() objects and offers help for navigating the traceback."""
|
||||||
help for navigating the traceback.
|
|
||||||
"""
|
|
||||||
|
|
||||||
_assert_start_repr = "AssertionError('assert "
|
_assert_start_repr = "AssertionError('assert "
|
||||||
|
|
||||||
|
@ -435,13 +412,12 @@ class ExceptionInfo(Generic[_E]):
|
||||||
exc_info: Tuple["Type[_E]", "_E", TracebackType],
|
exc_info: Tuple["Type[_E]", "_E", TracebackType],
|
||||||
exprinfo: Optional[str] = None,
|
exprinfo: Optional[str] = None,
|
||||||
) -> "ExceptionInfo[_E]":
|
) -> "ExceptionInfo[_E]":
|
||||||
"""returns an ExceptionInfo for an existing exc_info tuple.
|
"""Returns an ExceptionInfo for an existing exc_info tuple.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Experimental API
|
Experimental API
|
||||||
|
|
||||||
|
|
||||||
:param exprinfo: a text string helping to determine if we should
|
:param exprinfo: a text string helping to determine if we should
|
||||||
strip ``AssertionError`` from the output, defaults
|
strip ``AssertionError`` from the output, defaults
|
||||||
to the exception message/``__str__()``
|
to the exception message/``__str__()``
|
||||||
|
@ -460,13 +436,12 @@ class ExceptionInfo(Generic[_E]):
|
||||||
def from_current(
|
def from_current(
|
||||||
cls, exprinfo: Optional[str] = None
|
cls, exprinfo: Optional[str] = None
|
||||||
) -> "ExceptionInfo[BaseException]":
|
) -> "ExceptionInfo[BaseException]":
|
||||||
"""returns an ExceptionInfo matching the current traceback
|
"""Returns an ExceptionInfo matching the current traceback.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Experimental API
|
Experimental API
|
||||||
|
|
||||||
|
|
||||||
:param exprinfo: a text string helping to determine if we should
|
:param exprinfo: a text string helping to determine if we should
|
||||||
strip ``AssertionError`` from the output, defaults
|
strip ``AssertionError`` from the output, defaults
|
||||||
to the exception message/``__str__()``
|
to the exception message/``__str__()``
|
||||||
|
@ -480,8 +455,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def for_later(cls) -> "ExceptionInfo[_E]":
|
def for_later(cls) -> "ExceptionInfo[_E]":
|
||||||
"""return an unfilled ExceptionInfo
|
"""Return an unfilled ExceptionInfo."""
|
||||||
"""
|
|
||||||
return cls(None)
|
return cls(None)
|
||||||
|
|
||||||
def fill_unfilled(self, exc_info: Tuple["Type[_E]", _E, TracebackType]) -> None:
|
def fill_unfilled(self, exc_info: Tuple["Type[_E]", _E, TracebackType]) -> None:
|
||||||
|
@ -491,7 +465,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self) -> "Type[_E]":
|
def type(self) -> "Type[_E]":
|
||||||
"""the exception class"""
|
"""The exception class."""
|
||||||
assert (
|
assert (
|
||||||
self._excinfo is not None
|
self._excinfo is not None
|
||||||
), ".type can only be used after the context manager exits"
|
), ".type can only be used after the context manager exits"
|
||||||
|
@ -499,7 +473,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> _E:
|
def value(self) -> _E:
|
||||||
"""the exception value"""
|
"""The exception value."""
|
||||||
assert (
|
assert (
|
||||||
self._excinfo is not None
|
self._excinfo is not None
|
||||||
), ".value can only be used after the context manager exits"
|
), ".value can only be used after the context manager exits"
|
||||||
|
@ -507,7 +481,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tb(self) -> TracebackType:
|
def tb(self) -> TracebackType:
|
||||||
"""the exception raw traceback"""
|
"""The exception raw traceback."""
|
||||||
assert (
|
assert (
|
||||||
self._excinfo is not None
|
self._excinfo is not None
|
||||||
), ".tb can only be used after the context manager exits"
|
), ".tb can only be used after the context manager exits"
|
||||||
|
@ -515,7 +489,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def typename(self) -> str:
|
def typename(self) -> str:
|
||||||
"""the type name of the exception"""
|
"""The type name of the exception."""
|
||||||
assert (
|
assert (
|
||||||
self._excinfo is not None
|
self._excinfo is not None
|
||||||
), ".typename can only be used after the context manager exits"
|
), ".typename can only be used after the context manager exits"
|
||||||
|
@ -523,7 +497,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def traceback(self) -> Traceback:
|
def traceback(self) -> Traceback:
|
||||||
"""the traceback"""
|
"""The traceback."""
|
||||||
if self._traceback is None:
|
if self._traceback is None:
|
||||||
self._traceback = Traceback(self.tb, excinfo=ref(self))
|
self._traceback = Traceback(self.tb, excinfo=ref(self))
|
||||||
return self._traceback
|
return self._traceback
|
||||||
|
@ -540,12 +514,12 @@ class ExceptionInfo(Generic[_E]):
|
||||||
)
|
)
|
||||||
|
|
||||||
def exconly(self, tryshort: bool = False) -> str:
|
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
|
When 'tryshort' resolves to True, and the exception is a
|
||||||
_pytest._code._AssertionError, only the actual exception part of
|
_pytest._code._AssertionError, only the actual exception part of
|
||||||
the exception representation is returned (so 'AssertionError: ' is
|
the exception representation is returned (so 'AssertionError: ' is
|
||||||
removed from the beginning)
|
removed from the beginning).
|
||||||
"""
|
"""
|
||||||
lines = format_exception_only(self.type, self.value)
|
lines = format_exception_only(self.type, self.value)
|
||||||
text = "".join(lines)
|
text = "".join(lines)
|
||||||
|
@ -558,7 +532,10 @@ class ExceptionInfo(Generic[_E]):
|
||||||
def errisinstance(
|
def errisinstance(
|
||||||
self, exc: Union["Type[BaseException]", Tuple["Type[BaseException]", ...]]
|
self, exc: Union["Type[BaseException]", Tuple["Type[BaseException]", ...]]
|
||||||
) -> bool:
|
) -> 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)
|
return isinstance(self.value, exc)
|
||||||
|
|
||||||
def _getreprcrash(self) -> "ReprFileLocation":
|
def _getreprcrash(self) -> "ReprFileLocation":
|
||||||
|
@ -577,8 +554,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
truncate_locals: bool = True,
|
truncate_locals: bool = True,
|
||||||
chain: bool = True,
|
chain: bool = True,
|
||||||
) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]:
|
) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]:
|
||||||
"""
|
"""Return str()able representation of this exception info.
|
||||||
Return str()able representation of this exception info.
|
|
||||||
|
|
||||||
:param bool showlocals:
|
:param bool showlocals:
|
||||||
Show locals per traceback entry.
|
Show locals per traceback entry.
|
||||||
|
@ -627,11 +603,10 @@ class ExceptionInfo(Generic[_E]):
|
||||||
return fmt.repr_excinfo(self)
|
return fmt.repr_excinfo(self)
|
||||||
|
|
||||||
def match(self, regexp: "Union[str, Pattern]") -> "Literal[True]":
|
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`.
|
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
|
__tracebackhide__ = True
|
||||||
assert re.search(
|
assert re.search(
|
||||||
|
@ -643,7 +618,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class FormattedExcinfo:
|
class FormattedExcinfo:
|
||||||
""" presenting information about failing Functions and Generators. """
|
"""Presenting information about failing Functions and Generators."""
|
||||||
|
|
||||||
# for traceback entries
|
# for traceback entries
|
||||||
flow_marker = ">"
|
flow_marker = ">"
|
||||||
|
@ -694,7 +669,7 @@ class FormattedExcinfo:
|
||||||
excinfo: Optional[ExceptionInfo] = None,
|
excinfo: Optional[ExceptionInfo] = None,
|
||||||
short: bool = False,
|
short: bool = False,
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
""" return formatted and marked up source lines. """
|
"""Return formatted and marked up source lines."""
|
||||||
lines = []
|
lines = []
|
||||||
if source is None or line_index >= len(source.lines):
|
if source is None or line_index >= len(source.lines):
|
||||||
source = Source("???")
|
source = Source("???")
|
||||||
|
@ -804,7 +779,7 @@ class FormattedExcinfo:
|
||||||
if self.tbfilter:
|
if self.tbfilter:
|
||||||
traceback = traceback.filter()
|
traceback = traceback.filter()
|
||||||
|
|
||||||
if excinfo.errisinstance(RecursionError):
|
if isinstance(excinfo.value, RecursionError):
|
||||||
traceback, extraline = self._truncate_recursive_traceback(traceback)
|
traceback, extraline = self._truncate_recursive_traceback(traceback)
|
||||||
else:
|
else:
|
||||||
extraline = None
|
extraline = None
|
||||||
|
@ -935,7 +910,7 @@ class ExceptionRepr(TerminalRepr):
|
||||||
reprcrash = None # type: Optional[ReprFileLocation]
|
reprcrash = None # type: Optional[ReprFileLocation]
|
||||||
reprtraceback = None # type: ReprTraceback
|
reprtraceback = None # type: ReprTraceback
|
||||||
|
|
||||||
def __attrs_post_init__(self):
|
def __attrs_post_init__(self) -> None:
|
||||||
self.sections = [] # type: List[Tuple[str, str, str]]
|
self.sections = [] # type: List[Tuple[str, str, str]]
|
||||||
|
|
||||||
def addsection(self, name: str, content: str, sep: str = "-") -> None:
|
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__()
|
super().__attrs_post_init__()
|
||||||
# reprcrash and reprtraceback of the outermost (the newest) exception
|
# reprcrash and reprtraceback of the outermost (the newest) exception
|
||||||
# in the chain
|
# in the chain
|
||||||
|
@ -1157,8 +1132,9 @@ class ReprFuncArgs(TerminalRepr):
|
||||||
tw.line("")
|
tw.line("")
|
||||||
|
|
||||||
|
|
||||||
def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
|
def getfslineno(obj: object) -> Tuple[Union[str, py.path.local], int]:
|
||||||
""" Return source location (path, lineno) for the given object.
|
"""Return source location (path, lineno) for the given object.
|
||||||
|
|
||||||
If the source cannot be determined return ("", -1).
|
If the source cannot be determined return ("", -1).
|
||||||
|
|
||||||
The line number is 0-based.
|
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.
|
# 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
|
obj = obj.place_as # type: ignore[attr-defined]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
code = Code(obj)
|
code = Code(obj)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
try:
|
try:
|
||||||
fn = inspect.getsourcefile(obj) or inspect.getfile(obj)
|
fn = inspect.getsourcefile(obj) or inspect.getfile(obj) # type: ignore[arg-type]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return "", -1
|
return "", -1
|
||||||
|
|
||||||
|
@ -1186,8 +1162,8 @@ def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
return fspath, lineno
|
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;
|
# relative paths that we use to filter traceback entries from appearing to the user;
|
||||||
|
|
|
@ -98,12 +98,12 @@ class AlwaysDispatchingPrettyPrinter(pprint.PrettyPrinter):
|
||||||
level: int,
|
level: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
# Type ignored because _dispatch is private.
|
# 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)
|
objid = id(object)
|
||||||
if objid in context or p is None:
|
if objid in context or p is None:
|
||||||
# Type ignored because _format is private.
|
# Type ignored because _format is private.
|
||||||
super()._format( # type: ignore[misc] # noqa: F821
|
super()._format( # type: ignore[misc]
|
||||||
object, stream, indent, allowance, context, level,
|
object, stream, indent, allowance, context, level,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
|
@ -80,7 +80,7 @@ class Cache:
|
||||||
rm_rf(d)
|
rm_rf(d)
|
||||||
|
|
||||||
@staticmethod
|
@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)
|
return resolve_from_str(config.getini("cache_dir"), config.rootdir)
|
||||||
|
|
||||||
def warn(self, fmt: str, **args: object) -> None:
|
def warn(self, fmt: str, **args: object) -> None:
|
||||||
|
@ -113,7 +113,7 @@ class Cache:
|
||||||
def _getvaluepath(self, key: str) -> Path:
|
def _getvaluepath(self, key: str) -> Path:
|
||||||
return self._cachedir.joinpath(self._CACHE_PREFIX_VALUES, Path(key))
|
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
|
""" return cached value for the given key. If no value
|
||||||
was yet cached or the value cannot be read, the specified
|
was yet cached or the value cannot be read, the specified
|
||||||
default is returned.
|
default is returned.
|
||||||
|
@ -131,7 +131,7 @@ class Cache:
|
||||||
except (ValueError, OSError):
|
except (ValueError, OSError):
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def set(self, key, value) -> None:
|
def set(self, key: str, value: object) -> None:
|
||||||
""" save value for the given key.
|
""" save value for the given key.
|
||||||
|
|
||||||
:param key: must be a ``/`` separated value. Usually the first
|
: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
|
vdir = basedir / Cache._CACHE_PREFIX_VALUES
|
||||||
tw.sep("-", "cache values for %r" % glob)
|
tw.sep("-", "cache values for %r" % glob)
|
||||||
for valpath in sorted(x for x in vdir.rglob(glob) if x.is_file()):
|
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)
|
val = config.cache.get(key, dummy)
|
||||||
if val is dummy:
|
if val is dummy:
|
||||||
tw.line("%s contains unreadable content, will be ignored" % key)
|
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):
|
# if p.check(dir=1):
|
||||||
# print("%s/" % p.relto(basedir))
|
# print("%s/" % p.relto(basedir))
|
||||||
if p.is_file():
|
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))
|
tw.line("{} is a file of length {:d}".format(key, p.stat().st_size))
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -821,7 +821,7 @@ class CaptureFixture:
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@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``.
|
"""Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
|
||||||
|
|
||||||
The captured output is made available via ``capsys.readouterr()`` method
|
The captured output is made available via ``capsys.readouterr()`` method
|
||||||
|
@ -838,7 +838,7 @@ def capsys(request: SubRequest):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@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``.
|
"""Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
|
||||||
|
|
||||||
The captured output is made available via ``capsysbinary.readouterr()``
|
The captured output is made available via ``capsysbinary.readouterr()``
|
||||||
|
@ -855,7 +855,7 @@ def capsysbinary(request: SubRequest):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@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``.
|
"""Enable text capturing of writes to file descriptors ``1`` and ``2``.
|
||||||
|
|
||||||
The captured output is made available via ``capfd.readouterr()`` method
|
The captured output is made available via ``capfd.readouterr()`` method
|
||||||
|
@ -872,7 +872,7 @@ def capfd(request: SubRequest):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@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``.
|
"""Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
|
||||||
|
|
||||||
The captured output is made available via ``capfd.readouterr()`` method
|
The captured output is made available via ``capfd.readouterr()`` method
|
||||||
|
|
|
@ -146,7 +146,7 @@ class pytestPDB:
|
||||||
|
|
||||||
# Type ignored because mypy doesn't support "dynamic"
|
# Type ignored because mypy doesn't support "dynamic"
|
||||||
# inheritance like this.
|
# 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
|
_pytest_capman = capman
|
||||||
_continued = False
|
_continued = False
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ def _enter_pdb(
|
||||||
rep.toterminal(tw)
|
rep.toterminal(tw)
|
||||||
tw.sep(">", "entering PDB")
|
tw.sep(">", "entering PDB")
|
||||||
tb = _postmortem_traceback(excinfo)
|
tb = _postmortem_traceback(excinfo)
|
||||||
rep._pdbshown = True # type: ignore[attr-defined] # noqa: F821
|
rep._pdbshown = True # type: ignore[attr-defined]
|
||||||
post_mortem(tb)
|
post_mortem(tb)
|
||||||
return rep
|
return rep
|
||||||
|
|
||||||
|
|
|
@ -284,7 +284,7 @@ class DoctestItem(pytest.Item):
|
||||||
failures = [] # type: List[doctest.DocTestFailure]
|
failures = [] # type: List[doctest.DocTestFailure]
|
||||||
# Type ignored because we change the type of `out` from what
|
# Type ignored because we change the type of `out` from what
|
||||||
# doctest expects.
|
# 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:
|
if failures:
|
||||||
raise MultipleDoctestFailures(failures)
|
raise MultipleDoctestFailures(failures)
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ class DoctestItem(pytest.Item):
|
||||||
sys.stderr.write(err)
|
sys.stderr.write(err)
|
||||||
|
|
||||||
# TODO: Type ignored -- breaks Liskov Substitution.
|
# TODO: Type ignored -- breaks Liskov Substitution.
|
||||||
def repr_failure( # type: ignore[override] # noqa: F821
|
def repr_failure( # type: ignore[override]
|
||||||
self, excinfo: ExceptionInfo[BaseException],
|
self, excinfo: ExceptionInfo[BaseException],
|
||||||
) -> Union[str, TerminalRepr]:
|
) -> Union[str, TerminalRepr]:
|
||||||
import doctest
|
import doctest
|
||||||
|
@ -329,7 +329,7 @@ class DoctestItem(pytest.Item):
|
||||||
lineno = test.lineno + example.lineno + 1
|
lineno = test.lineno + example.lineno + 1
|
||||||
message = type(failure).__name__
|
message = type(failure).__name__
|
||||||
# TODO: ReprFileLocation doesn't expect a None lineno.
|
# 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()
|
checker = _get_checker()
|
||||||
report_choice = _get_report_choice(
|
report_choice = _get_report_choice(
|
||||||
self.config.getoption("doctestreport")
|
self.config.getoption("doctestreport")
|
||||||
|
@ -567,9 +567,9 @@ def _setup_fixtures(doctest_item: DoctestItem) -> FixtureRequest:
|
||||||
def func() -> None:
|
def func() -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
doctest_item.funcargs = {} # type: ignore[attr-defined] # noqa: F821
|
doctest_item.funcargs = {} # type: ignore[attr-defined]
|
||||||
fm = doctest_item.session._fixturemanager
|
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
|
node=doctest_item, func=func, cls=None, funcargs=False
|
||||||
)
|
)
|
||||||
fixture_request = FixtureRequest(doctest_item)
|
fixture_request = FixtureRequest(doctest_item)
|
||||||
|
|
|
@ -248,7 +248,7 @@ def get_parametrized_fixture_keys(item: "nodes.Item", scopenum: int) -> Iterator
|
||||||
the specified scope. """
|
the specified scope. """
|
||||||
assert scopenum < scopenum_function # function
|
assert scopenum < scopenum_function # function
|
||||||
try:
|
try:
|
||||||
callspec = item.callspec # type: ignore[attr-defined] # noqa: F821
|
callspec = item.callspec # type: ignore[attr-defined]
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -266,7 +266,7 @@ def get_parametrized_fixture_keys(item: "nodes.Item", scopenum: int) -> Iterator
|
||||||
elif scopenum == 2: # module
|
elif scopenum == 2: # module
|
||||||
key = (argname, param_index, item.fspath)
|
key = (argname, param_index, item.fspath)
|
||||||
elif scopenum == 3: # class
|
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)
|
key = (argname, param_index, item.fspath, item_cls)
|
||||||
yield key
|
yield key
|
||||||
|
|
||||||
|
@ -477,7 +477,7 @@ class FixtureRequest:
|
||||||
fixturedefs = self._fixturemanager.getfixturedefs(argname, parentid)
|
fixturedefs = self._fixturemanager.getfixturedefs(argname, parentid)
|
||||||
# TODO: Fix this type ignore. Either add assert or adjust types.
|
# TODO: Fix this type ignore. Either add assert or adjust types.
|
||||||
# Can this be None here?
|
# 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
|
# fixturedefs list is immutable so we maintain a decreasing index
|
||||||
index = self._arg2index.get(argname, 0) - 1
|
index = self._arg2index.get(argname, 0) - 1
|
||||||
if fixturedefs is None or (-index > len(fixturedefs)):
|
if fixturedefs is None or (-index > len(fixturedefs)):
|
||||||
|
@ -723,7 +723,7 @@ class FixtureRequest:
|
||||||
if scope == "package":
|
if scope == "package":
|
||||||
# FIXME: _fixturedef is not defined on FixtureRequest (this class),
|
# FIXME: _fixturedef is not defined on FixtureRequest (this class),
|
||||||
# but on FixtureRequest (a subclass).
|
# 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:
|
else:
|
||||||
node = get_scope_node(self._pyfuncitem, scope)
|
node = get_scope_node(self._pyfuncitem, scope)
|
||||||
if node is None and scope == "class":
|
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):
|
class FixtureLookupError(LookupError):
|
||||||
""" could not return a requested Fixture (missing or invalid). """
|
""" 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.argname = argname
|
||||||
self.request = request
|
self.request = request
|
||||||
self.fixturestack = request._get_fixturestack()
|
self.fixturestack = request._get_fixturestack()
|
||||||
|
@ -861,7 +863,14 @@ class FixtureLookupError(LookupError):
|
||||||
|
|
||||||
|
|
||||||
class FixtureLookupErrorRepr(TerminalRepr):
|
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.tblines = tblines
|
||||||
self.errorstring = errorstring
|
self.errorstring = errorstring
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
@ -935,7 +944,7 @@ def _eval_scope_callable(
|
||||||
try:
|
try:
|
||||||
# Type ignored because there is no typing mechanism to specify
|
# Type ignored because there is no typing mechanism to specify
|
||||||
# keyword arguments, currently.
|
# 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:
|
except Exception as e:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"Error evaluating {} while defining fixture '{}'.\n"
|
"Error evaluating {} while defining fixture '{}'.\n"
|
||||||
|
@ -1072,7 +1081,7 @@ def resolve_fixture_function(
|
||||||
if fixturedef.unittest:
|
if fixturedef.unittest:
|
||||||
if request.instance is not None:
|
if request.instance is not None:
|
||||||
# bind the unbound method to the TestCase instance
|
# 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:
|
else:
|
||||||
# the fixture function needs to be bound to the actual
|
# the fixture function needs to be bound to the actual
|
||||||
# request.instance so that code working with "fixturedef" behaves
|
# 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
|
# 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
|
# (for example a plugin class with a fixture), see #2270
|
||||||
if hasattr(fixturefunc, "__self__") and not isinstance(
|
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
|
return fixturefunc
|
||||||
fixturefunc = getimfunc(fixturedef.func)
|
fixturefunc = getimfunc(fixturedef.func)
|
||||||
if fixturefunc != 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
|
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
|
# 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)
|
# 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
|
return result
|
||||||
|
|
||||||
|
@ -1200,7 +1209,7 @@ class FixtureFunctionMarker:
|
||||||
)
|
)
|
||||||
|
|
||||||
# Type ignored because https://github.com/python/mypy/issues/2087.
|
# 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
|
return function
|
||||||
|
|
||||||
|
|
||||||
|
@ -1493,7 +1502,7 @@ class FixtureManager:
|
||||||
def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None:
|
def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None:
|
||||||
nodeid = None
|
nodeid = None
|
||||||
try:
|
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:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -32,7 +32,6 @@ if TYPE_CHECKING:
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.nodes import Collector
|
from _pytest.nodes import Collector
|
||||||
from _pytest.nodes import Item
|
from _pytest.nodes import Item
|
||||||
from _pytest.nodes import Node
|
|
||||||
from _pytest.outcomes import Exit
|
from _pytest.outcomes import Exit
|
||||||
from _pytest.python import Function
|
from _pytest.python import Function
|
||||||
from _pytest.python import Metafunc
|
from _pytest.python import Metafunc
|
||||||
|
@ -827,7 +826,7 @@ def pytest_keyboard_interrupt(
|
||||||
|
|
||||||
|
|
||||||
def pytest_exception_interact(
|
def pytest_exception_interact(
|
||||||
node: "Node",
|
node: Union["Item", "Collector"],
|
||||||
call: "CallInfo[object]",
|
call: "CallInfo[object]",
|
||||||
report: Union["CollectReport", "TestReport"],
|
report: Union["CollectReport", "TestReport"],
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
|
@ -14,6 +14,7 @@ import platform
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Match
|
from typing import Match
|
||||||
|
@ -70,7 +71,7 @@ del _legal_xml_re
|
||||||
_py_ext_re = re.compile(r"\.py$")
|
_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:
|
def repl(matchobj: Match[str]) -> str:
|
||||||
i = ord(matchobj.group())
|
i = ord(matchobj.group())
|
||||||
if i <= 0xFF:
|
if i <= 0xFF:
|
||||||
|
@ -78,7 +79,7 @@ def bin_xml_escape(arg: str) -> py.xml.raw:
|
||||||
else:
|
else:
|
||||||
return "#x%04X" % i
|
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:
|
def merge_family(left, right) -> None:
|
||||||
|
@ -118,10 +119,10 @@ class _NodeReporter:
|
||||||
self.xml.add_stats(type(node).__name__)
|
self.xml.add_stats(type(node).__name__)
|
||||||
self.nodes.append(node)
|
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)))
|
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)
|
self.attrs[str(name)] = bin_xml_escape(value)
|
||||||
|
|
||||||
def make_properties_node(self) -> Union[py.xml.Tag, str]:
|
def make_properties_node(self) -> Union[py.xml.Tag, str]:
|
||||||
|
@ -280,7 +281,7 @@ class _NodeReporter:
|
||||||
self.__dict__.clear()
|
self.__dict__.clear()
|
||||||
# Type ignored becuase mypy doesn't like overriding a method.
|
# Type ignored becuase 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: py.xml.raw(data) # type: ignore # noqa: F821
|
self.to_xml = lambda: py.xml.raw(data) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def _warn_incompatibility_with_xunit2(
|
def _warn_incompatibility_with_xunit2(
|
||||||
|
@ -301,12 +302,14 @@ def _warn_incompatibility_with_xunit2(
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def record_property(request: FixtureRequest):
|
def record_property(request: FixtureRequest) -> Callable[[str, object], None]:
|
||||||
"""Add an extra properties the calling test.
|
"""Add extra properties to the calling test.
|
||||||
|
|
||||||
User properties become part of the test report and are available to the
|
User properties become part of the test report and are available to the
|
||||||
configured reporters, like JUnit XML.
|
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::
|
Example::
|
||||||
|
|
||||||
|
@ -322,10 +325,11 @@ def record_property(request: FixtureRequest):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@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.
|
"""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
|
from _pytest.warning_types import PytestExperimentalApiWarning
|
||||||
|
|
||||||
|
@ -336,7 +340,7 @@ def record_xml_attribute(request: FixtureRequest):
|
||||||
_warn_incompatibility_with_xunit2(request, "record_xml_attribute")
|
_warn_incompatibility_with_xunit2(request, "record_xml_attribute")
|
||||||
|
|
||||||
# Declare noop
|
# Declare noop
|
||||||
def add_attr_noop(name: str, value: str) -> None:
|
def add_attr_noop(name: str, value: object) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
attr_func = add_attr_noop
|
attr_func = add_attr_noop
|
||||||
|
@ -359,7 +363,7 @@ def _check_record_param_type(param: str, v: str) -> None:
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@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
|
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.
|
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
|
__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"""
|
"""noop function in case --junitxml was not passed in the command-line"""
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
_check_record_param_type("name", name)
|
_check_record_param_type("name", name)
|
||||||
|
@ -693,7 +697,7 @@ class LogXML:
|
||||||
def pytest_terminal_summary(self, terminalreporter: TerminalReporter) -> None:
|
def pytest_terminal_summary(self, terminalreporter: TerminalReporter) -> None:
|
||||||
terminalreporter.write_sep("-", "generated xml file: {}".format(self.logfile))
|
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
|
__tracebackhide__ = True
|
||||||
_check_record_param_type("name", name)
|
_check_record_param_type("name", name)
|
||||||
self.global_properties.append((name, bin_xml_escape(value)))
|
self.global_properties.append((name, bin_xml_escape(value)))
|
||||||
|
|
|
@ -165,7 +165,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] # noqa: F821
|
auto_indent = self._get_auto_indent(record.auto_indent) # type: ignore[attr-defined]
|
||||||
else:
|
else:
|
||||||
auto_indent = self._auto_indent
|
auto_indent = self._auto_indent
|
||||||
|
|
||||||
|
@ -755,7 +755,7 @@ class _LiveLoggingStreamHandler(logging.StreamHandler):
|
||||||
:param _pytest.terminal.TerminalReporter terminal_reporter:
|
:param _pytest.terminal.TerminalReporter terminal_reporter:
|
||||||
:param _pytest.capture.CaptureManager capture_manager:
|
: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.capture_manager = capture_manager
|
||||||
self.reset()
|
self.reset()
|
||||||
self.set_when(None)
|
self.set_when(None)
|
||||||
|
|
|
@ -265,7 +265,7 @@ def wrap_session(
|
||||||
session.exitstatus = exc.returncode
|
session.exitstatus = exc.returncode
|
||||||
sys.stderr.write("{}: {}\n".format(type(exc).__name__, exc))
|
sys.stderr.write("{}: {}\n".format(type(exc).__name__, exc))
|
||||||
else:
|
else:
|
||||||
if excinfo.errisinstance(SystemExit):
|
if isinstance(excinfo.value, SystemExit):
|
||||||
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")
|
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -125,7 +125,7 @@ class ParameterSet(
|
||||||
#
|
#
|
||||||
# @pytest.mark.parametrize(('x', 'y'), [1, 2])
|
# @pytest.mark.parametrize(('x', 'y'), [1, 2])
|
||||||
# def test_foo(x, y): pass
|
# 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
|
@staticmethod
|
||||||
def _parse_parametrize_args(
|
def _parse_parametrize_args(
|
||||||
|
@ -321,7 +321,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] # noqa: F821
|
def __call__(self, arg: _Markable) -> _Markable: # type: ignore[misc]
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@overload # noqa: F811
|
@overload # noqa: F811
|
||||||
|
|
|
@ -457,7 +457,7 @@ class Collector(Node):
|
||||||
raise NotImplementedError("abstract")
|
raise NotImplementedError("abstract")
|
||||||
|
|
||||||
# TODO: This omits the style= parameter which breaks Liskov Substitution.
|
# 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]
|
self, excinfo: ExceptionInfo[BaseException]
|
||||||
) -> Union[str, TerminalRepr]:
|
) -> Union[str, TerminalRepr]:
|
||||||
"""
|
"""
|
||||||
|
@ -600,7 +600,7 @@ class FSCollector(Collector):
|
||||||
else:
|
else:
|
||||||
duplicate_paths.add(path)
|
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):
|
class File(FSCollector):
|
||||||
|
|
|
@ -363,15 +363,15 @@ def make_numbered_dir_with_cleanup(
|
||||||
raise e
|
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"
|
assert not isinstance(input, Path), "would break on py2"
|
||||||
root = Path(root)
|
rootpath = Path(root)
|
||||||
input = expanduser(input)
|
input = expanduser(input)
|
||||||
input = expandvars(input)
|
input = expandvars(input)
|
||||||
if isabs(input):
|
if isabs(input):
|
||||||
return Path(input)
|
return Path(input)
|
||||||
else:
|
else:
|
||||||
return root.joinpath(input)
|
return rootpath.joinpath(input)
|
||||||
|
|
||||||
|
|
||||||
def fnmatch_ex(pattern: str, path) -> bool:
|
def fnmatch_ex(pattern: str, path) -> bool:
|
||||||
|
|
|
@ -32,6 +32,7 @@ from _pytest.compat import TYPE_CHECKING
|
||||||
from _pytest.config import _PluggyPlugin
|
from _pytest.config import _PluggyPlugin
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
from _pytest.config import PytestPluginManager
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
from _pytest.fixtures import FixtureRequest
|
from _pytest.fixtures import FixtureRequest
|
||||||
from _pytest.main import Session
|
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._pluginmanager = pluginmanager
|
||||||
self.calls = [] # type: List[ParsedCall]
|
self.calls = [] # type: List[ParsedCall]
|
||||||
|
|
||||||
|
@ -376,7 +377,7 @@ def LineMatcher_fixture(request: FixtureRequest) -> "Type[LineMatcher]":
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@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.
|
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
|
@pytest.fixture
|
||||||
def _sys_snapshot():
|
def _sys_snapshot() -> Generator[None, None, None]:
|
||||||
snappaths = SysPathsSnapshot()
|
snappaths = SysPathsSnapshot()
|
||||||
snapmods = SysModulesSnapshot()
|
snapmods = SysModulesSnapshot()
|
||||||
yield
|
yield
|
||||||
|
@ -526,7 +527,7 @@ class CwdSnapshot:
|
||||||
|
|
||||||
|
|
||||||
class SysModulesSnapshot:
|
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.__preserve = preserve
|
||||||
self.__saved = dict(sys.modules)
|
self.__saved = dict(sys.modules)
|
||||||
|
|
||||||
|
@ -605,13 +606,13 @@ class Testdir:
|
||||||
# Do not use colors for inner runs by default.
|
# Do not use colors for inner runs by default.
|
||||||
mp.setenv("PY_COLORS", "0")
|
mp.setenv("PY_COLORS", "0")
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return "<Testdir {!r}>".format(self.tmpdir)
|
return "<Testdir {!r}>".format(self.tmpdir)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return str(self.tmpdir)
|
return str(self.tmpdir)
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self) -> None:
|
||||||
"""Clean up global state artifacts.
|
"""Clean up global state artifacts.
|
||||||
|
|
||||||
Some methods modify the global interpreter state and this tries to
|
Some methods modify the global interpreter state and this tries to
|
||||||
|
@ -624,7 +625,7 @@ class Testdir:
|
||||||
self._cwd_snapshot.restore()
|
self._cwd_snapshot.restore()
|
||||||
self.monkeypatch.undo()
|
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
|
# some zope modules used by twisted-related tests keep internal state
|
||||||
# and can't be deleted; we had some trouble in the past with
|
# and can't be deleted; we had some trouble in the past with
|
||||||
# `zope.interface` for example
|
# `zope.interface` for example
|
||||||
|
@ -633,13 +634,13 @@ class Testdir:
|
||||||
|
|
||||||
return SysModulesSnapshot(preserve=preserve_module)
|
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."""
|
"""Create a new :py:class:`HookRecorder` for a PluginManager."""
|
||||||
pluginmanager.reprec = reprec = HookRecorder(pluginmanager)
|
pluginmanager.reprec = reprec = HookRecorder(pluginmanager)
|
||||||
self.request.addfinalizer(reprec.finish_recording)
|
self.request.addfinalizer(reprec.finish_recording)
|
||||||
return reprec
|
return reprec
|
||||||
|
|
||||||
def chdir(self):
|
def chdir(self) -> None:
|
||||||
"""Cd into the temporary directory.
|
"""Cd into the temporary directory.
|
||||||
|
|
||||||
This is done automatically upon instantiation.
|
This is done automatically upon instantiation.
|
||||||
|
@ -647,7 +648,7 @@ class Testdir:
|
||||||
"""
|
"""
|
||||||
self.tmpdir.chdir()
|
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())
|
items = list(files.items())
|
||||||
|
|
||||||
def to_text(s):
|
def to_text(s):
|
||||||
|
@ -669,7 +670,7 @@ class Testdir:
|
||||||
ret = p
|
ret = p
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def makefile(self, ext, *args, **kwargs):
|
def makefile(self, ext: str, *args: str, **kwargs):
|
||||||
r"""Create new file(s) in the testdir.
|
r"""Create new file(s) in the testdir.
|
||||||
|
|
||||||
:param str ext: The extension the file(s) should use, including the dot, e.g. `.py`.
|
: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."""
|
"""Write a tox.ini file with 'source' as contents."""
|
||||||
return self.makefile(".ini", tox=source)
|
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."""
|
"""Return the pytest section from the tox.ini config file."""
|
||||||
p = self.makeini(source)
|
p = self.makeini(source)
|
||||||
return IniConfig(p)["pytest"]
|
return IniConfig(p)["pytest"]
|
||||||
|
@ -748,7 +749,7 @@ class Testdir:
|
||||||
"""
|
"""
|
||||||
return self._makefile(".txt", args, kwargs)
|
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`.
|
"""Prepend a directory to sys.path, defaults to :py:attr:`tmpdir`.
|
||||||
|
|
||||||
This is undone automatically when this object dies at the end of each
|
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))
|
self.monkeypatch.syspath_prepend(str(path))
|
||||||
|
|
||||||
def mkdir(self, name):
|
def mkdir(self, name) -> py.path.local:
|
||||||
"""Create a new (sub)directory."""
|
"""Create a new (sub)directory."""
|
||||||
return self.tmpdir.mkdir(name)
|
return self.tmpdir.mkdir(name)
|
||||||
|
|
||||||
def mkpydir(self, name):
|
def mkpydir(self, name) -> py.path.local:
|
||||||
"""Create a new python package.
|
"""Create a new python package.
|
||||||
|
|
||||||
This creates a (sub)directory with an empty ``__init__.py`` file so it
|
This creates a (sub)directory with an empty ``__init__.py`` file so it
|
||||||
|
@ -774,7 +775,7 @@ class Testdir:
|
||||||
p.ensure("__init__.py")
|
p.ensure("__init__.py")
|
||||||
return p
|
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.
|
"""Copy file from project's directory into the testdir.
|
||||||
|
|
||||||
:param str name: The name of the file to copy.
|
:param str name: The name of the file to copy.
|
||||||
|
@ -826,7 +827,7 @@ class Testdir:
|
||||||
|
|
||||||
Session = Session
|
Session = Session
|
||||||
|
|
||||||
def getnode(self, config, arg):
|
def getnode(self, config: Config, arg):
|
||||||
"""Return the collection node of a file.
|
"""Return the collection node of a file.
|
||||||
|
|
||||||
:param config: :py:class:`_pytest.config.Config` instance, see
|
:param config: :py:class:`_pytest.config.Config` instance, see
|
||||||
|
@ -861,7 +862,7 @@ class Testdir:
|
||||||
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK)
|
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK)
|
||||||
return res
|
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.
|
"""Generate all test items from a collection node.
|
||||||
|
|
||||||
This recurses into the collection node and returns a list of all the
|
This recurses into the collection node and returns a list of all the
|
||||||
|
@ -974,7 +975,7 @@ class Testdir:
|
||||||
class reprec: # type: ignore
|
class reprec: # type: ignore
|
||||||
pass
|
pass
|
||||||
|
|
||||||
reprec.ret = ret
|
reprec.ret = ret # type: ignore[attr-defined]
|
||||||
|
|
||||||
# typically we reraise keyboard interrupts from the child run
|
# typically we reraise keyboard interrupts from the child run
|
||||||
# because it's our user requesting interruption of the testing
|
# because it's our user requesting interruption of the testing
|
||||||
|
@ -1083,7 +1084,7 @@ class Testdir:
|
||||||
config._do_configure()
|
config._do_configure()
|
||||||
return config
|
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.
|
"""Return the test item for a test function.
|
||||||
|
|
||||||
This writes the source to a python file and runs pytest's collection on
|
This writes the source to a python file and runs pytest's collection on
|
||||||
|
@ -1104,7 +1105,7 @@ class Testdir:
|
||||||
funcname, source, items
|
funcname, source, items
|
||||||
)
|
)
|
||||||
|
|
||||||
def getitems(self, source):
|
def getitems(self, source) -> List[Item]:
|
||||||
"""Return all test items collected from the module.
|
"""Return all test items collected from the module.
|
||||||
|
|
||||||
This writes the source to a python file and runs pytest's collection on
|
This writes the source to a python file and runs pytest's collection on
|
||||||
|
@ -1114,7 +1115,7 @@ class Testdir:
|
||||||
modcol = self.getmodulecol(source)
|
modcol = self.getmodulecol(source)
|
||||||
return self.genitems([modcol])
|
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``.
|
"""Return the module collection node for ``source``.
|
||||||
|
|
||||||
This writes ``source`` to a file using :py:meth:`makepyfile` and then
|
This writes ``source`` to a file using :py:meth:`makepyfile` and then
|
||||||
|
@ -1199,7 +1200,9 @@ class Testdir:
|
||||||
|
|
||||||
return popen
|
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 command with arguments.
|
||||||
|
|
||||||
Run a process using subprocess.Popen saving the stdout and stderr.
|
Run a process using subprocess.Popen saving the stdout and stderr.
|
||||||
|
@ -1238,7 +1241,7 @@ class Testdir:
|
||||||
if isinstance(stdin, bytes):
|
if isinstance(stdin, bytes):
|
||||||
popen.stdin.close()
|
popen.stdin.close()
|
||||||
|
|
||||||
def handle_timeout():
|
def handle_timeout() -> None:
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
|
|
||||||
timeout_message = (
|
timeout_message = (
|
||||||
|
@ -1283,7 +1286,7 @@ class Testdir:
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
print("couldn't print to {} because of encoding".format(fp))
|
print("couldn't print to {} because of encoding".format(fp))
|
||||||
|
|
||||||
def _getpytestargs(self):
|
def _getpytestargs(self) -> Tuple[str, ...]:
|
||||||
return sys.executable, "-mpytest"
|
return sys.executable, "-mpytest"
|
||||||
|
|
||||||
def runpython(self, script) -> RunResult:
|
def runpython(self, script) -> RunResult:
|
||||||
|
@ -1298,7 +1301,7 @@ class Testdir:
|
||||||
"""Run python -c "command", return a :py:class:`RunResult`."""
|
"""Run python -c "command", return a :py:class:`RunResult`."""
|
||||||
return self.run(sys.executable, "-c", command)
|
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.
|
"""Run pytest as a subprocess with given arguments.
|
||||||
|
|
||||||
Any plugins added to the :py:attr:`plugins` list will be added using the
|
Any plugins added to the :py:attr:`plugins` list will be added using the
|
||||||
|
|
|
@ -13,7 +13,9 @@ from collections.abc import Sequence
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from typing import Generator
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
from typing import Iterator
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Mapping
|
from typing import Mapping
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
@ -196,8 +198,8 @@ def pytest_collect_file(path: py.path.local, parent) -> Optional["Module"]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def path_matches_patterns(path, patterns):
|
def path_matches_patterns(path: py.path.local, patterns: Iterable[str]) -> bool:
|
||||||
"""Returns True if the given py.path.local matches one of the patterns in the list of globs given"""
|
"""Returns True if path matches any of the patterns in the list of globs given."""
|
||||||
return any(path.fnmatch(pattern) for pattern in patterns)
|
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."""
|
"""Gets the underlying Python object. May be overwritten by subclasses."""
|
||||||
# TODO: Improve the type of `parent` such that assert/ignore aren't needed.
|
# TODO: Improve the type of `parent` such that assert/ignore aren't needed.
|
||||||
assert self.parent is not None
|
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)
|
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. """
|
""" return python path relative to the containing module. """
|
||||||
chain = self.listchain()
|
chain = self.listchain()
|
||||||
chain.reverse()
|
chain.reverse()
|
||||||
|
@ -338,10 +340,10 @@ class PyobjMixin:
|
||||||
|
|
||||||
|
|
||||||
class PyCollector(PyobjMixin, nodes.Collector):
|
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)
|
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
|
""" Look for the __test__ attribute, which is applied by the
|
||||||
@nose.tools.istest decorator
|
@nose.tools.istest decorator
|
||||||
"""
|
"""
|
||||||
|
@ -350,10 +352,10 @@ class PyCollector(PyobjMixin, nodes.Collector):
|
||||||
# function) as test classes.
|
# function) as test classes.
|
||||||
return safe_getattr(obj, "__test__", False) is True
|
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)
|
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 self.funcnamefilter(name) or self.isnosetest(obj):
|
||||||
if isinstance(obj, staticmethod):
|
if isinstance(obj, staticmethod):
|
||||||
# static methods need to be unwrapped
|
# static methods need to be unwrapped
|
||||||
|
@ -365,10 +367,10 @@ class PyCollector(PyobjMixin, nodes.Collector):
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def istestclass(self, obj, name):
|
def istestclass(self, obj: object, name: str) -> bool:
|
||||||
return self.classnamefilter(name) or self.isnosetest(obj)
|
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
|
checks if the given name matches the prefix or glob-pattern defined
|
||||||
in ini configuration.
|
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]]]
|
) # type: Union[None, nodes.Item, nodes.Collector, List[Union[nodes.Item, nodes.Collector]]]
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def _genfunctions(self, name, funcobj):
|
def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]:
|
||||||
modulecol = self.getparent(Module)
|
modulecol = self.getparent(Module)
|
||||||
assert modulecol is not None
|
assert modulecol is not None
|
||||||
module = modulecol.obj
|
module = modulecol.obj
|
||||||
|
@ -486,7 +488,7 @@ class Module(nodes.File, PyCollector):
|
||||||
self.session._fixturemanager.parsefactories(self)
|
self.session._fixturemanager.parsefactories(self)
|
||||||
return super().collect()
|
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
|
"""Injects a hidden autouse, module scoped fixture into the collected module object
|
||||||
that invokes setUpModule/tearDownModule if either or both are available.
|
that invokes setUpModule/tearDownModule if either or both are available.
|
||||||
|
|
||||||
|
@ -504,7 +506,7 @@ class Module(nodes.File, PyCollector):
|
||||||
return
|
return
|
||||||
|
|
||||||
@fixtures.fixture(autouse=True, scope="module")
|
@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:
|
if setup_module is not None:
|
||||||
_call_with_optional_argument(setup_module, request.module)
|
_call_with_optional_argument(setup_module, request.module)
|
||||||
yield
|
yield
|
||||||
|
@ -513,7 +515,7 @@ class Module(nodes.File, PyCollector):
|
||||||
|
|
||||||
self.obj.__pytest_setup_module = xunit_setup_module_fixture
|
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
|
"""Injects a hidden autouse, function scoped fixture into the collected module object
|
||||||
that invokes setup_function/teardown_function if either or both are available.
|
that invokes setup_function/teardown_function if either or both are available.
|
||||||
|
|
||||||
|
@ -528,7 +530,7 @@ class Module(nodes.File, PyCollector):
|
||||||
return
|
return
|
||||||
|
|
||||||
@fixtures.fixture(autouse=True, scope="function")
|
@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:
|
if request.instance is not None:
|
||||||
# in this case we are bound to an instance, so we need to let
|
# in this case we are bound to an instance, so we need to let
|
||||||
# setup_method handle this
|
# setup_method handle this
|
||||||
|
@ -608,7 +610,7 @@ class Package(Module):
|
||||||
)
|
)
|
||||||
self.name = os.path.basename(str(fspath.dirname))
|
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
|
# not using fixtures to call setup_module here because autouse fixtures
|
||||||
# from packages are not called automatically (#4085)
|
# from packages are not called automatically (#4085)
|
||||||
setup_module = _get_first_non_fixture_func(
|
setup_module = _get_first_non_fixture_func(
|
||||||
|
@ -661,7 +663,7 @@ class Package(Module):
|
||||||
pkg_prefixes.add(path)
|
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
|
"""Call the given function with the given argument if func accepts one argument, otherwise
|
||||||
calls func without arguments"""
|
calls func without arguments"""
|
||||||
arg_count = func.__code__.co_argcount
|
arg_count = func.__code__.co_argcount
|
||||||
|
@ -673,7 +675,7 @@ def _call_with_optional_argument(func, arg):
|
||||||
func()
|
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
|
"""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
|
xunit-style function, but only if not marked as a fixture to
|
||||||
avoid calling it twice.
|
avoid calling it twice.
|
||||||
|
@ -723,7 +725,7 @@ class Class(PyCollector):
|
||||||
|
|
||||||
return [Instance.from_parent(self, name="()")]
|
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
|
"""Injects a hidden autouse, class scoped fixture into the collected class object
|
||||||
that invokes setup_class/teardown_class if either or both are available.
|
that invokes setup_class/teardown_class if either or both are available.
|
||||||
|
|
||||||
|
@ -736,7 +738,7 @@ class Class(PyCollector):
|
||||||
return
|
return
|
||||||
|
|
||||||
@fixtures.fixture(autouse=True, scope="class")
|
@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:
|
if setup_class is not None:
|
||||||
func = getimfunc(setup_class)
|
func = getimfunc(setup_class)
|
||||||
_call_with_optional_argument(func, self.obj)
|
_call_with_optional_argument(func, self.obj)
|
||||||
|
@ -747,7 +749,7 @@ class Class(PyCollector):
|
||||||
|
|
||||||
self.obj.__pytest_setup_class = xunit_setup_class_fixture
|
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
|
"""Injects a hidden autouse, function scoped fixture into the collected class object
|
||||||
that invokes setup_method/teardown_method if either or both are available.
|
that invokes setup_method/teardown_method if either or both are available.
|
||||||
|
|
||||||
|
@ -760,7 +762,7 @@ class Class(PyCollector):
|
||||||
return
|
return
|
||||||
|
|
||||||
@fixtures.fixture(autouse=True, scope="function")
|
@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
|
method = request.function
|
||||||
if setup_method is not None:
|
if setup_method is not None:
|
||||||
func = getattr(self, "setup_method")
|
func = getattr(self, "setup_method")
|
||||||
|
@ -782,7 +784,7 @@ class Instance(PyCollector):
|
||||||
def _getobj(self):
|
def _getobj(self):
|
||||||
# TODO: Improve the type of `parent` such that assert/ignore aren't needed.
|
# TODO: Improve the type of `parent` such that assert/ignore aren't needed.
|
||||||
assert self.parent is not None
|
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()
|
return obj()
|
||||||
|
|
||||||
def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:
|
def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:
|
||||||
|
@ -794,16 +796,18 @@ class Instance(PyCollector):
|
||||||
return self.obj
|
return self.obj
|
||||||
|
|
||||||
|
|
||||||
def hasinit(obj):
|
def hasinit(obj: object) -> bool:
|
||||||
init = getattr(obj, "__init__", None)
|
init = getattr(obj, "__init__", None) # type: object
|
||||||
if init:
|
if init:
|
||||||
return init != object.__init__
|
return init != object.__init__
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def hasnew(obj):
|
def hasnew(obj: object) -> bool:
|
||||||
new = getattr(obj, "__new__", None)
|
new = getattr(obj, "__new__", None) # type: object
|
||||||
if new:
|
if new:
|
||||||
return new != object.__new__
|
return new != object.__new__
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class CallSpec2:
|
class CallSpec2:
|
||||||
|
@ -843,7 +847,7 @@ class CallSpec2:
|
||||||
|
|
||||||
def setmulti2(
|
def setmulti2(
|
||||||
self,
|
self,
|
||||||
valtypes: "Mapping[str, Literal['params', 'funcargs']]",
|
valtypes: Mapping[str, "Literal['params', 'funcargs']"],
|
||||||
argnames: typing.Sequence[str],
|
argnames: typing.Sequence[str],
|
||||||
valset: Iterable[object],
|
valset: Iterable[object],
|
||||||
id: str,
|
id: str,
|
||||||
|
@ -903,7 +907,7 @@ class Metafunc:
|
||||||
self._arg2fixturedefs = fixtureinfo.name2fixturedefs
|
self._arg2fixturedefs = fixtureinfo.name2fixturedefs
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def funcargnames(self):
|
def funcargnames(self) -> List[str]:
|
||||||
""" alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
|
""" alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
|
||||||
warnings.warn(FUNCARGNAMES, stacklevel=2)
|
warnings.warn(FUNCARGNAMES, stacklevel=2)
|
||||||
return self.fixturenames
|
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.
|
"""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.
|
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.
|
Related to issue #1832, based on code posted by @Kingdread.
|
||||||
"""
|
"""
|
||||||
from _pytest.fixtures import scopes
|
if isinstance(indirect, Sequence):
|
||||||
|
|
||||||
if isinstance(indirect, (list, tuple)):
|
|
||||||
all_arguments_are_fixtures = len(indirect) == len(argnames)
|
all_arguments_are_fixtures = len(indirect) == len(argnames)
|
||||||
else:
|
else:
|
||||||
all_arguments_are_fixtures = bool(indirect)
|
all_arguments_are_fixtures = bool(indirect)
|
||||||
|
@ -1196,7 +1202,7 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
|
||||||
]
|
]
|
||||||
if used_scopes:
|
if used_scopes:
|
||||||
# Takes the most narrow scope from used fixtures
|
# Takes the most narrow scope from used fixtures
|
||||||
for scope in reversed(scopes):
|
for scope in reversed(fixtures.scopes):
|
||||||
if scope in used_scopes:
|
if scope in used_scopes:
|
||||||
return scope
|
return scope
|
||||||
|
|
||||||
|
@ -1264,7 +1270,7 @@ def _idvalset(
|
||||||
ids: Optional[List[Union[None, str]]],
|
ids: Optional[List[Union[None, str]]],
|
||||||
nodeid: Optional[str],
|
nodeid: Optional[str],
|
||||||
config: Optional[Config],
|
config: Optional[Config],
|
||||||
):
|
) -> str:
|
||||||
if parameterset.id is not None:
|
if parameterset.id is not None:
|
||||||
return parameterset.id
|
return parameterset.id
|
||||||
id = None if ids is None or idx >= len(ids) else ids[idx]
|
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)
|
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
|
import _pytest.config
|
||||||
|
|
||||||
session.perform_collect()
|
session.perform_collect()
|
||||||
|
@ -1330,7 +1336,7 @@ def _show_fixtures_per_test(config, session):
|
||||||
loc = getlocation(func, curdir)
|
loc = getlocation(func, curdir)
|
||||||
return curdir.bestrelpath(py.path.local(loc))
|
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
|
argname = fixture_def.argname
|
||||||
if verbose <= 0 and argname.startswith("_"):
|
if verbose <= 0 and argname.startswith("_"):
|
||||||
return
|
return
|
||||||
|
@ -1346,18 +1352,16 @@ def _show_fixtures_per_test(config, session):
|
||||||
else:
|
else:
|
||||||
tw.line(" no docstring available", red=True)
|
tw.line(" no docstring available", red=True)
|
||||||
|
|
||||||
def write_item(item):
|
def write_item(item: nodes.Item) -> None:
|
||||||
try:
|
# Not all items have _fixtureinfo attribute.
|
||||||
info = item._fixtureinfo
|
info = getattr(item, "_fixtureinfo", None) # type: Optional[FuncFixtureInfo]
|
||||||
except AttributeError:
|
if info is None or not info.name2fixturedefs:
|
||||||
# doctests items have no _fixtureinfo attribute
|
# This test item does not use any fixtures.
|
||||||
return
|
|
||||||
if not info.name2fixturedefs:
|
|
||||||
# this test item does not use any fixtures
|
|
||||||
return
|
return
|
||||||
tw.line()
|
tw.line()
|
||||||
tw.sep("-", "fixtures used by {}".format(item.name))
|
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
|
# dict key not used in loop but needed for sorting
|
||||||
for _, fixturedefs in sorted(info.name2fixturedefs.items()):
|
for _, fixturedefs in sorted(info.name2fixturedefs.items()):
|
||||||
assert fixturedefs is not None
|
assert fixturedefs is not None
|
||||||
|
@ -1448,15 +1452,15 @@ class Function(PyobjMixin, nodes.Item):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name,
|
name: str,
|
||||||
parent,
|
parent,
|
||||||
config=None,
|
config: Optional[Config] = None,
|
||||||
callspec: Optional[CallSpec2] = None,
|
callspec: Optional[CallSpec2] = None,
|
||||||
callobj=NOTSET,
|
callobj=NOTSET,
|
||||||
keywords=None,
|
keywords=None,
|
||||||
session=None,
|
session: Optional[Session] = None,
|
||||||
fixtureinfo: Optional[FuncFixtureInfo] = None,
|
fixtureinfo: Optional[FuncFixtureInfo] = None,
|
||||||
originalname=None,
|
originalname: Optional[str] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
param name: the full function name, including any decorations like those
|
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)
|
return super().from_parent(parent=parent, **kw)
|
||||||
|
|
||||||
def _initrequest(self):
|
def _initrequest(self) -> None:
|
||||||
self.funcargs = {}
|
self.funcargs = {} # type: Dict[str, object]
|
||||||
self._request = fixtures.FixtureRequest(self)
|
self._request = fixtures.FixtureRequest(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -1552,7 +1556,7 @@ class Function(PyobjMixin, nodes.Item):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def funcargnames(self):
|
def funcargnames(self) -> List[str]:
|
||||||
""" alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
|
""" alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
|
||||||
warnings.warn(FUNCARGNAMES, stacklevel=2)
|
warnings.warn(FUNCARGNAMES, stacklevel=2)
|
||||||
return self.fixturenames
|
return self.fixturenames
|
||||||
|
@ -1589,7 +1593,7 @@ class Function(PyobjMixin, nodes.Item):
|
||||||
entry.set_repr_style("short")
|
entry.set_repr_style("short")
|
||||||
|
|
||||||
# TODO: Type ignored -- breaks Liskov Substitution.
|
# TODO: Type ignored -- breaks Liskov Substitution.
|
||||||
def repr_failure( # type: ignore[override] # noqa: F821
|
def repr_failure( # type: ignore[override]
|
||||||
self, excinfo: ExceptionInfo[BaseException],
|
self, excinfo: ExceptionInfo[BaseException],
|
||||||
) -> Union[str, TerminalRepr]:
|
) -> Union[str, TerminalRepr]:
|
||||||
style = self.config.getoption("tbstyle", "auto")
|
style = self.config.getoption("tbstyle", "auto")
|
||||||
|
|
|
@ -165,7 +165,7 @@ class WarningsRecorder(warnings.catch_warnings):
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
# Type ignored due to the way typeshed handles warnings.catch_warnings.
|
# 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._entered = False
|
||||||
self._list = [] # type: List[warnings.WarningMessage]
|
self._list = [] # type: List[warnings.WarningMessage]
|
||||||
|
|
||||||
|
|
|
@ -308,7 +308,7 @@ class TestReport(BaseReport):
|
||||||
if not isinstance(excinfo, ExceptionInfo):
|
if not isinstance(excinfo, ExceptionInfo):
|
||||||
outcome = "failed"
|
outcome = "failed"
|
||||||
longrepr = excinfo
|
longrepr = excinfo
|
||||||
elif excinfo.errisinstance(skip.Exception):
|
elif isinstance(excinfo.value, skip.Exception):
|
||||||
outcome = "skipped"
|
outcome = "skipped"
|
||||||
r = excinfo._getreprcrash()
|
r = excinfo._getreprcrash()
|
||||||
longrepr = (str(r.path), r.lineno, r.message)
|
longrepr = (str(r.path), r.lineno, r.message)
|
||||||
|
|
|
@ -106,8 +106,8 @@ def runtestprotocol(
|
||||||
item: Item, log: bool = True, nextitem: Optional[Item] = None
|
item: Item, log: bool = True, nextitem: Optional[Item] = None
|
||||||
) -> List[TestReport]:
|
) -> List[TestReport]:
|
||||||
hasrequest = hasattr(item, "_request")
|
hasrequest = hasattr(item, "_request")
|
||||||
if hasrequest and not item._request: # type: ignore[attr-defined] # noqa: F821
|
if hasrequest and not item._request: # type: ignore[attr-defined]
|
||||||
item._initrequest() # type: ignore[attr-defined] # noqa: F821
|
item._initrequest() # type: ignore[attr-defined]
|
||||||
rep = call_and_report(item, "setup", log)
|
rep = call_and_report(item, "setup", log)
|
||||||
reports = [rep]
|
reports = [rep]
|
||||||
if rep.passed:
|
if rep.passed:
|
||||||
|
@ -119,8 +119,8 @@ def runtestprotocol(
|
||||||
# after all teardown hooks have been called
|
# after all teardown hooks have been called
|
||||||
# want funcargs and request info to go away
|
# want funcargs and request info to go away
|
||||||
if hasrequest:
|
if hasrequest:
|
||||||
item._request = False # type: ignore[attr-defined] # noqa: F821
|
item._request = False # type: ignore[attr-defined]
|
||||||
item.funcargs = None # type: ignore[attr-defined] # noqa: F821
|
item.funcargs = None # type: ignore[attr-defined]
|
||||||
return reports
|
return reports
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,11 +215,18 @@ def call_and_report(
|
||||||
|
|
||||||
|
|
||||||
def check_interactive_exception(call: "CallInfo", report: BaseReport) -> bool:
|
def check_interactive_exception(call: "CallInfo", report: BaseReport) -> bool:
|
||||||
return call.excinfo is not None and not (
|
"""Check whether the call raised an exception that should be reported as
|
||||||
hasattr(report, "wasxfail")
|
interactive."""
|
||||||
or call.excinfo.errisinstance(Skipped)
|
if call.excinfo is None:
|
||||||
or call.excinfo.errisinstance(bdb.BdbQuit)
|
# 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(
|
def call_runtest_hook(
|
||||||
|
@ -287,7 +294,7 @@ class CallInfo(Generic[_T]):
|
||||||
result = func() # type: Optional[_T]
|
result = func() # type: Optional[_T]
|
||||||
except BaseException:
|
except BaseException:
|
||||||
excinfo = ExceptionInfo.from_current()
|
excinfo = ExceptionInfo.from_current()
|
||||||
if reraise is not None and excinfo.errisinstance(reraise):
|
if reraise is not None and isinstance(excinfo.value, reraise):
|
||||||
raise
|
raise
|
||||||
result = None
|
result = None
|
||||||
# use the perf counter
|
# use the perf counter
|
||||||
|
@ -325,7 +332,7 @@ def pytest_make_collect_report(collector: Collector) -> CollectReport:
|
||||||
if unittest is not None:
|
if unittest is not None:
|
||||||
# Type ignored because unittest is loaded dynamically.
|
# Type ignored because unittest is loaded dynamically.
|
||||||
skip_exceptions.append(unittest.SkipTest) # type: ignore
|
skip_exceptions.append(unittest.SkipTest) # type: ignore
|
||||||
if call.excinfo.errisinstance(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")
|
||||||
assert isinstance(r_, ExceptionChainRepr), repr(r_)
|
assert isinstance(r_, ExceptionChainRepr), repr(r_)
|
||||||
|
@ -415,7 +422,7 @@ class SetupState:
|
||||||
# check if the last collection node has raised an error
|
# check if the last collection node has raised an error
|
||||||
for col in self.stack:
|
for col in self.stack:
|
||||||
if hasattr(col, "_prepare_exc"):
|
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
|
raise exc
|
||||||
|
|
||||||
needed_collectors = colitem.listchain()
|
needed_collectors = colitem.listchain()
|
||||||
|
@ -424,7 +431,7 @@ class SetupState:
|
||||||
try:
|
try:
|
||||||
col.setup()
|
col.setup()
|
||||||
except TEST_OUTCOME as e:
|
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
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ def pytest_fixture_setup(
|
||||||
param = fixturedef.ids[request.param_index]
|
param = fixturedef.ids[request.param_index]
|
||||||
else:
|
else:
|
||||||
param = request.param
|
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")
|
_show_fixture_action(fixturedef, "SETUP")
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ def pytest_fixture_post_finalizer(fixturedef: FixtureDef) -> None:
|
||||||
if config.option.setupshow:
|
if config.option.setupshow:
|
||||||
_show_fixture_action(fixturedef, "TEARDOWN")
|
_show_fixture_action(fixturedef, "TEARDOWN")
|
||||||
if hasattr(fixturedef, "cached_param"):
|
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:
|
def _show_fixture_action(fixturedef: FixtureDef, msg: str) -> None:
|
||||||
|
|
|
@ -56,7 +56,7 @@ def pytest_configure(config: Config) -> None:
|
||||||
def nop(*args, **kwargs):
|
def nop(*args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
nop.Exception = xfail.Exception # type: ignore[attr-defined] # noqa: F821
|
nop.Exception = xfail.Exception # type: ignore[attr-defined]
|
||||||
setattr(pytest, "xfail", nop)
|
setattr(pytest, "xfail", nop)
|
||||||
|
|
||||||
config.addinivalue_line(
|
config.addinivalue_line(
|
||||||
|
|
|
@ -1219,7 +1219,7 @@ def _get_line_with_reprcrash_message(
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Type ignored intentionally -- possible AttributeError expected.
|
# 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:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -46,7 +46,7 @@ class TempPathFactory:
|
||||||
given_basetemp=config.option.basetemp, trace=config.trace.get("tmpdir")
|
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)
|
basename = os.path.normpath(basename)
|
||||||
if (self.getbasetemp() / basename).resolve().parent != self.getbasetemp():
|
if (self.getbasetemp() / basename).resolve().parent != self.getbasetemp():
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -119,7 +119,7 @@ class TempdirFactory:
|
||||||
"""
|
"""
|
||||||
return py.path.local(self._tmppath_factory.mktemp(basename, numbered).resolve())
|
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``"""
|
"""backward compat wrapper for ``_tmppath_factory.getbasetemp``"""
|
||||||
return py.path.local(self._tmppath_factory.getbasetemp().resolve())
|
return py.path.local(self._tmppath_factory.getbasetemp().resolve())
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ def _mk_tmp(request: FixtureRequest, factory: TempPathFactory) -> Path:
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def tmpdir(tmp_path):
|
def tmpdir(tmp_path: Path) -> py.path.local:
|
||||||
"""Return a temporary directory path object
|
"""Return a temporary directory path object
|
||||||
which is unique to each test function invocation,
|
which is unique to each test function invocation,
|
||||||
created as a sub directory of the base temporary
|
created as a sub directory of the base temporary
|
||||||
|
|
|
@ -102,13 +102,13 @@ class UnitTestCase(Class):
|
||||||
cls, "setUpClass", "tearDownClass", scope="class", pass_self=False
|
cls, "setUpClass", "tearDownClass", scope="class", pass_self=False
|
||||||
)
|
)
|
||||||
if class_fixture:
|
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(
|
method_fixture = _make_xunit_fixture(
|
||||||
cls, "setup_method", "teardown_method", scope="function", pass_self=True
|
cls, "setup_method", "teardown_method", scope="function", pass_self=True
|
||||||
)
|
)
|
||||||
if method_fixture:
|
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(
|
def _make_xunit_fixture(
|
||||||
|
@ -148,7 +148,7 @@ class TestCaseFunction(Function):
|
||||||
# a bound method to be called during teardown() if set (see 'runtest()')
|
# a bound method to be called during teardown() if set (see 'runtest()')
|
||||||
self._explicit_tearDown = None # type: Optional[Callable[[], None]]
|
self._explicit_tearDown = None # type: Optional[Callable[[], None]]
|
||||||
assert self.parent is not 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)
|
self._obj = getattr(self._testcase, self.name)
|
||||||
if hasattr(self, "_request"):
|
if hasattr(self, "_request"):
|
||||||
self._request._fillfixtures()
|
self._request._fillfixtures()
|
||||||
|
@ -167,7 +167,7 @@ class TestCaseFunction(Function):
|
||||||
# unwrap potential exception info (see twisted trial support below)
|
# unwrap potential exception info (see twisted trial support below)
|
||||||
rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo)
|
rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo)
|
||||||
try:
|
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
|
# invoke the attributes to trigger storing the traceback
|
||||||
# trial causes some issue there
|
# trial causes some issue there
|
||||||
excinfo.value
|
excinfo.value
|
||||||
|
@ -259,7 +259,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.
|
# 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:
|
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
|
||||||
|
@ -275,7 +275,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(self._testcase, self.name, self.obj)
|
setattr(self._testcase, self.name, self.obj)
|
||||||
try:
|
try:
|
||||||
self._testcase(result=self) # type: ignore[arg-type] # noqa: F821
|
self._testcase(result=self) # type: ignore[arg-type]
|
||||||
finally:
|
finally:
|
||||||
delattr(self._testcase, self.name)
|
delattr(self._testcase, self.name)
|
||||||
|
|
||||||
|
@ -302,9 +302,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None:
|
||||||
if (
|
if (
|
||||||
unittest
|
unittest
|
||||||
and call.excinfo
|
and call.excinfo
|
||||||
and call.excinfo.errisinstance(
|
and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined]
|
||||||
unittest.SkipTest # type: ignore[attr-defined] # noqa: F821
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
excinfo = call.excinfo
|
excinfo = call.excinfo
|
||||||
# let's substitute the excinfo with a pytest.skip one
|
# let's substitute the excinfo with a pytest.skip one
|
||||||
|
|
|
@ -752,7 +752,7 @@ raise ValueError()
|
||||||
from _pytest._code.code import Code
|
from _pytest._code.code import Code
|
||||||
|
|
||||||
monkeypatch.setattr(Code, "path", "bogus")
|
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")
|
p = FormattedExcinfo(style="short")
|
||||||
reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
|
reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
|
||||||
lines = reprtb.lines
|
lines = reprtb.lines
|
||||||
|
|
|
@ -16,4 +16,4 @@ def test_comparing_two_different_data_classes() -> None:
|
||||||
left = SimpleDataObjectOne(1, "b")
|
left = SimpleDataObjectOne(1, "b")
|
||||||
right = SimpleDataObjectTwo(1, "c")
|
right = SimpleDataObjectTwo(1, "c")
|
||||||
|
|
||||||
assert left != right # type: ignore[comparison-overlap] # noqa: F821
|
assert left != right # type: ignore[comparison-overlap]
|
||||||
|
|
|
@ -34,8 +34,8 @@ def test_exceptions() -> None:
|
||||||
raise self.ex
|
raise self.ex
|
||||||
|
|
||||||
class BrokenReprException(Exception):
|
class BrokenReprException(Exception):
|
||||||
__str__ = None # type: ignore[assignment] # noqa: F821
|
__str__ = None # type: ignore[assignment]
|
||||||
__repr__ = None # type: ignore[assignment] # noqa: F821
|
__repr__ = None # type: ignore[assignment]
|
||||||
|
|
||||||
assert "Exception" in saferepr(BrokenRepr(Exception("broken")))
|
assert "Exception" in saferepr(BrokenRepr(Exception("broken")))
|
||||||
s = saferepr(BrokenReprException("really broken"))
|
s = saferepr(BrokenReprException("really broken"))
|
||||||
|
@ -44,7 +44,7 @@ def test_exceptions() -> None:
|
||||||
|
|
||||||
none = None
|
none = None
|
||||||
try:
|
try:
|
||||||
none() # type: ignore[misc] # noqa: F821
|
none() # type: ignore[misc]
|
||||||
except BaseException as exc:
|
except BaseException as exc:
|
||||||
exp_exc = repr(exc)
|
exp_exc = repr(exc)
|
||||||
obj = BrokenRepr(BrokenReprException("omg even worse"))
|
obj = BrokenRepr(BrokenReprException("omg even worse"))
|
||||||
|
@ -139,7 +139,7 @@ def test_big_repr():
|
||||||
def test_repr_on_newstyle() -> None:
|
def test_repr_on_newstyle() -> None:
|
||||||
class Function:
|
class Function:
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s>" % (self.name) # type: ignore[attr-defined] # noqa: F821
|
return "<%s>" % (self.name) # type: ignore[attr-defined]
|
||||||
|
|
||||||
assert saferepr(Function())
|
assert saferepr(Function())
|
||||||
|
|
||||||
|
|
|
@ -675,7 +675,11 @@ class TestFunction:
|
||||||
pass
|
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_func",
|
"test_func",
|
||||||
"test_no_param",
|
"test_no_param",
|
||||||
|
@ -720,10 +724,10 @@ class TestSorting:
|
||||||
assert fn1 != fn3
|
assert fn1 != fn3
|
||||||
|
|
||||||
for fn in fn1, fn2, 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 != modcol
|
||||||
assert fn != [1, 2, 3] # type: ignore[comparison-overlap] # noqa: F821
|
assert fn != [1, 2, 3] # type: ignore[comparison-overlap]
|
||||||
assert [1, 2, 3] != fn # type: ignore[comparison-overlap] # noqa: F821
|
assert [1, 2, 3] != fn # type: ignore[comparison-overlap]
|
||||||
assert modcol != fn
|
assert modcol != fn
|
||||||
|
|
||||||
def test_allow_sane_sorting_for_decorators(self, testdir):
|
def test_allow_sane_sorting_for_decorators(self, testdir):
|
||||||
|
|
|
@ -3850,7 +3850,7 @@ class TestScopeOrdering:
|
||||||
)
|
)
|
||||||
testdir.runpytest()
|
testdir.runpytest()
|
||||||
# actual fixture execution differs: dependent fixtures must be created first ("my_tmpdir")
|
# 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()
|
assert FIXTURE_ORDER == "s1 my_tmpdir_factory p1 m1 my_tmpdir f1 f2".split()
|
||||||
|
|
||||||
def test_func_closure_module(self, testdir):
|
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)."""
|
"""Raise error if there are positional and keyword arguments for the same parameter (#1682)."""
|
||||||
with pytest.raises(TypeError) as excinfo:
|
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):
|
def arg(arg):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -4171,7 +4171,7 @@ def test_fixture_duplicated_arguments() -> None:
|
||||||
|
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
|
|
||||||
@pytest.fixture( # type: ignore[call-overload] # noqa: F821
|
@pytest.fixture( # type: ignore[call-overload]
|
||||||
"function",
|
"function",
|
||||||
["p1"],
|
["p1"],
|
||||||
True,
|
True,
|
||||||
|
@ -4199,7 +4199,7 @@ def test_fixture_with_positionals() -> None:
|
||||||
|
|
||||||
with pytest.warns(pytest.PytestDeprecationWarning) as warnings:
|
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():
|
def fixture_with_positionals():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -4213,7 +4213,7 @@ def test_fixture_with_positionals() -> None:
|
||||||
def test_fixture_with_too_many_positionals() -> None:
|
def test_fixture_with_too_many_positionals() -> None:
|
||||||
with pytest.raises(TypeError) as excinfo:
|
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():
|
def fixture_with_positionals():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,12 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
from typing import cast
|
||||||
|
from typing import Dict
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from typing import Sequence
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
@ -74,7 +77,7 @@ class TestMetafunc:
|
||||||
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
|
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
|
||||||
|
|
||||||
with pytest.raises(TypeError, match="^ids must be a callable or an iterable$"):
|
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 test_parametrize_error_iterator(self) -> None:
|
||||||
def func(x):
|
def func(x):
|
||||||
|
@ -92,7 +95,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] # noqa: F821
|
metafunc.parametrize("x", [1, 2], ids=gen()) # type: ignore[arg-type]
|
||||||
assert [(x.funcargs, x.id) for x in metafunc._calls] == [
|
assert [(x.funcargs, x.id) for x in metafunc._calls] == [
|
||||||
({"x": 1}, "0"),
|
({"x": 1}, "0"),
|
||||||
({"x": 2}, "2"),
|
({"x": 2}, "2"),
|
||||||
|
@ -104,7 +107,7 @@ class TestMetafunc:
|
||||||
r" Exc\(from_gen\) \(type: <class .*Exc'>\) at index 2"
|
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 test_parametrize_bad_scope(self) -> None:
|
||||||
def func(x):
|
def func(x):
|
||||||
|
@ -115,7 +118,7 @@ class TestMetafunc:
|
||||||
fail.Exception,
|
fail.Exception,
|
||||||
match=r"parametrize\(\) call in func got an unexpected scope value 'doggy'",
|
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:
|
def test_parametrize_request_name(self, testdir: Testdir) -> None:
|
||||||
"""Show proper error when 'request' is used as a parameter name in parametrize (#6183)"""
|
"""Show proper error when 'request' is used as a parameter name in parametrize (#6183)"""
|
||||||
|
@ -138,12 +141,15 @@ class TestMetafunc:
|
||||||
class DummyFixtureDef:
|
class DummyFixtureDef:
|
||||||
scope = attr.ib()
|
scope = attr.ib()
|
||||||
|
|
||||||
fixtures_defs = dict(
|
fixtures_defs = cast(
|
||||||
session_fix=[DummyFixtureDef("session")],
|
Dict[str, Sequence[fixtures.FixtureDef]],
|
||||||
package_fix=[DummyFixtureDef("package")],
|
dict(
|
||||||
module_fix=[DummyFixtureDef("module")],
|
session_fix=[DummyFixtureDef("session")],
|
||||||
class_fix=[DummyFixtureDef("class")],
|
package_fix=[DummyFixtureDef("package")],
|
||||||
func_fix=[DummyFixtureDef("function")],
|
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
|
# 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,
|
fail.Exception,
|
||||||
match="In func: expected Sequence or boolean for indirect, got dict",
|
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:
|
def test_parametrize_indirect_list_functional(self, testdir: Testdir) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -8,7 +8,7 @@ from _pytest.outcomes import Failed
|
||||||
class TestRaises:
|
class TestRaises:
|
||||||
def test_check_callable(self) -> None:
|
def test_check_callable(self) -> None:
|
||||||
with pytest.raises(TypeError, match=r".* must be callable"):
|
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):
|
def test_raises(self):
|
||||||
excinfo = pytest.raises(ValueError, int, "qwe")
|
excinfo = pytest.raises(ValueError, int, "qwe")
|
||||||
|
@ -30,7 +30,7 @@ class TestRaises:
|
||||||
|
|
||||||
def test_raises_falsey_type_error(self) -> None:
|
def test_raises_falsey_type_error(self) -> None:
|
||||||
with pytest.raises(TypeError):
|
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")
|
raise AssertionError("ohai")
|
||||||
|
|
||||||
def test_raises_repr_inflight(self):
|
def test_raises_repr_inflight(self):
|
||||||
|
@ -128,11 +128,11 @@ class TestRaises:
|
||||||
|
|
||||||
def test_noclass(self) -> None:
|
def test_noclass(self) -> None:
|
||||||
with pytest.raises(TypeError):
|
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:
|
def test_invalid_arguments_to_raises(self) -> None:
|
||||||
with pytest.raises(TypeError, match="unknown"):
|
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()
|
raise ValueError()
|
||||||
|
|
||||||
def test_tuple(self):
|
def test_tuple(self):
|
||||||
|
@ -262,12 +262,12 @@ class TestRaises:
|
||||||
assert False, "via __class__"
|
assert False, "via __class__"
|
||||||
|
|
||||||
with pytest.raises(AssertionError) as excinfo:
|
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
|
pass
|
||||||
assert "via __class__" in excinfo.value.args[0]
|
assert "via __class__" in excinfo.value.args[0]
|
||||||
|
|
||||||
def test_raises_context_manager_with_kwargs(self):
|
def test_raises_context_manager_with_kwargs(self):
|
||||||
with pytest.raises(TypeError) as excinfo:
|
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
|
pass
|
||||||
assert "Unexpected keyword arguments" in str(excinfo.value)
|
assert "Unexpected keyword arguments" in str(excinfo.value)
|
||||||
|
|
|
@ -51,7 +51,7 @@ def getmsg(
|
||||||
exec(code, ns)
|
exec(code, ns)
|
||||||
func = ns[f.__name__]
|
func = ns[f.__name__]
|
||||||
try:
|
try:
|
||||||
func() # type: ignore[operator] # noqa: F821
|
func() # type: ignore[operator]
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
if must_pass:
|
if must_pass:
|
||||||
pytest.fail("shouldn't have raised")
|
pytest.fail("shouldn't have raised")
|
||||||
|
@ -174,7 +174,7 @@ class TestAssertionRewrite:
|
||||||
assert getmsg(f3, {"a_global": False}) == "assert False"
|
assert getmsg(f3, {"a_global": False}) == "assert False"
|
||||||
|
|
||||||
def f4() -> None:
|
def f4() -> None:
|
||||||
assert sys == 42 # type: ignore[comparison-overlap] # noqa: F821
|
assert sys == 42 # type: ignore[comparison-overlap]
|
||||||
|
|
||||||
verbose = request.config.getoption("verbose")
|
verbose = request.config.getoption("verbose")
|
||||||
msg = getmsg(f4, {"sys": sys})
|
msg = getmsg(f4, {"sys": sys})
|
||||||
|
@ -188,7 +188,7 @@ class TestAssertionRewrite:
|
||||||
assert msg == "assert sys == 42"
|
assert msg == "assert sys == 42"
|
||||||
|
|
||||||
def f5() -> None:
|
def f5() -> None:
|
||||||
assert cls == 42 # type: ignore[name-defined] # noqa: F821
|
assert cls == 42 # type: ignore[name-defined] # noqa: F821
|
||||||
|
|
||||||
class X:
|
class X:
|
||||||
pass
|
pass
|
||||||
|
@ -684,7 +684,7 @@ class TestAssertionRewrite:
|
||||||
|
|
||||||
def test_formatchar(self) -> None:
|
def test_formatchar(self) -> None:
|
||||||
def f() -> None:
|
def f() -> None:
|
||||||
assert "%test" == "test" # type: ignore[comparison-overlap] # noqa: F821
|
assert "%test" == "test" # type: ignore[comparison-overlap]
|
||||||
|
|
||||||
msg = getmsg(f)
|
msg = getmsg(f)
|
||||||
assert msg is not None
|
assert msg is not None
|
||||||
|
@ -1264,7 +1264,7 @@ class TestEarlyRewriteBailout:
|
||||||
# use default patterns, otherwise we inherit pytest's testing config
|
# use default patterns, otherwise we inherit pytest's testing config
|
||||||
hook.fnpats[:] = ["test_*.py", "*_test.py"]
|
hook.fnpats[:] = ["test_*.py", "*_test.py"]
|
||||||
monkeypatch.setattr(hook, "_find_spec", spy_find_spec)
|
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()
|
testdir.syspathinsert()
|
||||||
return hook
|
return hook
|
||||||
|
|
||||||
|
|
|
@ -1537,7 +1537,7 @@ def test_encodedfile_writelines(tmpfile: BinaryIO) -> None:
|
||||||
ef = capture.EncodedFile(tmpfile, encoding="utf-8")
|
ef = capture.EncodedFile(tmpfile, encoding="utf-8")
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
ef.writelines([b"line1", b"line2"])
|
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()
|
ef.flush()
|
||||||
tmpfile.seek(0)
|
tmpfile.seek(0)
|
||||||
assert tmpfile.read() == b"line3line4"
|
assert tmpfile.read() == b"line3line4"
|
||||||
|
|
|
@ -41,10 +41,10 @@ class TestCollector:
|
||||||
|
|
||||||
for fn in fn1, fn2, fn3:
|
for fn in fn1, fn2, fn3:
|
||||||
assert isinstance(fn, pytest.Function)
|
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 != modcol
|
||||||
assert fn != [1, 2, 3] # type: ignore[comparison-overlap] # noqa: F821
|
assert fn != [1, 2, 3] # type: ignore[comparison-overlap]
|
||||||
assert [1, 2, 3] != fn # type: ignore[comparison-overlap] # noqa: F821
|
assert [1, 2, 3] != fn # type: ignore[comparison-overlap]
|
||||||
assert modcol != fn
|
assert modcol != fn
|
||||||
|
|
||||||
assert testdir.collect_by_name(modcol, "doesnotexist") is None
|
assert testdir.collect_by_name(modcol, "doesnotexist") is None
|
||||||
|
|
|
@ -1602,7 +1602,7 @@ def test_invocation_args(testdir):
|
||||||
|
|
||||||
# args cannot be None
|
# args cannot be None
|
||||||
with pytest.raises(TypeError):
|
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(
|
@pytest.mark.parametrize(
|
||||||
|
|
|
@ -1490,7 +1490,7 @@ def test_warning_on_unwrap_of_broken_object(
|
||||||
pytest.PytestWarning, match="^Got KeyError.* when unwrapping"
|
pytest.PytestWarning, match="^Got KeyError.* when unwrapping"
|
||||||
):
|
):
|
||||||
with pytest.raises(KeyError):
|
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"
|
assert inspect.unwrap.__module__ == "inspect"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1124,7 +1124,7 @@ def test_unicode_issue368(testdir) -> 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] # noqa: F821
|
test_report.wasxfail = ustr # type: ignore[attr-defined]
|
||||||
node_reporter.append_skipped(test_report)
|
node_reporter.append_skipped(test_report)
|
||||||
log.pytest_sessionfinish()
|
log.pytest_sessionfinish()
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ class TestMark:
|
||||||
def test_pytest_mark_notcallable(self) -> None:
|
def test_pytest_mark_notcallable(self) -> None:
|
||||||
mark = Mark()
|
mark = Mark()
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
mark() # type: ignore[operator] # noqa: F821
|
mark() # type: ignore[operator]
|
||||||
|
|
||||||
def test_mark_with_param(self):
|
def test_mark_with_param(self):
|
||||||
def some_function(abc):
|
def some_function(abc):
|
||||||
|
@ -31,10 +31,10 @@ 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] # 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(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):
|
def test_pytest_mark_name_starts_with_underscore(self):
|
||||||
mark = Mark()
|
mark = Mark()
|
||||||
|
@ -1077,7 +1077,7 @@ def test_markers_from_parametrize(testdir):
|
||||||
|
|
||||||
def test_pytest_param_id_requires_string() -> None:
|
def test_pytest_param_id_requires_string() -> None:
|
||||||
with pytest.raises(TypeError) as excinfo:
|
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
|
(msg,) = excinfo.value.args
|
||||||
assert msg == "Expected id to be a string, got <class 'bool'>: True"
|
assert msg == "Expected id to be a string, got <class 'bool'>: True"
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,9 @@ def test_ischildnode(baseid: str, nodeid: str, expected: bool) -> None:
|
||||||
|
|
||||||
def test_node_from_parent_disallowed_arguments() -> None:
|
def test_node_from_parent_disallowed_arguments() -> None:
|
||||||
with pytest.raises(TypeError, match="session is"):
|
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"):
|
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:
|
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.*"):
|
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:
|
def test__check_initialpaths_for_relpath() -> None:
|
||||||
|
|
|
@ -484,20 +484,20 @@ def test_linematcher_with_nonlist() -> None:
|
||||||
|
|
||||||
lm = LineMatcher([])
|
lm = LineMatcher([])
|
||||||
with pytest.raises(TypeError, match="invalid type for lines2: set"):
|
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"):
|
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"):
|
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"):
|
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"):
|
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(())
|
lm.fnmatch_lines(())
|
||||||
lm.fnmatch_lines("")
|
lm.fnmatch_lines("")
|
||||||
assert lm._getlines({}) == {} # 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] # noqa: F821
|
assert lm._getlines(set()) == set() # type: ignore[arg-type,comparison-overlap]
|
||||||
assert lm._getlines(Source()) == []
|
assert lm._getlines(Source()) == []
|
||||||
assert lm._getlines(Source("pass\npass")) == ["pass", "pass"]
|
assert lm._getlines(Source("pass\npass")) == ["pass", "pass"]
|
||||||
|
|
||||||
|
|
|
@ -884,7 +884,7 @@ def test_store_except_info_on_error() -> None:
|
||||||
raise IndexError("TEST")
|
raise IndexError("TEST")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
runner.pytest_runtest_call(ItemMightRaise()) # type: ignore[arg-type] # noqa: F821
|
runner.pytest_runtest_call(ItemMightRaise()) # type: ignore[arg-type]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
# Check that exception info is stored on sys
|
# 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
|
# The next run should clear the exception info stored by the previous run
|
||||||
ItemMightRaise.raise_error = False
|
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_type")
|
||||||
assert not hasattr(sys, "last_value")
|
assert not hasattr(sys, "last_value")
|
||||||
assert not hasattr(sys, "last_traceback")
|
assert not hasattr(sys, "last_traceback")
|
||||||
|
|
|
@ -47,7 +47,7 @@ def test_store() -> None:
|
||||||
|
|
||||||
# Can't accidentally add attributes to store object itself.
|
# Can't accidentally add attributes to store object itself.
|
||||||
with pytest.raises(AttributeError):
|
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.
|
# No interaction with anoter store.
|
||||||
store2 = Store()
|
store2 = Store()
|
||||||
|
|
|
@ -1699,7 +1699,7 @@ def test_summary_stats(
|
||||||
class fake_session:
|
class fake_session:
|
||||||
testscollected = 0
|
testscollected = 0
|
||||||
|
|
||||||
tr._session = fake_session # type: ignore[assignment] # noqa: F821
|
tr._session = fake_session # type: ignore[assignment]
|
||||||
assert tr._is_last_item
|
assert tr._is_last_item
|
||||||
|
|
||||||
# Reset cache.
|
# Reset cache.
|
||||||
|
|
Loading…
Reference in New Issue