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_return_any = True
|
||||
warn_unused_configs = True
|
||||
|
||||
[mypy-_pytest.*]
|
||||
check_untyped_defs = True
|
||||
|
|
|
@ -519,10 +519,11 @@ class MultiCapture:
|
|||
def pop_outerr_to_orig(self):
|
||||
""" pop current snapshot out/err capture and flush to orig streams. """
|
||||
out, err = self.readouterr()
|
||||
# TODO: Fix type ignores.
|
||||
if out:
|
||||
self.out.writeorg(out)
|
||||
self.out.writeorg(out) # type: ignore[union-attr] # noqa: F821
|
||||
if err:
|
||||
self.err.writeorg(err)
|
||||
self.err.writeorg(err) # type: ignore[union-attr] # noqa: F821
|
||||
return out, err
|
||||
|
||||
def suspend_capturing(self, in_: bool = False) -> None:
|
||||
|
@ -542,7 +543,8 @@ class MultiCapture:
|
|||
if self.err:
|
||||
self.err.resume()
|
||||
if self._in_suspended:
|
||||
self.in_.resume()
|
||||
# TODO: Fix type ignore.
|
||||
self.in_.resume() # type: ignore[union-attr] # noqa: F821
|
||||
self._in_suspended = False
|
||||
|
||||
def stop_capturing(self) -> None:
|
||||
|
|
|
@ -974,7 +974,7 @@ class Config:
|
|||
self._mark_plugins_for_rewrite(hook)
|
||||
_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
|
||||
modules or packages in the distribution package for
|
||||
|
@ -989,7 +989,9 @@ class Config:
|
|||
package_files = (
|
||||
str(file)
|
||||
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 []
|
||||
)
|
||||
|
||||
|
|
|
@ -721,7 +721,9 @@ class FixtureRequest:
|
|||
# this might also be a non-function Item despite its attribute name
|
||||
return self._pyfuncitem
|
||||
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:
|
||||
node = get_scope_node(self._pyfuncitem, scope)
|
||||
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
|
||||
# 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
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ if TYPE_CHECKING:
|
|||
|
||||
# Imported here due to circular import.
|
||||
from _pytest.main import Session
|
||||
from _pytest.warning_types import PytestWarning
|
||||
|
||||
|
||||
SEP = "/"
|
||||
|
||||
|
@ -118,9 +120,9 @@ class Node(metaclass=NodeMeta):
|
|||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
parent: Optional["Node"] = None,
|
||||
parent: "Optional[Node]" = None,
|
||||
config: Optional[Config] = None,
|
||||
session: Optional["Session"] = None,
|
||||
session: "Optional[Session]" = None,
|
||||
fspath: Optional[py.path.local] = None,
|
||||
nodeid: Optional[str] = None,
|
||||
) -> None:
|
||||
|
@ -201,7 +203,7 @@ class Node(metaclass=NodeMeta):
|
|||
def __repr__(self) -> str:
|
||||
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.
|
||||
|
||||
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)
|
||||
assert lineno is not None
|
||||
warnings.warn_explicit(
|
||||
warning,
|
||||
category=None,
|
||||
filename=str(path),
|
||||
lineno=lineno + 1 if lineno is not None else None,
|
||||
warning, category=None, filename=str(path), lineno=lineno + 1,
|
||||
)
|
||||
|
||||
# methods for ordering nodes
|
||||
|
@ -417,24 +417,26 @@ class Node(metaclass=NodeMeta):
|
|||
|
||||
|
||||
def get_fslocation_from_item(
|
||||
item: "Item",
|
||||
node: "Node",
|
||||
) -> 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)
|
||||
* "obj": a Python object that the item wraps.
|
||||
* "location": a pair (path, lineno)
|
||||
* "obj": a Python object that the node wraps.
|
||||
* "fspath": just a path
|
||||
|
||||
:rtype: a tuple of (str|LocalPath, int) with filename and line number.
|
||||
"""
|
||||
try:
|
||||
return item.location[:2]
|
||||
except AttributeError:
|
||||
pass
|
||||
obj = getattr(item, "obj", None)
|
||||
# See Item.location.
|
||||
location = getattr(
|
||||
node, "location", None
|
||||
) # type: Optional[Tuple[str, Optional[int], str]]
|
||||
if location is not None:
|
||||
return location[:2]
|
||||
obj = getattr(node, "obj", None)
|
||||
if obj is not None:
|
||||
return getfslineno(obj)
|
||||
return getattr(item, "fspath", "unknown location"), -1
|
||||
return getattr(node, "fspath", "unknown location"), -1
|
||||
|
||||
|
||||
class Collector(Node):
|
||||
|
|
|
@ -1169,8 +1169,10 @@ class Testdir:
|
|||
|
||||
popen = subprocess.Popen(cmdargs, stdout=stdout, stderr=stderr, **kw)
|
||||
if stdin is Testdir.CLOSE_STDIN:
|
||||
assert popen.stdin is not None
|
||||
popen.stdin.close()
|
||||
elif isinstance(stdin, bytes):
|
||||
assert popen.stdin is not None
|
||||
popen.stdin.write(stdin)
|
||||
|
||||
return popen
|
||||
|
|
|
@ -64,6 +64,7 @@ from _pytest.warning_types import PytestCollectionWarning
|
|||
from _pytest.warning_types import PytestUnhandledCoroutineWarning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Type
|
||||
from typing_extensions import Literal
|
||||
from _pytest.fixtures import _Scope
|
||||
|
||||
|
@ -256,6 +257,18 @@ def pytest_pycollect_makeitem(collector: "PyCollector", name: str, obj):
|
|||
class PyobjMixin:
|
||||
_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
|
||||
def module(self):
|
||||
"""Python module object this node was collected from (can be None)."""
|
||||
|
@ -292,7 +305,10 @@ class PyobjMixin:
|
|||
|
||||
def _getobj(self):
|
||||
"""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):
|
||||
""" return python path relative to the containing module. """
|
||||
|
@ -772,7 +788,10 @@ class Instance(PyCollector):
|
|||
# can be removed at node structure reorganization time
|
||||
|
||||
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]]:
|
||||
self.session._fixturemanager.parsefactories(self)
|
||||
|
@ -1527,7 +1546,8 @@ class Function(PyobjMixin, nodes.Item):
|
|||
return getimfunc(self.obj)
|
||||
|
||||
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
|
||||
def _pyfuncitem(self):
|
||||
|
|
|
@ -508,7 +508,7 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
|
|||
__tracebackhide__ = True
|
||||
|
||||
if isinstance(expected, Decimal):
|
||||
cls = ApproxDecimal
|
||||
cls = ApproxDecimal # type: Type[ApproxBase]
|
||||
elif isinstance(expected, Number):
|
||||
cls = ApproxScalar
|
||||
elif isinstance(expected, Mapping):
|
||||
|
@ -534,7 +534,7 @@ def _is_numpy_array(obj):
|
|||
"""
|
||||
import sys
|
||||
|
||||
np = sys.modules.get("numpy")
|
||||
np = sys.modules.get("numpy") # type: Any
|
||||
if np is not None:
|
||||
return isinstance(obj, np.ndarray)
|
||||
return False
|
||||
|
|
|
@ -136,8 +136,9 @@ class WarningsRecorder(warnings.catch_warnings):
|
|||
Adapted from `warnings.catch_warnings`.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(record=True)
|
||||
def __init__(self) -> None:
|
||||
# Type ignored due to the way typeshed handles warnings.catch_warnings.
|
||||
super().__init__(record=True) # type: ignore[call-arg] # noqa: F821
|
||||
self._entered = False
|
||||
self._list = [] # type: List[warnings.WarningMessage]
|
||||
|
||||
|
|
Loading…
Reference in New Issue