Skip to content

internal: clean up getfslineno #6656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/_pytest/_code/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ def path(self) -> Union[py.path.local, str]:
""" return a path object pointing to source code (or a str in case
of OSError / non-existing file).
"""
if not self.raw.co_filename:
return ""
try:
p = py.path.local(self.raw.co_filename)
# maybe don't try this checking
Expand Down
19 changes: 13 additions & 6 deletions src/_pytest/_code/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from bisect import bisect_right
from types import CodeType
from types import FrameType
from typing import Any
from typing import Iterator
from typing import List
from typing import Optional
Expand All @@ -17,6 +18,7 @@

import py

from _pytest.compat import get_real_func
from _pytest.compat import overload
from _pytest.compat import TYPE_CHECKING

Expand Down Expand Up @@ -282,14 +284,21 @@ def compile_( # noqa: F811
return s.compile(filename, mode, flags, _genframe=_genframe)


def getfslineno(obj) -> Tuple[Optional[Union["Literal['']", py.path.local]], int]:
def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bluetech had to take Any here instead of obj, for the place_as attribute check.

""" Return source location (path, lineno) for the given object.
If the source cannot be determined return ("", -1).

The line number is 0-based.
"""
from .code import Code

# xxx let decorators etc specify a sane ordering
# NOTE: this used to be done in _pytest.compat.getfslineno, initially added
# in 6ec13a2b9. It ("place_as") appears to be something very custom.
obj = get_real_func(obj)
if hasattr(obj, "place_as"):
obj = obj.place_as

try:
code = Code(obj)
except TypeError:
Expand All @@ -298,18 +307,16 @@ def getfslineno(obj) -> Tuple[Optional[Union["Literal['']", py.path.local]], int
except TypeError:
return "", -1

fspath = fn and py.path.local(fn) or None
fspath = fn and py.path.local(fn) or ""
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cannot really happen (becoming "", only if co_filename is empty on a code object, but that gets handled by Code then, which I've fixed to keep it (instead of turning it into cwd).
But I guess the or "" does not hurt - at least I'm confident that it never returned None actually.

lineno = -1
if fspath:
try:
_, lineno = findsource(obj)
except IOError:
pass
return fspath, lineno
else:
fspath = code.path
lineno = code.firstlineno
assert isinstance(lineno, int)
return fspath, lineno
return code.path, code.firstlineno


#
Expand Down
11 changes: 0 additions & 11 deletions src/_pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import attr
import py

import _pytest
from _pytest._io.saferepr import saferepr
from _pytest.outcomes import fail
from _pytest.outcomes import TEST_OUTCOME
Expand Down Expand Up @@ -307,16 +306,6 @@ def get_real_method(obj, holder):
return obj


def getfslineno(obj) -> Tuple[Union[str, py.path.local], int]:
# xxx let decorators etc specify a sane ordering
obj = get_real_func(obj)
if hasattr(obj, "place_as"):
obj = obj.place_as
fslineno = _pytest._code.getfslineno(obj)
assert isinstance(fslineno[1], int), obj
return fslineno


def getimfunc(func):
try:
return func.__func__
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
import _pytest
from _pytest._code.code import FormattedExcinfo
from _pytest._code.code import TerminalRepr
from _pytest._code.source import getfslineno
from _pytest._io import TerminalWriter
from _pytest.compat import _format_args
from _pytest.compat import _PytestWrapper
from _pytest.compat import get_real_func
from _pytest.compat import get_real_method
from _pytest.compat import getfslineno
from _pytest.compat import getfuncargnames
from _pytest.compat import getimfunc
from _pytest.compat import getlocation
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/mark/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

import attr

from .._code.source import getfslineno
from ..compat import ascii_escaped
from ..compat import ATTRS_EQ_FIELD
from ..compat import getfslineno
from ..compat import NOTSET
from _pytest.outcomes import fail
from _pytest.warning_types import PytestUnknownMarkWarning
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
from _pytest._code.code import ExceptionChainRepr
from _pytest._code.code import ExceptionInfo
from _pytest._code.code import ReprExceptionInfo
from _pytest._code.source import getfslineno
from _pytest.compat import cached_property
from _pytest.compat import getfslineno
from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config
from _pytest.config import PytestPluginManager
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
from _pytest import fixtures
from _pytest import nodes
from _pytest._code import filter_traceback
from _pytest._code.source import getfslineno
from _pytest.compat import ascii_escaped
from _pytest.compat import get_default_arg_names
from _pytest.compat import get_real_func
from _pytest.compat import getfslineno
from _pytest.compat import getimfunc
from _pytest.compat import getlocation
from _pytest.compat import is_generator
Expand Down
8 changes: 8 additions & 0 deletions testing/code/test_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,14 @@ class B:
B.__name__ = "B2"
assert getfslineno(B)[1] == -1

co = compile("...", "", "eval")
assert co.co_filename == ""

if hasattr(sys, "pypy_version_info"):
assert getfslineno(co) == ("", -1)
else:
assert getfslineno(co) == ("", 0)


def test_code_of_object_instance_with_call() -> None:
class A:
Expand Down