Merge pull request #7171 from bluetech/code-import-cycles
code: fix import cycles between code.py and source.py
This commit is contained in:
commit
d16ae0bbdc
|
@ -1,10 +1,22 @@
|
||||||
""" python inspection/code generation API """
|
"""Python inspection/code generation API."""
|
||||||
from .code import Code # noqa
|
from .code import Code
|
||||||
from .code import ExceptionInfo # noqa
|
from .code import ExceptionInfo
|
||||||
from .code import filter_traceback # noqa
|
from .code import filter_traceback
|
||||||
from .code import Frame # noqa
|
from .code import Frame
|
||||||
from .code import getrawcode # noqa
|
from .code import getfslineno
|
||||||
from .code import Traceback # noqa
|
from .code import getrawcode
|
||||||
from .source import compile_ as compile # noqa
|
from .code import Traceback
|
||||||
from .source import getfslineno # noqa
|
from .source import compile_ as compile
|
||||||
from .source import Source # noqa
|
from .source import Source
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Code",
|
||||||
|
"ExceptionInfo",
|
||||||
|
"filter_traceback",
|
||||||
|
"Frame",
|
||||||
|
"getfslineno",
|
||||||
|
"getrawcode",
|
||||||
|
"Traceback",
|
||||||
|
"compile",
|
||||||
|
"Source",
|
||||||
|
]
|
||||||
|
|
|
@ -29,10 +29,15 @@ import pluggy
|
||||||
import py
|
import py
|
||||||
|
|
||||||
import _pytest
|
import _pytest
|
||||||
|
from _pytest._code.source import findsource
|
||||||
|
from _pytest._code.source import getrawcode
|
||||||
|
from _pytest._code.source import getstatementrange_ast
|
||||||
|
from _pytest._code.source import Source
|
||||||
from _pytest._io import TerminalWriter
|
from _pytest._io import TerminalWriter
|
||||||
from _pytest._io.saferepr import safeformat
|
from _pytest._io.saferepr import safeformat
|
||||||
from _pytest._io.saferepr import saferepr
|
from _pytest._io.saferepr import saferepr
|
||||||
from _pytest.compat import ATTRS_EQ_FIELD
|
from _pytest.compat import ATTRS_EQ_FIELD
|
||||||
|
from _pytest.compat import get_real_func
|
||||||
from _pytest.compat import overload
|
from _pytest.compat import overload
|
||||||
from _pytest.compat import TYPE_CHECKING
|
from _pytest.compat import TYPE_CHECKING
|
||||||
|
|
||||||
|
@ -41,8 +46,6 @@ if TYPE_CHECKING:
|
||||||
from typing_extensions import Literal
|
from typing_extensions import Literal
|
||||||
from weakref import ReferenceType # noqa: F401
|
from weakref import ReferenceType # noqa: F401
|
||||||
|
|
||||||
from _pytest._code import Source
|
|
||||||
|
|
||||||
_TracebackStyle = Literal["long", "short", "line", "no", "native"]
|
_TracebackStyle = Literal["long", "short", "line", "no", "native"]
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,18 +93,14 @@ class Code:
|
||||||
def fullsource(self) -> Optional["Source"]:
|
def fullsource(self) -> Optional["Source"]:
|
||||||
""" return a _pytest._code.Source object for the full source file of the code
|
""" return a _pytest._code.Source object for the full source file of the code
|
||||||
"""
|
"""
|
||||||
from _pytest._code import source
|
full, _ = findsource(self.raw)
|
||||||
|
|
||||||
full, _ = source.findsource(self.raw)
|
|
||||||
return full
|
return full
|
||||||
|
|
||||||
def source(self) -> "Source":
|
def source(self) -> "Source":
|
||||||
""" return a _pytest._code.Source object for the code object's source only
|
""" return a _pytest._code.Source object for the code object's source only
|
||||||
"""
|
"""
|
||||||
# return source only for that part of code
|
# return source only for that part of code
|
||||||
import _pytest._code
|
return Source(self.raw)
|
||||||
|
|
||||||
return _pytest._code.Source(self.raw)
|
|
||||||
|
|
||||||
def getargs(self, var: bool = False) -> Tuple[str, ...]:
|
def getargs(self, var: bool = False) -> Tuple[str, ...]:
|
||||||
""" return a tuple with the argument names for the code object
|
""" return a tuple with the argument names for the code object
|
||||||
|
@ -132,10 +131,8 @@ class Frame:
|
||||||
@property
|
@property
|
||||||
def statement(self) -> "Source":
|
def statement(self) -> "Source":
|
||||||
""" statement this frame is at """
|
""" statement this frame is at """
|
||||||
import _pytest._code
|
|
||||||
|
|
||||||
if self.code.fullsource is None:
|
if self.code.fullsource is None:
|
||||||
return _pytest._code.Source("")
|
return Source("")
|
||||||
return self.code.fullsource.getstatement(self.lineno)
|
return self.code.fullsource.getstatement(self.lineno)
|
||||||
|
|
||||||
def eval(self, code, **vars):
|
def eval(self, code, **vars):
|
||||||
|
@ -231,8 +228,6 @@ class TracebackEntry:
|
||||||
""" return failing source code. """
|
""" return failing source code. """
|
||||||
# we use the passed in astcache to not reparse asttrees
|
# we use the passed in astcache to not reparse asttrees
|
||||||
# within exception info printing
|
# within exception info printing
|
||||||
from _pytest._code.source import getstatementrange_ast
|
|
||||||
|
|
||||||
source = self.frame.code.fullsource
|
source = self.frame.code.fullsource
|
||||||
if source is None:
|
if source is None:
|
||||||
return None
|
return None
|
||||||
|
@ -703,11 +698,9 @@ class FormattedExcinfo:
|
||||||
short: bool = False,
|
short: bool = False,
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
""" return formatted and marked up source lines. """
|
""" return formatted and marked up source lines. """
|
||||||
import _pytest._code
|
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
if source is None or line_index >= len(source.lines):
|
if source is None or line_index >= len(source.lines):
|
||||||
source = _pytest._code.Source("???")
|
source = Source("???")
|
||||||
line_index = 0
|
line_index = 0
|
||||||
if line_index < 0:
|
if line_index < 0:
|
||||||
line_index += len(source)
|
line_index += len(source)
|
||||||
|
@ -769,11 +762,9 @@ class FormattedExcinfo:
|
||||||
def repr_traceback_entry(
|
def repr_traceback_entry(
|
||||||
self, entry: TracebackEntry, excinfo: Optional[ExceptionInfo] = None
|
self, entry: TracebackEntry, excinfo: Optional[ExceptionInfo] = None
|
||||||
) -> "ReprEntry":
|
) -> "ReprEntry":
|
||||||
import _pytest._code
|
|
||||||
|
|
||||||
source = self._getentrysource(entry)
|
source = self._getentrysource(entry)
|
||||||
if source is None:
|
if source is None:
|
||||||
source = _pytest._code.Source("???")
|
source = Source("???")
|
||||||
line_index = 0
|
line_index = 0
|
||||||
else:
|
else:
|
||||||
line_index = entry.lineno - entry.getfirstlinesource()
|
line_index = entry.lineno - entry.getfirstlinesource()
|
||||||
|
@ -1150,19 +1141,37 @@ class ReprFuncArgs(TerminalRepr):
|
||||||
tw.line("")
|
tw.line("")
|
||||||
|
|
||||||
|
|
||||||
def getrawcode(obj, trycall: bool = True):
|
def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
|
||||||
""" return code object for given function. """
|
""" Return source location (path, lineno) for the given object.
|
||||||
|
If the source cannot be determined return ("", -1).
|
||||||
|
|
||||||
|
The line number is 0-based.
|
||||||
|
"""
|
||||||
|
# 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:
|
try:
|
||||||
return obj.__code__
|
code = Code(obj)
|
||||||
except AttributeError:
|
except TypeError:
|
||||||
obj = getattr(obj, "f_code", obj)
|
try:
|
||||||
obj = getattr(obj, "__code__", obj)
|
fn = inspect.getsourcefile(obj) or inspect.getfile(obj)
|
||||||
if trycall and not hasattr(obj, "co_firstlineno"):
|
except TypeError:
|
||||||
if hasattr(obj, "__call__") and not inspect.isclass(obj):
|
return "", -1
|
||||||
x = getrawcode(obj.__call__, trycall=False)
|
|
||||||
if hasattr(x, "co_firstlineno"):
|
fspath = fn and py.path.local(fn) or ""
|
||||||
return x
|
lineno = -1
|
||||||
return obj
|
if fspath:
|
||||||
|
try:
|
||||||
|
_, lineno = findsource(obj)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return fspath, lineno
|
||||||
|
else:
|
||||||
|
return code.path, code.firstlineno
|
||||||
|
|
||||||
|
|
||||||
# relative paths that we use to filter traceback entries from appearing to the user;
|
# relative paths that we use to filter traceback entries from appearing to the user;
|
||||||
|
|
|
@ -8,7 +8,6 @@ import warnings
|
||||||
from bisect import bisect_right
|
from bisect import bisect_right
|
||||||
from types import CodeType
|
from types import CodeType
|
||||||
from types import FrameType
|
from types import FrameType
|
||||||
from typing import Any
|
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
@ -18,7 +17,6 @@ from typing import Union
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
from _pytest.compat import get_real_func
|
|
||||||
from _pytest.compat import overload
|
from _pytest.compat import overload
|
||||||
from _pytest.compat import TYPE_CHECKING
|
from _pytest.compat import TYPE_CHECKING
|
||||||
|
|
||||||
|
@ -279,41 +277,6 @@ def compile_( # noqa: F811
|
||||||
return s.compile(filename, mode, flags, _genframe=_genframe)
|
return s.compile(filename, mode, flags, _genframe=_genframe)
|
||||||
|
|
||||||
|
|
||||||
def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
|
|
||||||
""" 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:
|
|
||||||
try:
|
|
||||||
fn = inspect.getsourcefile(obj) or inspect.getfile(obj)
|
|
||||||
except TypeError:
|
|
||||||
return "", -1
|
|
||||||
|
|
||||||
fspath = fn and py.path.local(fn) or ""
|
|
||||||
lineno = -1
|
|
||||||
if fspath:
|
|
||||||
try:
|
|
||||||
_, lineno = findsource(obj)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
return fspath, lineno
|
|
||||||
else:
|
|
||||||
return code.path, code.firstlineno
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# helper functions
|
# helper functions
|
||||||
#
|
#
|
||||||
|
@ -329,9 +292,22 @@ def findsource(obj) -> Tuple[Optional[Source], int]:
|
||||||
return source, lineno
|
return source, lineno
|
||||||
|
|
||||||
|
|
||||||
def getsource(obj, **kwargs) -> Source:
|
def getrawcode(obj, trycall: bool = True):
|
||||||
from .code import getrawcode
|
""" return code object for given function. """
|
||||||
|
try:
|
||||||
|
return obj.__code__
|
||||||
|
except AttributeError:
|
||||||
|
obj = getattr(obj, "f_code", obj)
|
||||||
|
obj = getattr(obj, "__code__", obj)
|
||||||
|
if trycall and not hasattr(obj, "co_firstlineno"):
|
||||||
|
if hasattr(obj, "__call__") and not inspect.isclass(obj):
|
||||||
|
x = getrawcode(obj.__call__, trycall=False)
|
||||||
|
if hasattr(x, "co_firstlineno"):
|
||||||
|
return x
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def getsource(obj, **kwargs) -> Source:
|
||||||
obj = getrawcode(obj)
|
obj = getrawcode(obj)
|
||||||
try:
|
try:
|
||||||
strsrc = inspect.getsource(obj)
|
strsrc = inspect.getsource(obj)
|
||||||
|
@ -346,8 +322,6 @@ def deindent(lines: Sequence[str]) -> List[str]:
|
||||||
|
|
||||||
|
|
||||||
def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[int]]:
|
def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[int]]:
|
||||||
import ast
|
|
||||||
|
|
||||||
# flatten all statements and except handlers into one lineno-list
|
# flatten all statements and except handlers into one lineno-list
|
||||||
# AST's line numbers start indexing at 1
|
# AST's line numbers start indexing at 1
|
||||||
values = [] # type: List[int]
|
values = [] # type: List[int]
|
||||||
|
|
|
@ -12,9 +12,9 @@ import attr
|
||||||
import py
|
import py
|
||||||
|
|
||||||
import _pytest
|
import _pytest
|
||||||
|
from _pytest._code import getfslineno
|
||||||
from _pytest._code.code import FormattedExcinfo
|
from _pytest._code.code import FormattedExcinfo
|
||||||
from _pytest._code.code import TerminalRepr
|
from _pytest._code.code import TerminalRepr
|
||||||
from _pytest._code.source import getfslineno
|
|
||||||
from _pytest._io import TerminalWriter
|
from _pytest._io import TerminalWriter
|
||||||
from _pytest.compat import _format_args
|
from _pytest.compat import _format_args
|
||||||
from _pytest.compat import _PytestWrapper
|
from _pytest.compat import _PytestWrapper
|
||||||
|
|
|
@ -14,7 +14,7 @@ from typing import Union
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
|
||||||
from .._code.source import getfslineno
|
from .._code import getfslineno
|
||||||
from ..compat import ascii_escaped
|
from ..compat import ascii_escaped
|
||||||
from ..compat import NOTSET
|
from ..compat import NOTSET
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
|
|
|
@ -12,10 +12,10 @@ from typing import Union
|
||||||
import py
|
import py
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
|
from _pytest._code import getfslineno
|
||||||
from _pytest._code.code import ExceptionChainRepr
|
from _pytest._code.code import ExceptionChainRepr
|
||||||
from _pytest._code.code import ExceptionInfo
|
from _pytest._code.code import ExceptionInfo
|
||||||
from _pytest._code.code import ReprExceptionInfo
|
from _pytest._code.code import ReprExceptionInfo
|
||||||
from _pytest._code.source import getfslineno
|
|
||||||
from _pytest.compat import cached_property
|
from _pytest.compat import cached_property
|
||||||
from _pytest.compat import TYPE_CHECKING
|
from _pytest.compat import TYPE_CHECKING
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
|
|
|
@ -25,8 +25,8 @@ import _pytest
|
||||||
from _pytest import fixtures
|
from _pytest import fixtures
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
from _pytest._code import filter_traceback
|
from _pytest._code import filter_traceback
|
||||||
|
from _pytest._code import getfslineno
|
||||||
from _pytest._code.code import ExceptionInfo
|
from _pytest._code.code import ExceptionInfo
|
||||||
from _pytest._code.source import getfslineno
|
|
||||||
from _pytest._io import TerminalWriter
|
from _pytest._io import TerminalWriter
|
||||||
from _pytest._io.saferepr import saferepr
|
from _pytest._io.saferepr import saferepr
|
||||||
from _pytest.compat import ascii_escaped
|
from _pytest.compat import ascii_escaped
|
||||||
|
|
Loading…
Reference in New Issue