diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 7cbb676bd..8817c5749 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -82,8 +82,8 @@ class Parser: self.optparser = self._getparser() try_argcomplete(self.optparser) - args = [str(x) if isinstance(x, py.path.local) else x for x in args] - return self.optparser.parse_args(args, namespace=namespace) + strargs = [str(x) if isinstance(x, py.path.local) else x for x in args] + return self.optparser.parse_args(strargs, namespace=namespace) def _getparser(self) -> "MyOptionParser": from _pytest._argcomplete import filescompleter @@ -124,8 +124,8 @@ class Parser: the remaining arguments unknown at this point. """ optparser = self._getparser() - args = [str(x) if isinstance(x, py.path.local) else x for x in args] - return optparser.parse_known_args(args, namespace=namespace) + strargs = [str(x) if isinstance(x, py.path.local) else x for x in args] + return optparser.parse_known_args(strargs, namespace=namespace) def addini(self, name, help, type=None, default=None): """ register an ini-file option. diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 707ce969d..fb84160c1 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -1,6 +1,9 @@ import os +from typing import Any +from typing import Iterable from typing import List from typing import Optional +from typing import Tuple import py @@ -60,7 +63,7 @@ def getcfg(args, config=None): return None, None, None -def get_common_ancestor(paths): +def get_common_ancestor(paths: Iterable[py.path.local]) -> py.path.local: common_ancestor = None for path in paths: if not path.exists(): @@ -113,7 +116,7 @@ def determine_setup( args: List[str], rootdir_cmd_arg: Optional[str] = None, config: Optional["Config"] = None, -): +) -> Tuple[py.path.local, Optional[str], Any]: dirs = get_dirs_from_args(args) if inifile: iniconfig = py.iniconfig.IniConfig(inifile) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index e62c5e17e..d7ca888cc 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -308,7 +308,7 @@ class DoctestItem(pytest.Item): else: return super().repr_failure(excinfo) - def reportinfo(self) -> Tuple[str, int, str]: + def reportinfo(self) -> Tuple[py.path.local, int, str]: return self.fspath, self.dtest.lineno, "[doctest] %s" % self.name diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index e576e4cbb..c3cd162cc 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -351,7 +351,7 @@ class FixtureRequest: self.fixturename = None #: Scope string, one of "function", "class", "module", "session" self.scope = "function" - self._fixture_defs = {} # argname -> FixtureDef + self._fixture_defs = {} # type: Dict[str, FixtureDef] fixtureinfo = pyfuncitem._fixtureinfo self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy() self._arg2index = {} @@ -426,7 +426,8 @@ class FixtureRequest: @scopeproperty() def fspath(self) -> py.path.local: """ the file system path of the test module which collected this test. """ - return self._pyfuncitem.fspath + # TODO: Remove ignore once _pyfuncitem is properly typed. + return self._pyfuncitem.fspath # type: ignore @property def keywords(self): @@ -549,7 +550,9 @@ class FixtureRequest: source_lineno = frameinfo.lineno source_path = py.path.local(source_path) if source_path.relto(funcitem.config.rootdir): - source_path = source_path.relto(funcitem.config.rootdir) + source_path_str = source_path.relto(funcitem.config.rootdir) + else: + source_path_str = str(source_path) msg = ( "The requested fixture has no parameter defined for test:\n" " {}\n\n" @@ -558,7 +561,7 @@ class FixtureRequest: funcitem.nodeid, fixturedef.argname, getlocation(fixturedef.func, funcitem.config.rootdir), - source_path, + source_path_str, source_lineno, ) ) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index a0f180cac..d6d512938 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -367,9 +367,9 @@ class Failed(Exception): @attr.s class _bestrelpath_cache(dict): - path = attr.ib() + path = attr.ib(type=py.path.local) - def __missing__(self, path: str) -> str: + def __missing__(self, path: py.path.local) -> str: r = self.path.bestrelpath(path) # type: str self[path] = r return r @@ -399,7 +399,7 @@ class Session(nodes.FSCollector): self._node_cache = {} self._bestrelpathcache = _bestrelpath_cache( config.rootdir - ) # type: Dict[str, str] + ) # type: Dict[py.path.local, str] # Dirnames of pkgs with dunder-init files. self._pkg_roots = {} @@ -414,7 +414,7 @@ class Session(nodes.FSCollector): self.testscollected, ) - def _node_location_to_relpath(self, node_path: str) -> str: + def _node_location_to_relpath(self, node_path: py.path.local) -> str: # bestrelpath is a quite slow function return self._bestrelpathcache[node_path] diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 3cfbf4626..fc951d2bc 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -462,6 +462,7 @@ class Item(Node): @cached_property def location(self) -> Tuple[str, Optional[int], str]: location = self.reportinfo() + assert isinstance(location[0], py.path.local), location[0] fspath = self.session._node_location_to_relpath(location[0]) assert type(location[2]) is str return (fspath, location[1], location[2]) diff --git a/testing/python/collect.py b/testing/python/collect.py index 6e9938227..a68738c81 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1018,10 +1018,10 @@ class TestReportInfo: def test_itemreport_reportinfo(self, testdir): testdir.makeconftest( """ - import pytest + import pytest, py class MyFunction(pytest.Function): def reportinfo(self): - return "ABCDE", 42, "custom" + return py.path.local("foo"), 42, "custom" def pytest_pycollect_makeitem(collector, name, obj): if name == "test_func": return MyFunction(name, parent=collector) @@ -1029,7 +1029,7 @@ class TestReportInfo: ) item = testdir.getitem("def test_func(): pass") item.config.pluginmanager.getplugin("runner") - assert item.location == ("ABCDE", 42, "custom") + assert item.location == ("foo", 42, "custom") def test_func_reportinfo(self, testdir): item = testdir.getitem("def test_func(): pass")