code/code: type annotations & doc cleanups
This commit is contained in:
parent
087b047426
commit
77f3cb4baa
|
@ -51,7 +51,7 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
class Code:
|
class Code:
|
||||||
""" wrapper around Python code objects """
|
"""Wrapper around Python code objects."""
|
||||||
|
|
||||||
def __init__(self, rawcode) -> None:
|
def __init__(self, rawcode) -> None:
|
||||||
if not hasattr(rawcode, "co_filename"):
|
if not hasattr(rawcode, "co_filename"):
|
||||||
|
@ -74,7 +74,7 @@ class Code:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self) -> Union[py.path.local, str]:
|
def path(self) -> Union[py.path.local, str]:
|
||||||
""" return a path object pointing to source code (or a str in case
|
"""Return a path object pointing to source code (or a str in case
|
||||||
of OSError / non-existing file).
|
of OSError / non-existing file).
|
||||||
"""
|
"""
|
||||||
if not self.raw.co_filename:
|
if not self.raw.co_filename:
|
||||||
|
@ -92,24 +92,22 @@ class Code:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
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."""
|
||||||
"""
|
|
||||||
full, _ = findsource(self.raw)
|
full, _ = 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
|
||||||
return Source(self.raw)
|
return 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.
|
||||||
|
|
||||||
if 'var' is set True also return the names of the variable and
|
If 'var' is set True also return the names of the variable and
|
||||||
keyword arguments when present
|
keyword arguments when present.
|
||||||
"""
|
"""
|
||||||
# handfull shortcut for getting args
|
# Handy shortcut for getting args.
|
||||||
raw = self.raw
|
raw = self.raw
|
||||||
argcount = raw.co_argcount
|
argcount = raw.co_argcount
|
||||||
if var:
|
if var:
|
||||||
|
@ -131,44 +129,43 @@ class Frame:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def statement(self) -> "Source":
|
def statement(self) -> "Source":
|
||||||
""" statement this frame is at """
|
"""Statement this frame is at."""
|
||||||
if self.code.fullsource is None:
|
if self.code.fullsource is None:
|
||||||
return 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):
|
||||||
""" evaluate 'code' in the frame
|
"""Evaluate 'code' in the frame.
|
||||||
|
|
||||||
'vars' are optional additional local variables
|
'vars' are optional additional local variables.
|
||||||
|
|
||||||
returns the result of the evaluation
|
Returns the result of the evaluation.
|
||||||
"""
|
"""
|
||||||
f_locals = self.f_locals.copy()
|
f_locals = self.f_locals.copy()
|
||||||
f_locals.update(vars)
|
f_locals.update(vars)
|
||||||
return eval(code, self.f_globals, f_locals)
|
return eval(code, self.f_globals, f_locals)
|
||||||
|
|
||||||
def exec_(self, code, **vars) -> None:
|
def exec_(self, code, **vars) -> None:
|
||||||
""" exec 'code' in the frame
|
"""Exec 'code' in the frame.
|
||||||
|
|
||||||
'vars' are optional; additional local variables
|
'vars' are optional; additional local variables.
|
||||||
"""
|
"""
|
||||||
f_locals = self.f_locals.copy()
|
f_locals = self.f_locals.copy()
|
||||||
f_locals.update(vars)
|
f_locals.update(vars)
|
||||||
exec(code, self.f_globals, f_locals)
|
exec(code, self.f_globals, f_locals)
|
||||||
|
|
||||||
def repr(self, object: object) -> str:
|
def repr(self, object: object) -> str:
|
||||||
""" return a 'safe' (non-recursive, one-line) string repr for 'object'
|
"""Return a 'safe' (non-recursive, one-line) string repr for 'object'."""
|
||||||
"""
|
|
||||||
return saferepr(object)
|
return saferepr(object)
|
||||||
|
|
||||||
def is_true(self, object):
|
def is_true(self, object):
|
||||||
return object
|
return object
|
||||||
|
|
||||||
def getargs(self, var: bool = False):
|
def getargs(self, var: bool = False):
|
||||||
""" return a list of tuples (name, value) for all arguments
|
"""Return a list of tuples (name, value) for all arguments.
|
||||||
|
|
||||||
if 'var' is set True also include the variable and keyword
|
If 'var' is set True, also include the variable and keyword arguments
|
||||||
arguments when present
|
when present.
|
||||||
"""
|
"""
|
||||||
retval = []
|
retval = []
|
||||||
for arg in self.code.getargs(var):
|
for arg in self.code.getargs(var):
|
||||||
|
@ -180,12 +177,16 @@ class Frame:
|
||||||
|
|
||||||
|
|
||||||
class TracebackEntry:
|
class TracebackEntry:
|
||||||
""" a single entry in a traceback """
|
"""A single entry in a Traceback."""
|
||||||
|
|
||||||
_repr_style = None # type: Optional[Literal["short", "long"]]
|
_repr_style = None # type: Optional[Literal["short", "long"]]
|
||||||
exprinfo = None
|
exprinfo = None
|
||||||
|
|
||||||
def __init__(self, rawentry: TracebackType, excinfo=None) -> None:
|
def __init__(
|
||||||
|
self,
|
||||||
|
rawentry: TracebackType,
|
||||||
|
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
|
||||||
|
) -> None:
|
||||||
self._excinfo = excinfo
|
self._excinfo = excinfo
|
||||||
self._rawentry = rawentry
|
self._rawentry = rawentry
|
||||||
self.lineno = rawentry.tb_lineno - 1
|
self.lineno = rawentry.tb_lineno - 1
|
||||||
|
@ -207,26 +208,26 @@ class TracebackEntry:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def statement(self) -> "Source":
|
def statement(self) -> "Source":
|
||||||
""" _pytest._code.Source object for the current statement """
|
"""_pytest._code.Source object for the current statement."""
|
||||||
source = self.frame.code.fullsource
|
source = self.frame.code.fullsource
|
||||||
assert source is not None
|
assert source is not None
|
||||||
return source.getstatement(self.lineno)
|
return source.getstatement(self.lineno)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self) -> Union[py.path.local, str]:
|
def path(self) -> Union[py.path.local, str]:
|
||||||
""" path to the source code """
|
"""Path to the source code."""
|
||||||
return self.frame.code.path
|
return self.frame.code.path
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def locals(self) -> Dict[str, Any]:
|
def locals(self) -> Dict[str, Any]:
|
||||||
""" locals of underlying frame """
|
"""Locals of underlying frame."""
|
||||||
return self.frame.f_locals
|
return self.frame.f_locals
|
||||||
|
|
||||||
def getfirstlinesource(self) -> int:
|
def getfirstlinesource(self) -> int:
|
||||||
return self.frame.code.firstlineno
|
return self.frame.code.firstlineno
|
||||||
|
|
||||||
def getsource(self, astcache=None) -> Optional["Source"]:
|
def getsource(self, astcache=None) -> Optional["Source"]:
|
||||||
""" 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
|
||||||
source = self.frame.code.fullsource
|
source = self.frame.code.fullsource
|
||||||
|
@ -251,19 +252,19 @@ class TracebackEntry:
|
||||||
|
|
||||||
source = property(getsource)
|
source = property(getsource)
|
||||||
|
|
||||||
def ishidden(self):
|
def ishidden(self) -> bool:
|
||||||
""" return True if the current frame has a var __tracebackhide__
|
"""Return True if the current frame has a var __tracebackhide__
|
||||||
resolving to True.
|
resolving to True.
|
||||||
|
|
||||||
If __tracebackhide__ is a callable, it gets called with the
|
If __tracebackhide__ is a callable, it gets called with the
|
||||||
ExceptionInfo instance and can decide whether to hide the traceback.
|
ExceptionInfo instance and can decide whether to hide the traceback.
|
||||||
|
|
||||||
mostly for internal use
|
Mostly for internal use.
|
||||||
"""
|
"""
|
||||||
f = self.frame
|
f = self.frame
|
||||||
tbh = f.f_locals.get(
|
tbh = f.f_locals.get(
|
||||||
"__tracebackhide__", f.f_globals.get("__tracebackhide__", False)
|
"__tracebackhide__", f.f_globals.get("__tracebackhide__", False)
|
||||||
)
|
) # type: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]]
|
||||||
if tbh and callable(tbh):
|
if tbh and callable(tbh):
|
||||||
return tbh(None if self._excinfo is None else self._excinfo())
|
return tbh(None if self._excinfo is None else self._excinfo())
|
||||||
return tbh
|
return tbh
|
||||||
|
@ -280,21 +281,19 @@ class TracebackEntry:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
""" co_name of underlying code """
|
"""co_name of underlying code."""
|
||||||
return self.frame.code.raw.co_name
|
return self.frame.code.raw.co_name
|
||||||
|
|
||||||
|
|
||||||
class Traceback(List[TracebackEntry]):
|
class Traceback(List[TracebackEntry]):
|
||||||
""" Traceback objects encapsulate and offer higher level
|
"""Traceback objects encapsulate and offer higher level access to Traceback entries."""
|
||||||
access to Traceback entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
tb: Union[TracebackType, Iterable[TracebackEntry]],
|
tb: Union[TracebackType, Iterable[TracebackEntry]],
|
||||||
excinfo: Optional["ReferenceType[ExceptionInfo]"] = None,
|
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
""" initialize from given python traceback object and ExceptionInfo """
|
"""Initialize from given python traceback object and ExceptionInfo."""
|
||||||
self._excinfo = excinfo
|
self._excinfo = excinfo
|
||||||
if isinstance(tb, TracebackType):
|
if isinstance(tb, TracebackType):
|
||||||
|
|
||||||
|
@ -313,16 +312,16 @@ class Traceback(List[TracebackEntry]):
|
||||||
path=None,
|
path=None,
|
||||||
lineno: Optional[int] = None,
|
lineno: Optional[int] = None,
|
||||||
firstlineno: Optional[int] = None,
|
firstlineno: Optional[int] = None,
|
||||||
excludepath=None,
|
excludepath: Optional[py.path.local] = None,
|
||||||
) -> "Traceback":
|
) -> "Traceback":
|
||||||
""" return a Traceback instance wrapping part of this Traceback
|
"""Return a Traceback instance wrapping part of this Traceback.
|
||||||
|
|
||||||
by providing any combination of path, lineno and firstlineno, the
|
By providing any combination of path, lineno and firstlineno, the
|
||||||
first frame to start the to-be-returned traceback is determined
|
first frame to start the to-be-returned traceback is determined.
|
||||||
|
|
||||||
this allows cutting the first part of a Traceback instance e.g.
|
This allows cutting the first part of a Traceback instance e.g.
|
||||||
for formatting reasons (removing some uninteresting bits that deal
|
for formatting reasons (removing some uninteresting bits that deal
|
||||||
with handling of the exception/traceback)
|
with handling of the exception/traceback).
|
||||||
"""
|
"""
|
||||||
for x in self:
|
for x in self:
|
||||||
code = x.frame.code
|
code = x.frame.code
|
||||||
|
@ -359,21 +358,19 @@ class Traceback(List[TracebackEntry]):
|
||||||
def filter(
|
def filter(
|
||||||
self, fn: Callable[[TracebackEntry], bool] = lambda x: not x.ishidden()
|
self, fn: Callable[[TracebackEntry], bool] = lambda x: not x.ishidden()
|
||||||
) -> "Traceback":
|
) -> "Traceback":
|
||||||
""" return a Traceback instance with certain items removed
|
"""Return a Traceback instance with certain items removed
|
||||||
|
|
||||||
fn is a function that gets a single argument, a TracebackEntry
|
fn is a function that gets a single argument, a TracebackEntry
|
||||||
instance, and should return True when the item should be added
|
instance, and should return True when the item should be added
|
||||||
to the Traceback, False when not
|
to the Traceback, False when not.
|
||||||
|
|
||||||
by default this removes all the TracebackEntries which are hidden
|
By default this removes all the TracebackEntries which are hidden
|
||||||
(see ishidden() above)
|
(see ishidden() above).
|
||||||
"""
|
"""
|
||||||
return Traceback(filter(fn, self), self._excinfo)
|
return Traceback(filter(fn, self), self._excinfo)
|
||||||
|
|
||||||
def getcrashentry(self) -> TracebackEntry:
|
def getcrashentry(self) -> TracebackEntry:
|
||||||
""" return last non-hidden traceback entry that lead
|
"""Return last non-hidden traceback entry that lead to the exception of a traceback."""
|
||||||
to the exception of a traceback.
|
|
||||||
"""
|
|
||||||
for i in range(-1, -len(self) - 1, -1):
|
for i in range(-1, -len(self) - 1, -1):
|
||||||
entry = self[i]
|
entry = self[i]
|
||||||
if not entry.ishidden():
|
if not entry.ishidden():
|
||||||
|
@ -381,9 +378,8 @@ class Traceback(List[TracebackEntry]):
|
||||||
return self[-1]
|
return self[-1]
|
||||||
|
|
||||||
def recursionindex(self) -> Optional[int]:
|
def recursionindex(self) -> Optional[int]:
|
||||||
""" return the index of the frame/TracebackEntry where recursion
|
"""Return the index of the frame/TracebackEntry where recursion originates if
|
||||||
originates if appropriate, None if no recursion occurred
|
appropriate, None if no recursion occurred."""
|
||||||
"""
|
|
||||||
cache = {} # type: Dict[Tuple[Any, int, int], List[Dict[str, Any]]]
|
cache = {} # type: Dict[Tuple[Any, int, int], List[Dict[str, Any]]]
|
||||||
for i, entry in enumerate(self):
|
for i, entry in enumerate(self):
|
||||||
# id for the code.raw is needed to work around
|
# id for the code.raw is needed to work around
|
||||||
|
@ -414,14 +410,12 @@ co_equal = compile(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
_E = TypeVar("_E", bound=BaseException)
|
_E = TypeVar("_E", bound=BaseException, covariant=True)
|
||||||
|
|
||||||
|
|
||||||
@attr.s(repr=False)
|
@attr.s(repr=False)
|
||||||
class ExceptionInfo(Generic[_E]):
|
class ExceptionInfo(Generic[_E]):
|
||||||
""" wraps sys.exc_info() objects and offers
|
"""Wraps sys.exc_info() objects and offers help for navigating the traceback."""
|
||||||
help for navigating the traceback.
|
|
||||||
"""
|
|
||||||
|
|
||||||
_assert_start_repr = "AssertionError('assert "
|
_assert_start_repr = "AssertionError('assert "
|
||||||
|
|
||||||
|
@ -435,13 +429,12 @@ class ExceptionInfo(Generic[_E]):
|
||||||
exc_info: Tuple["Type[_E]", "_E", TracebackType],
|
exc_info: Tuple["Type[_E]", "_E", TracebackType],
|
||||||
exprinfo: Optional[str] = None,
|
exprinfo: Optional[str] = None,
|
||||||
) -> "ExceptionInfo[_E]":
|
) -> "ExceptionInfo[_E]":
|
||||||
"""returns an ExceptionInfo for an existing exc_info tuple.
|
"""Returns an ExceptionInfo for an existing exc_info tuple.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Experimental API
|
Experimental API
|
||||||
|
|
||||||
|
|
||||||
:param exprinfo: a text string helping to determine if we should
|
:param exprinfo: a text string helping to determine if we should
|
||||||
strip ``AssertionError`` from the output, defaults
|
strip ``AssertionError`` from the output, defaults
|
||||||
to the exception message/``__str__()``
|
to the exception message/``__str__()``
|
||||||
|
@ -460,13 +453,12 @@ class ExceptionInfo(Generic[_E]):
|
||||||
def from_current(
|
def from_current(
|
||||||
cls, exprinfo: Optional[str] = None
|
cls, exprinfo: Optional[str] = None
|
||||||
) -> "ExceptionInfo[BaseException]":
|
) -> "ExceptionInfo[BaseException]":
|
||||||
"""returns an ExceptionInfo matching the current traceback
|
"""Returns an ExceptionInfo matching the current traceback.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Experimental API
|
Experimental API
|
||||||
|
|
||||||
|
|
||||||
:param exprinfo: a text string helping to determine if we should
|
:param exprinfo: a text string helping to determine if we should
|
||||||
strip ``AssertionError`` from the output, defaults
|
strip ``AssertionError`` from the output, defaults
|
||||||
to the exception message/``__str__()``
|
to the exception message/``__str__()``
|
||||||
|
@ -480,8 +472,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def for_later(cls) -> "ExceptionInfo[_E]":
|
def for_later(cls) -> "ExceptionInfo[_E]":
|
||||||
"""return an unfilled ExceptionInfo
|
"""Return an unfilled ExceptionInfo."""
|
||||||
"""
|
|
||||||
return cls(None)
|
return cls(None)
|
||||||
|
|
||||||
def fill_unfilled(self, exc_info: Tuple["Type[_E]", _E, TracebackType]) -> None:
|
def fill_unfilled(self, exc_info: Tuple["Type[_E]", _E, TracebackType]) -> None:
|
||||||
|
@ -491,7 +482,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self) -> "Type[_E]":
|
def type(self) -> "Type[_E]":
|
||||||
"""the exception class"""
|
"""The exception class."""
|
||||||
assert (
|
assert (
|
||||||
self._excinfo is not None
|
self._excinfo is not None
|
||||||
), ".type can only be used after the context manager exits"
|
), ".type can only be used after the context manager exits"
|
||||||
|
@ -499,7 +490,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> _E:
|
def value(self) -> _E:
|
||||||
"""the exception value"""
|
"""The exception value."""
|
||||||
assert (
|
assert (
|
||||||
self._excinfo is not None
|
self._excinfo is not None
|
||||||
), ".value can only be used after the context manager exits"
|
), ".value can only be used after the context manager exits"
|
||||||
|
@ -507,7 +498,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tb(self) -> TracebackType:
|
def tb(self) -> TracebackType:
|
||||||
"""the exception raw traceback"""
|
"""The exception raw traceback."""
|
||||||
assert (
|
assert (
|
||||||
self._excinfo is not None
|
self._excinfo is not None
|
||||||
), ".tb can only be used after the context manager exits"
|
), ".tb can only be used after the context manager exits"
|
||||||
|
@ -515,7 +506,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def typename(self) -> str:
|
def typename(self) -> str:
|
||||||
"""the type name of the exception"""
|
"""The type name of the exception."""
|
||||||
assert (
|
assert (
|
||||||
self._excinfo is not None
|
self._excinfo is not None
|
||||||
), ".typename can only be used after the context manager exits"
|
), ".typename can only be used after the context manager exits"
|
||||||
|
@ -523,7 +514,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def traceback(self) -> Traceback:
|
def traceback(self) -> Traceback:
|
||||||
"""the traceback"""
|
"""The traceback."""
|
||||||
if self._traceback is None:
|
if self._traceback is None:
|
||||||
self._traceback = Traceback(self.tb, excinfo=ref(self))
|
self._traceback = Traceback(self.tb, excinfo=ref(self))
|
||||||
return self._traceback
|
return self._traceback
|
||||||
|
@ -540,12 +531,12 @@ class ExceptionInfo(Generic[_E]):
|
||||||
)
|
)
|
||||||
|
|
||||||
def exconly(self, tryshort: bool = False) -> str:
|
def exconly(self, tryshort: bool = False) -> str:
|
||||||
""" return the exception as a string
|
"""Return the exception as a string.
|
||||||
|
|
||||||
when 'tryshort' resolves to True, and the exception is a
|
When 'tryshort' resolves to True, and the exception is a
|
||||||
_pytest._code._AssertionError, only the actual exception part of
|
_pytest._code._AssertionError, only the actual exception part of
|
||||||
the exception representation is returned (so 'AssertionError: ' is
|
the exception representation is returned (so 'AssertionError: ' is
|
||||||
removed from the beginning)
|
removed from the beginning).
|
||||||
"""
|
"""
|
||||||
lines = format_exception_only(self.type, self.value)
|
lines = format_exception_only(self.type, self.value)
|
||||||
text = "".join(lines)
|
text = "".join(lines)
|
||||||
|
@ -580,8 +571,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
truncate_locals: bool = True,
|
truncate_locals: bool = True,
|
||||||
chain: bool = True,
|
chain: bool = True,
|
||||||
) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]:
|
) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]:
|
||||||
"""
|
"""Return str()able representation of this exception info.
|
||||||
Return str()able representation of this exception info.
|
|
||||||
|
|
||||||
:param bool showlocals:
|
:param bool showlocals:
|
||||||
Show locals per traceback entry.
|
Show locals per traceback entry.
|
||||||
|
@ -630,11 +620,10 @@ class ExceptionInfo(Generic[_E]):
|
||||||
return fmt.repr_excinfo(self)
|
return fmt.repr_excinfo(self)
|
||||||
|
|
||||||
def match(self, regexp: "Union[str, Pattern]") -> "Literal[True]":
|
def match(self, regexp: "Union[str, Pattern]") -> "Literal[True]":
|
||||||
"""
|
"""Check whether the regular expression `regexp` matches the string
|
||||||
Check whether the regular expression `regexp` matches the string
|
|
||||||
representation of the exception using :func:`python:re.search`.
|
representation of the exception using :func:`python:re.search`.
|
||||||
If it matches `True` is returned.
|
|
||||||
If it doesn't match an `AssertionError` is raised.
|
If it matches `True` is returned, otherwise an `AssertionError` is raised.
|
||||||
"""
|
"""
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
assert re.search(
|
assert re.search(
|
||||||
|
@ -646,7 +635,7 @@ class ExceptionInfo(Generic[_E]):
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class FormattedExcinfo:
|
class FormattedExcinfo:
|
||||||
""" presenting information about failing Functions and Generators. """
|
"""Presenting information about failing Functions and Generators."""
|
||||||
|
|
||||||
# for traceback entries
|
# for traceback entries
|
||||||
flow_marker = ">"
|
flow_marker = ">"
|
||||||
|
@ -697,7 +686,7 @@ class FormattedExcinfo:
|
||||||
excinfo: Optional[ExceptionInfo] = None,
|
excinfo: Optional[ExceptionInfo] = None,
|
||||||
short: bool = False,
|
short: bool = False,
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
""" return formatted and marked up source lines. """
|
"""Return formatted and marked up source lines."""
|
||||||
lines = []
|
lines = []
|
||||||
if source is None or line_index >= len(source.lines):
|
if source is None or line_index >= len(source.lines):
|
||||||
source = Source("???")
|
source = Source("???")
|
||||||
|
@ -938,7 +927,7 @@ class ExceptionRepr(TerminalRepr):
|
||||||
reprcrash = None # type: Optional[ReprFileLocation]
|
reprcrash = None # type: Optional[ReprFileLocation]
|
||||||
reprtraceback = None # type: ReprTraceback
|
reprtraceback = None # type: ReprTraceback
|
||||||
|
|
||||||
def __attrs_post_init__(self):
|
def __attrs_post_init__(self) -> None:
|
||||||
self.sections = [] # type: List[Tuple[str, str, str]]
|
self.sections = [] # type: List[Tuple[str, str, str]]
|
||||||
|
|
||||||
def addsection(self, name: str, content: str, sep: str = "-") -> None:
|
def addsection(self, name: str, content: str, sep: str = "-") -> None:
|
||||||
|
@ -958,7 +947,7 @@ class ExceptionChainRepr(ExceptionRepr):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
def __attrs_post_init__(self):
|
def __attrs_post_init__(self) -> None:
|
||||||
super().__attrs_post_init__()
|
super().__attrs_post_init__()
|
||||||
# reprcrash and reprtraceback of the outermost (the newest) exception
|
# reprcrash and reprtraceback of the outermost (the newest) exception
|
||||||
# in the chain
|
# in the chain
|
||||||
|
@ -1160,8 +1149,9 @@ class ReprFuncArgs(TerminalRepr):
|
||||||
tw.line("")
|
tw.line("")
|
||||||
|
|
||||||
|
|
||||||
def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
|
def getfslineno(obj: object) -> Tuple[Union[str, py.path.local], int]:
|
||||||
""" Return source location (path, lineno) for the given object.
|
"""Return source location (path, lineno) for the given object.
|
||||||
|
|
||||||
If the source cannot be determined return ("", -1).
|
If the source cannot be determined return ("", -1).
|
||||||
|
|
||||||
The line number is 0-based.
|
The line number is 0-based.
|
||||||
|
@ -1171,13 +1161,13 @@ def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
|
||||||
# in 6ec13a2b9. It ("place_as") appears to be something very custom.
|
# in 6ec13a2b9. It ("place_as") appears to be something very custom.
|
||||||
obj = get_real_func(obj)
|
obj = get_real_func(obj)
|
||||||
if hasattr(obj, "place_as"):
|
if hasattr(obj, "place_as"):
|
||||||
obj = obj.place_as
|
obj = obj.place_as # type: ignore[attr-defined]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
code = Code(obj)
|
code = Code(obj)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
try:
|
try:
|
||||||
fn = inspect.getsourcefile(obj) or inspect.getfile(obj)
|
fn = inspect.getsourcefile(obj) or inspect.getfile(obj) # type: ignore[arg-type]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return "", -1
|
return "", -1
|
||||||
|
|
||||||
|
@ -1189,8 +1179,8 @@ def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
return fspath, lineno
|
return fspath, lineno
|
||||||
else:
|
|
||||||
return code.path, code.firstlineno
|
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;
|
||||||
|
|
Loading…
Reference in New Issue