Merge pull request #6518 from bluetech/fix-py-typed-fixes-regression

Fix internal assert failure regression in 5.3.4
This commit is contained in:
Ran Benita 2020-01-21 00:01:07 +02:00 committed by GitHub
commit a52f791461
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 32 additions and 25 deletions

View File

@ -82,8 +82,8 @@ class Parser:
self.optparser = self._getparser() self.optparser = self._getparser()
try_argcomplete(self.optparser) try_argcomplete(self.optparser)
strargs = [str(x) if isinstance(x, py.path.local) else x for x in args] args = [str(x) if isinstance(x, py.path.local) else x for x in args]
return self.optparser.parse_args(strargs, namespace=namespace) return self.optparser.parse_args(args, namespace=namespace)
def _getparser(self) -> "MyOptionParser": def _getparser(self) -> "MyOptionParser":
from _pytest._argcomplete import filescompleter from _pytest._argcomplete import filescompleter
@ -124,8 +124,8 @@ class Parser:
the remaining arguments unknown at this point. the remaining arguments unknown at this point.
""" """
optparser = self._getparser() optparser = self._getparser()
strargs = [str(x) if isinstance(x, py.path.local) else x for x in args] args = [str(x) if isinstance(x, py.path.local) else x for x in args]
return optparser.parse_known_args(strargs, namespace=namespace) return optparser.parse_known_args(args, namespace=namespace)
def addini(self, name, help, type=None, default=None): def addini(self, name, help, type=None, default=None):
""" register an ini-file option. """ register an ini-file option.

View File

@ -1,9 +1,6 @@
import os import os
from typing import Any
from typing import Iterable
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Tuple
import py import py
@ -63,7 +60,7 @@ def getcfg(args, config=None):
return None, None, None return None, None, None
def get_common_ancestor(paths: Iterable[py.path.local]) -> py.path.local: def get_common_ancestor(paths):
common_ancestor = None common_ancestor = None
for path in paths: for path in paths:
if not path.exists(): if not path.exists():
@ -116,7 +113,7 @@ def determine_setup(
args: List[str], args: List[str],
rootdir_cmd_arg: Optional[str] = None, rootdir_cmd_arg: Optional[str] = None,
config: Optional["Config"] = None, config: Optional["Config"] = None,
) -> Tuple[py.path.local, Optional[str], Any]: ):
dirs = get_dirs_from_args(args) dirs = get_dirs_from_args(args)
if inifile: if inifile:
iniconfig = py.iniconfig.IniConfig(inifile) iniconfig = py.iniconfig.IniConfig(inifile)

View File

@ -308,7 +308,7 @@ class DoctestItem(pytest.Item):
else: else:
return super().repr_failure(excinfo) return super().repr_failure(excinfo)
def reportinfo(self) -> Tuple[py.path.local, int, str]: def reportinfo(self) -> Tuple[str, int, str]:
return self.fspath, self.dtest.lineno, "[doctest] %s" % self.name return self.fspath, self.dtest.lineno, "[doctest] %s" % self.name

View File

@ -351,7 +351,7 @@ class FixtureRequest:
self.fixturename = None self.fixturename = None
#: Scope string, one of "function", "class", "module", "session" #: Scope string, one of "function", "class", "module", "session"
self.scope = "function" self.scope = "function"
self._fixture_defs = {} # type: Dict[str, FixtureDef] self._fixture_defs = {} # argname -> FixtureDef
fixtureinfo = pyfuncitem._fixtureinfo fixtureinfo = pyfuncitem._fixtureinfo
self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy() self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy()
self._arg2index = {} self._arg2index = {}
@ -426,8 +426,7 @@ class FixtureRequest:
@scopeproperty() @scopeproperty()
def fspath(self) -> py.path.local: def fspath(self) -> py.path.local:
""" the file system path of the test module which collected this test. """ """ the file system path of the test module which collected this test. """
# TODO: Remove ignore once _pyfuncitem is properly typed. return self._pyfuncitem.fspath
return self._pyfuncitem.fspath # type: ignore
@property @property
def keywords(self): def keywords(self):
@ -550,9 +549,7 @@ class FixtureRequest:
source_lineno = frameinfo.lineno source_lineno = frameinfo.lineno
source_path = py.path.local(source_path) source_path = py.path.local(source_path)
if source_path.relto(funcitem.config.rootdir): if source_path.relto(funcitem.config.rootdir):
source_path_str = source_path.relto(funcitem.config.rootdir) source_path = source_path.relto(funcitem.config.rootdir)
else:
source_path_str = str(source_path)
msg = ( msg = (
"The requested fixture has no parameter defined for test:\n" "The requested fixture has no parameter defined for test:\n"
" {}\n\n" " {}\n\n"
@ -561,7 +558,7 @@ class FixtureRequest:
funcitem.nodeid, funcitem.nodeid,
fixturedef.argname, fixturedef.argname,
getlocation(fixturedef.func, funcitem.config.rootdir), getlocation(fixturedef.func, funcitem.config.rootdir),
source_path_str, source_path,
source_lineno, source_lineno,
) )
) )

View File

@ -367,9 +367,9 @@ class Failed(Exception):
@attr.s @attr.s
class _bestrelpath_cache(dict): class _bestrelpath_cache(dict):
path = attr.ib(type=py.path.local) path = attr.ib()
def __missing__(self, path: py.path.local) -> str: def __missing__(self, path: str) -> str:
r = self.path.bestrelpath(path) # type: str r = self.path.bestrelpath(path) # type: str
self[path] = r self[path] = r
return r return r
@ -399,7 +399,7 @@ class Session(nodes.FSCollector):
self._node_cache = {} self._node_cache = {}
self._bestrelpathcache = _bestrelpath_cache( self._bestrelpathcache = _bestrelpath_cache(
config.rootdir config.rootdir
) # type: Dict[py.path.local, str] ) # type: Dict[str, str]
# Dirnames of pkgs with dunder-init files. # Dirnames of pkgs with dunder-init files.
self._pkg_roots = {} self._pkg_roots = {}
@ -414,7 +414,7 @@ class Session(nodes.FSCollector):
self.testscollected, self.testscollected,
) )
def _node_location_to_relpath(self, node_path: py.path.local) -> str: def _node_location_to_relpath(self, node_path: str) -> str:
# bestrelpath is a quite slow function # bestrelpath is a quite slow function
return self._bestrelpathcache[node_path] return self._bestrelpathcache[node_path]

View File

@ -462,7 +462,6 @@ class Item(Node):
@cached_property @cached_property
def location(self) -> Tuple[str, Optional[int], str]: def location(self) -> Tuple[str, Optional[int], str]:
location = self.reportinfo() location = self.reportinfo()
assert isinstance(location[0], py.path.local), location[0]
fspath = self.session._node_location_to_relpath(location[0]) fspath = self.session._node_location_to_relpath(location[0])
assert type(location[2]) is str assert type(location[2]) is str
return (fspath, location[1], location[2]) return (fspath, location[1], location[2])

View File

@ -1018,10 +1018,10 @@ class TestReportInfo:
def test_itemreport_reportinfo(self, testdir): def test_itemreport_reportinfo(self, testdir):
testdir.makeconftest( testdir.makeconftest(
""" """
import pytest, py import pytest
class MyFunction(pytest.Function): class MyFunction(pytest.Function):
def reportinfo(self): def reportinfo(self):
return py.path.local("foo"), 42, "custom" return "ABCDE", 42, "custom"
def pytest_pycollect_makeitem(collector, name, obj): def pytest_pycollect_makeitem(collector, name, obj):
if name == "test_func": if name == "test_func":
return MyFunction(name, parent=collector) return MyFunction(name, parent=collector)
@ -1029,7 +1029,7 @@ class TestReportInfo:
) )
item = testdir.getitem("def test_func(): pass") item = testdir.getitem("def test_func(): pass")
item.config.pluginmanager.getplugin("runner") item.config.pluginmanager.getplugin("runner")
assert item.location == ("foo", 42, "custom") assert item.location == ("ABCDE", 42, "custom")
def test_func_reportinfo(self, testdir): def test_func_reportinfo(self, testdir):
item = testdir.getitem("def test_func(): pass") item = testdir.getitem("def test_func(): pass")

View File

@ -375,3 +375,17 @@ def test_skip_test_with_unicode(testdir):
) )
result = testdir.runpytest() result = testdir.runpytest()
result.stdout.fnmatch_lines(["* 1 skipped *"]) result.stdout.fnmatch_lines(["* 1 skipped *"])
def test_issue_6517(testdir):
testdir.makepyfile(
"""
from nose.tools import raises
@raises(RuntimeError)
def test_fail_without_tcp():
raise RuntimeError
"""
)
result = testdir.runpytest()
result.stdout.fnmatch_lines(["* 1 passed *"])