|
43 | 43 | from _pytest._code.code import TerminalRepr |
44 | 44 | from _pytest._io import TerminalWriter |
45 | 45 | from _pytest.compat import assert_never |
46 | | -from _pytest.compat import get_real_func |
47 | | -from _pytest.compat import getfuncargnames |
48 | 46 | from _pytest.compat import getimfunc |
49 | | -from _pytest.compat import getlocation |
50 | 47 | from _pytest.compat import is_generator |
51 | 48 | from _pytest.compat import NOTSET |
52 | 49 | from _pytest.compat import NotSetType |
|
58 | 55 | from _pytest.deprecated import check_ispytest |
59 | 56 | from _pytest.deprecated import MARKED_FIXTURE |
60 | 57 | from _pytest.deprecated import YIELD_FIXTURE |
| 58 | +from _pytest.fixtures import getfuncargnames |
61 | 59 | from _pytest.main import Session |
62 | 60 | from _pytest.mark import Mark |
63 | 61 | from _pytest.mark import ParameterSet |
@@ -1914,3 +1912,40 @@ def _showfixtures_main(config: Config, session: Session) -> None: |
1914 | 1912 | def write_docstring(tw: TerminalWriter, doc: str, indent: str = " ") -> None: |
1915 | 1913 | for line in doc.split("\n"): |
1916 | 1914 | tw.line(indent + line) |
| 1915 | + |
| 1916 | + |
| 1917 | +def get_real_func(obj): |
| 1918 | + """Get the real function object of the (possibly) wrapped object by |
| 1919 | + :func:`functools.wraps`, or :func:`functools.partial`, or :func:`pytest.fixture`.""" |
| 1920 | + start_obj = obj |
| 1921 | + for _ in range(100): |
| 1922 | + if isinstance(obj, FixtureFunctionDefinition): |
| 1923 | + obj = obj._get_wrapped_function() |
| 1924 | + break |
| 1925 | + new_obj = getattr(obj, "__wrapped__", None) |
| 1926 | + if new_obj is None: |
| 1927 | + break |
| 1928 | + obj = new_obj |
| 1929 | + else: |
| 1930 | + from _pytest._io.saferepr import saferepr |
| 1931 | + |
| 1932 | + raise ValueError( |
| 1933 | + f"could not find real function of {saferepr(start_obj)}\nstopped at {saferepr(obj)}" |
| 1934 | + ) |
| 1935 | + if isinstance(obj, functools.partial): |
| 1936 | + obj = obj.func |
| 1937 | + return obj |
| 1938 | + |
| 1939 | + |
| 1940 | +def getlocation(function, curdir: str | os.PathLike[str] | None = None) -> str: |
| 1941 | + function = get_real_func(function) |
| 1942 | + fn = Path(inspect.getfile(function)) |
| 1943 | + lineno = function.__code__.co_firstlineno |
| 1944 | + if curdir is not None: |
| 1945 | + try: |
| 1946 | + relfn = fn.relative_to(curdir) |
| 1947 | + except ValueError: |
| 1948 | + pass |
| 1949 | + else: |
| 1950 | + return "%s:%d" % (relfn, lineno + 1) |
| 1951 | + return "%s:%d" % (fn, lineno + 1) |
0 commit comments