Enable check_untyped_defs mypy option for src/
This option checks even functions which are not annotated. It's a good step to ensure that existing type annotation are correct. In a Pareto fashion, the last few holdouts are always the ugliest, beware.
This commit is contained in:
parent
848ab00663
commit
71dfdca4df
|
@ -98,3 +98,6 @@ strict_equality = True
|
||||||
warn_redundant_casts = True
|
warn_redundant_casts = True
|
||||||
warn_return_any = True
|
warn_return_any = True
|
||||||
warn_unused_configs = True
|
warn_unused_configs = True
|
||||||
|
|
||||||
|
[mypy-_pytest.*]
|
||||||
|
check_untyped_defs = True
|
||||||
|
|
|
@ -519,10 +519,11 @@ class MultiCapture:
|
||||||
def pop_outerr_to_orig(self):
|
def pop_outerr_to_orig(self):
|
||||||
""" pop current snapshot out/err capture and flush to orig streams. """
|
""" pop current snapshot out/err capture and flush to orig streams. """
|
||||||
out, err = self.readouterr()
|
out, err = self.readouterr()
|
||||||
|
# TODO: Fix type ignores.
|
||||||
if out:
|
if out:
|
||||||
self.out.writeorg(out)
|
self.out.writeorg(out) # type: ignore[union-attr] # noqa: F821
|
||||||
if err:
|
if err:
|
||||||
self.err.writeorg(err)
|
self.err.writeorg(err) # type: ignore[union-attr] # noqa: F821
|
||||||
return out, err
|
return out, err
|
||||||
|
|
||||||
def suspend_capturing(self, in_: bool = False) -> None:
|
def suspend_capturing(self, in_: bool = False) -> None:
|
||||||
|
@ -542,7 +543,8 @@ class MultiCapture:
|
||||||
if self.err:
|
if self.err:
|
||||||
self.err.resume()
|
self.err.resume()
|
||||||
if self._in_suspended:
|
if self._in_suspended:
|
||||||
self.in_.resume()
|
# TODO: Fix type ignore.
|
||||||
|
self.in_.resume() # type: ignore[union-attr] # noqa: F821
|
||||||
self._in_suspended = False
|
self._in_suspended = False
|
||||||
|
|
||||||
def stop_capturing(self) -> None:
|
def stop_capturing(self) -> None:
|
||||||
|
|
|
@ -974,7 +974,7 @@ class Config:
|
||||||
self._mark_plugins_for_rewrite(hook)
|
self._mark_plugins_for_rewrite(hook)
|
||||||
_warn_about_missing_assertion(mode)
|
_warn_about_missing_assertion(mode)
|
||||||
|
|
||||||
def _mark_plugins_for_rewrite(self, hook):
|
def _mark_plugins_for_rewrite(self, hook) -> None:
|
||||||
"""
|
"""
|
||||||
Given an importhook, mark for rewrite any top-level
|
Given an importhook, mark for rewrite any top-level
|
||||||
modules or packages in the distribution package for
|
modules or packages in the distribution package for
|
||||||
|
@ -989,7 +989,9 @@ class Config:
|
||||||
package_files = (
|
package_files = (
|
||||||
str(file)
|
str(file)
|
||||||
for dist in importlib_metadata.distributions()
|
for dist in importlib_metadata.distributions()
|
||||||
if any(ep.group == "pytest11" for ep in dist.entry_points)
|
# Type ignored due to missing stub:
|
||||||
|
# https://github.com/python/typeshed/pull/3795
|
||||||
|
if any(ep.group == "pytest11" for ep in dist.entry_points) # type: ignore
|
||||||
for file in dist.files or []
|
for file in dist.files or []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -721,7 +721,9 @@ class FixtureRequest:
|
||||||
# this might also be a non-function Item despite its attribute name
|
# this might also be a non-function Item despite its attribute name
|
||||||
return self._pyfuncitem
|
return self._pyfuncitem
|
||||||
if scope == "package":
|
if scope == "package":
|
||||||
node = get_scope_package(self._pyfuncitem, self._fixturedef)
|
# FIXME: _fixturedef is not defined on FixtureRequest (this class),
|
||||||
|
# but on FixtureRequest (a subclass).
|
||||||
|
node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] # noqa: F821
|
||||||
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":
|
||||||
|
@ -1158,7 +1160,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)
|
result.__pytest_wrapped__ = _PytestWrapper(function) # type: ignore[attr-defined] # noqa: F821
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
# Imported here due to circular import.
|
# Imported here due to circular import.
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
|
from _pytest.warning_types import PytestWarning
|
||||||
|
|
||||||
|
|
||||||
SEP = "/"
|
SEP = "/"
|
||||||
|
|
||||||
|
@ -118,9 +120,9 @@ class Node(metaclass=NodeMeta):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
parent: Optional["Node"] = None,
|
parent: "Optional[Node]" = None,
|
||||||
config: Optional[Config] = None,
|
config: Optional[Config] = None,
|
||||||
session: Optional["Session"] = None,
|
session: "Optional[Session]" = None,
|
||||||
fspath: Optional[py.path.local] = None,
|
fspath: Optional[py.path.local] = None,
|
||||||
nodeid: Optional[str] = None,
|
nodeid: Optional[str] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -201,7 +203,7 @@ class Node(metaclass=NodeMeta):
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "<{} {}>".format(self.__class__.__name__, getattr(self, "name", None))
|
return "<{} {}>".format(self.__class__.__name__, getattr(self, "name", None))
|
||||||
|
|
||||||
def warn(self, warning):
|
def warn(self, warning: "PytestWarning") -> None:
|
||||||
"""Issue a warning for this item.
|
"""Issue a warning for this item.
|
||||||
|
|
||||||
Warnings will be displayed after the test session, unless explicitly suppressed
|
Warnings will be displayed after the test session, unless explicitly suppressed
|
||||||
|
@ -226,11 +228,9 @@ class Node(metaclass=NodeMeta):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
path, lineno = get_fslocation_from_item(self)
|
path, lineno = get_fslocation_from_item(self)
|
||||||
|
assert lineno is not None
|
||||||
warnings.warn_explicit(
|
warnings.warn_explicit(
|
||||||
warning,
|
warning, category=None, filename=str(path), lineno=lineno + 1,
|
||||||
category=None,
|
|
||||||
filename=str(path),
|
|
||||||
lineno=lineno + 1 if lineno is not None else None,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# methods for ordering nodes
|
# methods for ordering nodes
|
||||||
|
@ -417,24 +417,26 @@ class Node(metaclass=NodeMeta):
|
||||||
|
|
||||||
|
|
||||||
def get_fslocation_from_item(
|
def get_fslocation_from_item(
|
||||||
item: "Item",
|
node: "Node",
|
||||||
) -> Tuple[Union[str, py.path.local], Optional[int]]:
|
) -> Tuple[Union[str, py.path.local], Optional[int]]:
|
||||||
"""Tries to extract the actual location from an item, depending on available attributes:
|
"""Tries to extract the actual location from a node, depending on available attributes:
|
||||||
|
|
||||||
* "fslocation": a pair (path, lineno)
|
* "location": a pair (path, lineno)
|
||||||
* "obj": a Python object that the item wraps.
|
* "obj": a Python object that the node wraps.
|
||||||
* "fspath": just a path
|
* "fspath": just a path
|
||||||
|
|
||||||
:rtype: a tuple of (str|LocalPath, int) with filename and line number.
|
:rtype: a tuple of (str|LocalPath, int) with filename and line number.
|
||||||
"""
|
"""
|
||||||
try:
|
# See Item.location.
|
||||||
return item.location[:2]
|
location = getattr(
|
||||||
except AttributeError:
|
node, "location", None
|
||||||
pass
|
) # type: Optional[Tuple[str, Optional[int], str]]
|
||||||
obj = getattr(item, "obj", None)
|
if location is not None:
|
||||||
|
return location[:2]
|
||||||
|
obj = getattr(node, "obj", None)
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
return getfslineno(obj)
|
return getfslineno(obj)
|
||||||
return getattr(item, "fspath", "unknown location"), -1
|
return getattr(node, "fspath", "unknown location"), -1
|
||||||
|
|
||||||
|
|
||||||
class Collector(Node):
|
class Collector(Node):
|
||||||
|
|
|
@ -1169,8 +1169,10 @@ class Testdir:
|
||||||
|
|
||||||
popen = subprocess.Popen(cmdargs, stdout=stdout, stderr=stderr, **kw)
|
popen = subprocess.Popen(cmdargs, stdout=stdout, stderr=stderr, **kw)
|
||||||
if stdin is Testdir.CLOSE_STDIN:
|
if stdin is Testdir.CLOSE_STDIN:
|
||||||
|
assert popen.stdin is not None
|
||||||
popen.stdin.close()
|
popen.stdin.close()
|
||||||
elif isinstance(stdin, bytes):
|
elif isinstance(stdin, bytes):
|
||||||
|
assert popen.stdin is not None
|
||||||
popen.stdin.write(stdin)
|
popen.stdin.write(stdin)
|
||||||
|
|
||||||
return popen
|
return popen
|
||||||
|
|
|
@ -64,6 +64,7 @@ from _pytest.warning_types import PytestCollectionWarning
|
||||||
from _pytest.warning_types import PytestUnhandledCoroutineWarning
|
from _pytest.warning_types import PytestUnhandledCoroutineWarning
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from typing import Type
|
||||||
from typing_extensions import Literal
|
from typing_extensions import Literal
|
||||||
from _pytest.fixtures import _Scope
|
from _pytest.fixtures import _Scope
|
||||||
|
|
||||||
|
@ -256,6 +257,18 @@ def pytest_pycollect_makeitem(collector: "PyCollector", name: str, obj):
|
||||||
class PyobjMixin:
|
class PyobjMixin:
|
||||||
_ALLOW_MARKERS = True
|
_ALLOW_MARKERS = True
|
||||||
|
|
||||||
|
# Function and attributes that the mixin needs (for type-checking only).
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
name = "" # type: str
|
||||||
|
parent = None # type: Optional[nodes.Node]
|
||||||
|
own_markers = [] # type: List[Mark]
|
||||||
|
|
||||||
|
def getparent(self, cls: Type[nodes._NodeType]) -> Optional[nodes._NodeType]:
|
||||||
|
...
|
||||||
|
|
||||||
|
def listchain(self) -> List[nodes.Node]:
|
||||||
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def module(self):
|
def module(self):
|
||||||
"""Python module object this node was collected from (can be None)."""
|
"""Python module object this node was collected from (can be None)."""
|
||||||
|
@ -292,7 +305,10 @@ class PyobjMixin:
|
||||||
|
|
||||||
def _getobj(self):
|
def _getobj(self):
|
||||||
"""Gets the underlying Python object. May be overwritten by subclasses."""
|
"""Gets the underlying Python object. May be overwritten by subclasses."""
|
||||||
return getattr(self.parent.obj, self.name)
|
# TODO: Improve the type of `parent` such that assert/ignore aren't needed.
|
||||||
|
assert self.parent is not None
|
||||||
|
obj = self.parent.obj # type: ignore[attr-defined] # noqa: F821
|
||||||
|
return getattr(obj, self.name)
|
||||||
|
|
||||||
def getmodpath(self, stopatmodule=True, includemodule=False):
|
def getmodpath(self, stopatmodule=True, includemodule=False):
|
||||||
""" return python path relative to the containing module. """
|
""" return python path relative to the containing module. """
|
||||||
|
@ -772,7 +788,10 @@ class Instance(PyCollector):
|
||||||
# can be removed at node structure reorganization time
|
# can be removed at node structure reorganization time
|
||||||
|
|
||||||
def _getobj(self):
|
def _getobj(self):
|
||||||
return self.parent.obj()
|
# TODO: Improve the type of `parent` such that assert/ignore aren't needed.
|
||||||
|
assert self.parent is not None
|
||||||
|
obj = self.parent.obj # type: ignore[attr-defined] # noqa: F821
|
||||||
|
return obj()
|
||||||
|
|
||||||
def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:
|
def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:
|
||||||
self.session._fixturemanager.parsefactories(self)
|
self.session._fixturemanager.parsefactories(self)
|
||||||
|
@ -1527,7 +1546,8 @@ class Function(PyobjMixin, nodes.Item):
|
||||||
return getimfunc(self.obj)
|
return getimfunc(self.obj)
|
||||||
|
|
||||||
def _getobj(self):
|
def _getobj(self):
|
||||||
return getattr(self.parent.obj, self.originalname)
|
assert self.parent is not None
|
||||||
|
return getattr(self.parent.obj, self.originalname) # type: ignore[attr-defined]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _pyfuncitem(self):
|
def _pyfuncitem(self):
|
||||||
|
|
|
@ -508,7 +508,7 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
|
|
||||||
if isinstance(expected, Decimal):
|
if isinstance(expected, Decimal):
|
||||||
cls = ApproxDecimal
|
cls = ApproxDecimal # type: Type[ApproxBase]
|
||||||
elif isinstance(expected, Number):
|
elif isinstance(expected, Number):
|
||||||
cls = ApproxScalar
|
cls = ApproxScalar
|
||||||
elif isinstance(expected, Mapping):
|
elif isinstance(expected, Mapping):
|
||||||
|
@ -534,7 +534,7 @@ def _is_numpy_array(obj):
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
np = sys.modules.get("numpy")
|
np = sys.modules.get("numpy") # type: Any
|
||||||
if np is not None:
|
if np is not None:
|
||||||
return isinstance(obj, np.ndarray)
|
return isinstance(obj, np.ndarray)
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -136,8 +136,9 @@ class WarningsRecorder(warnings.catch_warnings):
|
||||||
Adapted from `warnings.catch_warnings`.
|
Adapted from `warnings.catch_warnings`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__(record=True)
|
# Type ignored due to the way typeshed handles warnings.catch_warnings.
|
||||||
|
super().__init__(record=True) # type: ignore[call-arg] # noqa: F821
|
||||||
self._entered = False
|
self._entered = False
|
||||||
self._list = [] # type: List[warnings.WarningMessage]
|
self._list = [] # type: List[warnings.WarningMessage]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue