-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
I ran into this while tracking down another issue.
In TerminalReporter.pytest_runtest_logstart
, we have:
pytest/src/_pytest/terminal.py
Lines 507 to 513 in adc1974
def pytest_runtest_logstart( | |
self, nodeid: str, location: Tuple[str, Optional[int], str] | |
) -> None: | |
# Ensure that the path is printed before the | |
# 1st test of a module starts running. | |
if self.showlongtestinfo: | |
line = self._locationline(nodeid, *location) |
where the first argument of location
is expected to be a string. But the func signature and impl of _locationline
and pathlib.bestrelpath
are actually expecting a Path
object:
pytest/src/_pytest/terminal.py
Lines 867 to 884 in adc1974
def _locationline(self, nodeid, fspath, lineno, domain): | |
def mkrel(nodeid): | |
line = self.config.cwd_relative_nodeid(nodeid) | |
if domain and line.endswith(domain): | |
line = line[: -len(domain)] | |
values = domain.split("[") | |
values[0] = values[0].replace(".", "::") # don't replace '.' in params | |
line += "[".join(values) | |
return line | |
# collect_fspath comes from testid which has a "/"-normalized path. | |
if fspath: | |
res = mkrel(nodeid) | |
if self.verbosity >= 2 and nodeid.split("::")[0] != fspath.replace( | |
"\\", nodes.SEP | |
): | |
res += " <- " + bestrelpath(self.startpath, fspath) |
Lines 680 to 698 in adc1974
def bestrelpath(directory: Path, dest: Path) -> str: | |
"""Return a string which is a relative path from directory to dest such | |
that directory/bestrelpath == dest. | |
The paths must be either both absolute or both relative. | |
If no such path can be determined, returns dest. | |
""" | |
if dest == directory: | |
return os.curdir | |
# Find the longest common directory. | |
base = commonpath(directory, dest) | |
# Can be the case on Windows for two absolute paths on different drives. | |
# Can be the case for two relative paths without common prefix. | |
# Can be the case for a relative path and an absolute path. | |
if not base: | |
return str(dest) | |
reldirectory = directory.relative_to(base) | |
reldest = dest.relative_to(base) |
Due to the __tracebackhide__ = True
line, this caused a harder-to-trackdown exception:
AttributeError: 'str' object has no attribute 'relative_to'
Apologies that I don't have a simple reproducible example (the code that generates this is a bit involved, bringing in twisted etc).
I experienced this when my report had location
attribute that was of the following form: (str, int, str)
right before calling: session.ihook.pytest_runtest_logreport(report=report)
in Python 3.8.6 with pytest 3.6.4 (and the code snippets above are from master, so I know the issue still exists). The situation was that nodeid.split("::")[0] != fspath.replace("\\", nodes.SEP)
, so we needed to call bestrelpath
which requires a Path
object.