[RFC] code location as a namedtuple

This commit is contained in:
Ronny Pfannschmidt 2020-11-21 14:17:31 +01:00
parent 431ec6d34e
commit a99885f344
3 changed files with 26 additions and 6 deletions

View File

@ -13,6 +13,7 @@ from pathlib import Path
from typing import Any
from typing import Callable
from typing import Generic
from typing import NamedTuple
from typing import NoReturn
from typing import TYPE_CHECKING
from typing import TypeVar
@ -94,17 +95,35 @@ def is_async_function(func: object) -> bool:
def getlocation(function, curdir: str | None = None) -> str:
class CodeLocation(NamedTuple):
path: Path
lineno: int
def CodeLocation__str__(self: CodeLocation) -> str:
"""Python 3.6 hack for NamedTuple __str__"""
return f"{self.path}:{self.lineno}"
setattr(CodeLocation, "__str__", CodeLocation__str__)
def getlocation(function, curdir: Path | None) -> CodeLocation:
function = get_real_func(function)
fn = Path(inspect.getfile(function))
lineno = function.__code__.co_firstlineno
# TODO: this cycle indicates a larger issue
from .pathlib import bestrelpath
if curdir is not None:
try:
relfn = fn.relative_to(curdir)
relfn = Path(bestrelpath(curdir, fn))
except ValueError:
pass
else:
return "%s:%d" % (relfn, lineno + 1)
return "%s:%d" % (fn, lineno + 1)
return CodeLocation(relfn, lineno + 1)
return CodeLocation(fn, lineno + 1)
def num_mock_patch_args(function) -> int:

View File

@ -1210,7 +1210,7 @@ class FixtureFunctionMarker:
name = self.name or function.__name__
if name == "request":
location = getlocation(function)
location = getlocation(function, None)
fail(
"'request' is a reserved word for fixtures, use another name:\n {}".format(
location

View File

@ -39,6 +39,7 @@ from _pytest._io import TerminalWriter
from _pytest._io.saferepr import saferepr
from _pytest.compat import ascii_escaped
from _pytest.compat import assert_never
from _pytest.compat import CodeLocation
from _pytest.compat import final
from _pytest.compat import get_default_arg_names
from _pytest.compat import get_real_func
@ -1634,14 +1635,14 @@ def _showfixtures_main(config: Config, session: Session) -> None:
fm = session._fixturemanager
available = []
seen: Set[Tuple[str, str]] = set()
seen: Set[Tuple[str, CodeLocation]] = set()
for argname, fixturedefs in fm._arg2fixturedefs.items():
assert fixturedefs is not None
if not fixturedefs:
continue
for fixturedef in fixturedefs:
loc = getlocation(fixturedef.func, str(curdir))
loc = getlocation(fixturedef.func, curdir)
if (fixturedef.argname, loc) in seen:
continue
seen.add((fixturedef.argname, loc))