Format docstrings in a consistent style

This commit is contained in:
Ran Benita
2020-07-14 10:55:17 +03:00
parent 6882c0368b
commit 0242de4f56
55 changed files with 1589 additions and 1685 deletions

View File

@@ -71,9 +71,8 @@ class Code:
@property
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).
"""
"""Return a path object pointing to source code, or an ``str`` in
case of ``OSError`` / non-existing file."""
if not self.raw.co_filename:
return ""
try:
@@ -420,15 +419,16 @@ class ExceptionInfo(Generic[_E]):
exc_info: Tuple["Type[_E]", "_E", TracebackType],
exprinfo: Optional[str] = None,
) -> "ExceptionInfo[_E]":
"""Returns an ExceptionInfo for an existing exc_info tuple.
"""Return an ExceptionInfo for an existing exc_info tuple.
.. warning::
Experimental API
:param exprinfo: a text string helping to determine if we should
strip ``AssertionError`` from the output, defaults
to the exception message/``__str__()``
:param exprinfo:
A text string helping to determine if we should strip
``AssertionError`` from the output. Defaults to the exception
message/``__str__()``.
"""
_striptext = ""
if exprinfo is None and isinstance(exc_info[1], AssertionError):
@@ -444,15 +444,16 @@ class ExceptionInfo(Generic[_E]):
def from_current(
cls, exprinfo: Optional[str] = None
) -> "ExceptionInfo[BaseException]":
"""Returns an ExceptionInfo matching the current traceback.
"""Return an ExceptionInfo matching the current traceback.
.. warning::
Experimental API
:param exprinfo: a text string helping to determine if we should
strip ``AssertionError`` from the output, defaults
to the exception message/``__str__()``
:param exprinfo:
A text string helping to determine if we should strip
``AssertionError`` from the output. Defaults to the exception
message/``__str__()``.
"""
tup = sys.exc_info()
assert tup[0] is not None, "no current exception"
@@ -467,7 +468,7 @@ class ExceptionInfo(Generic[_E]):
return cls(None)
def fill_unfilled(self, exc_info: Tuple["Type[_E]", _E, TracebackType]) -> None:
"""fill an unfilled ExceptionInfo created with for_later()"""
"""Fill an unfilled ExceptionInfo created with ``for_later()``."""
assert self._excinfo is None, "ExceptionInfo was already filled"
self._excinfo = exc_info
@@ -568,7 +569,8 @@ class ExceptionInfo(Generic[_E]):
Show locals per traceback entry.
Ignored if ``style=="native"``.
:param str style: long|short|no|native|value traceback style
:param str style:
long|short|no|native|value traceback style.
:param bool abspath:
If paths should be changed to absolute or left unchanged.
@@ -583,7 +585,8 @@ class ExceptionInfo(Generic[_E]):
:param bool truncate_locals:
With ``showlocals==True``, make sure locals can be safely represented as strings.
:param bool chain: if chained exceptions in Python 3 should be shown.
:param bool chain:
If chained exceptions in Python 3 should be shown.
.. versionchanged:: 3.9
@@ -643,7 +646,7 @@ class FormattedExcinfo:
astcache = attr.ib(default=attr.Factory(dict), init=False, repr=False)
def _getindent(self, source: "Source") -> int:
# figure out indent for given source
# Figure out indent for the given source.
try:
s = str(source.getstatement(len(source) - 1))
except KeyboardInterrupt:
@@ -704,7 +707,7 @@ class FormattedExcinfo:
) -> List[str]:
lines = []
indentstr = " " * indent
# get the real exception information out
# Get the real exception information out.
exlines = excinfo.exconly(tryshort=True).split("\n")
failindent = self.fail_marker + indentstr[1:]
for line in exlines:
@@ -730,8 +733,7 @@ class FormattedExcinfo:
str_repr = saferepr(value)
else:
str_repr = safeformat(value)
# if len(str_repr) < 70 or not isinstance(value,
# (list, tuple, dict)):
# if len(str_repr) < 70 or not isinstance(value, (list, tuple, dict)):
lines.append("{:<10} = {}".format(name, str_repr))
# else:
# self._line("%-10s =\\" % (name,))
@@ -809,16 +811,17 @@ class FormattedExcinfo:
def _truncate_recursive_traceback(
self, traceback: Traceback
) -> Tuple[Traceback, Optional[str]]:
"""
Truncate the given recursive traceback trying to find the starting point
of the recursion.
"""Truncate the given recursive traceback trying to find the starting
point of the recursion.
The detection is done by going through each traceback entry and finding the
point in which the locals of the frame are equal to the locals of a previous frame (see ``recursionindex()``.
The detection is done by going through each traceback entry and
finding the point in which the locals of the frame are equal to the
locals of a previous frame (see ``recursionindex()``).
Handle the situation where the recursion process might raise an exception (for example
comparing numpy arrays using equality raises a TypeError), in which case we do our best to
warn the user of the error and show a limited traceback.
Handle the situation where the recursion process might raise an
exception (for example comparing numpy arrays using equality raises a
TypeError), in which case we do our best to warn the user of the
error and show a limited traceback.
"""
try:
recursionindex = traceback.recursionindex()
@@ -863,8 +866,8 @@ class FormattedExcinfo:
excinfo_._getreprcrash() if self.style != "value" else None
) # type: Optional[ReprFileLocation]
else:
# fallback to native repr if the exception doesn't have a traceback:
# ExceptionInfo objects require a full traceback to work
# Fallback to native repr if the exception doesn't have a traceback:
# ExceptionInfo objects require a full traceback to work.
reprtraceback = ReprTracebackNative(
traceback.format_exception(type(e), e, None)
)
@@ -915,7 +918,7 @@ class TerminalRepr:
# This class is abstract -- only subclasses are instantiated.
@attr.s(**{ATTRS_EQ_FIELD: False}) # type: ignore
class ExceptionRepr(TerminalRepr):
# Provided by in subclasses.
# Provided by subclasses.
reprcrash = None # type: Optional[ReprFileLocation]
reprtraceback = None # type: ReprTraceback
@@ -942,7 +945,7 @@ class ExceptionChainRepr(ExceptionRepr):
def __attrs_post_init__(self) -> None:
super().__attrs_post_init__()
# reprcrash and reprtraceback of the outermost (the newest) exception
# in the chain
# in the chain.
self.reprtraceback = self.chain[-1][0]
self.reprcrash = self.chain[-1][1]
@@ -974,7 +977,7 @@ class ReprTraceback(TerminalRepr):
entrysep = "_ "
def toterminal(self, tw: TerminalWriter) -> None:
# the entries might have different styles
# The entries might have different styles.
for i, entry in enumerate(self.reprentries):
if entry.style == "long":
tw.line("")
@@ -1017,7 +1020,7 @@ class ReprEntry(TerminalRepr):
style = attr.ib(type="_TracebackStyle")
def _write_entry_lines(self, tw: TerminalWriter) -> None:
"""Writes the source code portions of a list of traceback entries with syntax highlighting.
"""Write the source code portions of a list of traceback entries with syntax highlighting.
Usually entries are lines like these:
@@ -1099,8 +1102,8 @@ class ReprFileLocation(TerminalRepr):
message = attr.ib(type=str)
def toterminal(self, tw: TerminalWriter) -> None:
# filename and lineno output for each entry,
# using an output format that most editors understand
# Filename and lineno output for each entry, using an output format
# that most editors understand.
msg = self.message
i = msg.find("\n")
if i != -1:
@@ -1175,10 +1178,10 @@ def getfslineno(obj: object) -> Tuple[Union[str, py.path.local], int]:
return code.path, code.firstlineno
# relative paths that we use to filter traceback entries from appearing to the user;
# see filter_traceback
# Relative paths that we use to filter traceback entries from appearing to the user;
# see filter_traceback.
# note: if we need to add more paths than what we have now we should probably use a list
# for better maintenance
# for better maintenance.
_PLUGGY_DIR = py.path.local(pluggy.__file__.rstrip("oc"))
# pluggy is either a package or a single module depending on the version
@@ -1197,14 +1200,14 @@ def filter_traceback(entry: TracebackEntry) -> bool:
* internal traceback from pytest or its internal libraries, py and pluggy.
"""
# entry.path might sometimes return a str object when the entry
# points to dynamically generated code
# see https://bitbucket.org/pytest-dev/py/issues/71
# points to dynamically generated code.
# See https://bitbucket.org/pytest-dev/py/issues/71.
raw_filename = entry.frame.code.raw.co_filename
is_generated = "<" in raw_filename and ">" in raw_filename
if is_generated:
return False
# entry.path might point to a non-existing file, in which case it will
# also return a str object. see #1133
# also return a str object. See #1133.
p = py.path.local(entry.path)
return (
not p.relto(_PLUGGY_DIR) and not p.relto(_PYTEST_DIR) and not p.relto(_PY_DIR)

View File

@@ -67,9 +67,7 @@ class Source:
return len(self.lines)
def strip(self) -> "Source":
""" return new source object with trailing
and leading blank lines removed.
"""
"""Return new Source object with trailing and leading blank lines removed."""
start, end = 0, len(self)
while start < end and not self.lines[start].strip():
start += 1
@@ -80,31 +78,28 @@ class Source:
return source
def indent(self, indent: str = " " * 4) -> "Source":
""" return a copy of the source object with
all lines indented by the given indent-string.
"""
"""Return a copy of the source object with all lines indented by the
given indent-string."""
newsource = Source()
newsource.lines = [(indent + line) for line in self.lines]
return newsource
def getstatement(self, lineno: int) -> "Source":
""" return Source statement which contains the
given linenumber (counted from 0).
"""
"""Return Source statement which contains the given linenumber
(counted from 0)."""
start, end = self.getstatementrange(lineno)
return self[start:end]
def getstatementrange(self, lineno: int) -> Tuple[int, int]:
""" return (start, end) tuple which spans the minimal
statement region which containing the given lineno.
"""
"""Return (start, end) tuple which spans the minimal statement region
which containing the given lineno."""
if not (0 <= lineno < len(self)):
raise IndexError("lineno out of range")
ast, start, end = getstatementrange_ast(lineno, self)
return start, end
def deindent(self) -> "Source":
"""return a new source object deindented."""
"""Return a new Source object deindented."""
newsource = Source()
newsource.lines[:] = deindent(self.lines)
return newsource
@@ -129,7 +124,7 @@ def findsource(obj) -> Tuple[Optional[Source], int]:
def getrawcode(obj, trycall: bool = True):
""" return code object for given function. """
"""Return code object for given function."""
try:
return obj.__code__
except AttributeError:
@@ -148,8 +143,8 @@ def deindent(lines: Iterable[str]) -> List[str]:
def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[int]]:
# flatten all statements and except handlers into one lineno-list
# AST's line numbers start indexing at 1
# Flatten all statements and except handlers into one lineno-list.
# AST's line numbers start indexing at 1.
values = [] # type: List[int]
for x in ast.walk(node):
if isinstance(x, (ast.stmt, ast.ExceptHandler)):
@@ -157,7 +152,7 @@ def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[i
for name in ("finalbody", "orelse"):
val = getattr(x, name, None) # type: Optional[List[ast.stmt]]
if val:
# treat the finally/orelse part as its own statement
# Treat the finally/orelse part as its own statement.
values.append(val[0].lineno - 1 - 1)
values.sort()
insert_index = bisect_right(values, lineno)
@@ -178,13 +173,13 @@ def getstatementrange_ast(
if astnode is None:
content = str(source)
# See #4260:
# don't produce duplicate warnings when compiling source to find ast
# Don't produce duplicate warnings when compiling source to find AST.
with warnings.catch_warnings():
warnings.simplefilter("ignore")
astnode = ast.parse(content, "source", "exec")
start, end = get_statement_startend2(lineno, astnode)
# we need to correct the end:
# We need to correct the end:
# - ast-parsing strips comments
# - there might be empty lines
# - we might have lesser indented code blocks at the end
@@ -192,10 +187,10 @@ def getstatementrange_ast(
end = len(source.lines)
if end > start + 1:
# make sure we don't span differently indented code blocks
# by using the BlockFinder helper used which inspect.getsource() uses itself
# Make sure we don't span differently indented code blocks
# by using the BlockFinder helper used which inspect.getsource() uses itself.
block_finder = inspect.BlockFinder()
# if we start with an indented line, put blockfinder to "started" mode
# If we start with an indented line, put blockfinder to "started" mode.
block_finder.started = source.lines[start][0].isspace()
it = ((x + "\n") for x in source.lines[start:end])
try:
@@ -206,7 +201,7 @@ def getstatementrange_ast(
except Exception:
pass
# the end might still point to a comment or empty line, correct it
# The end might still point to a comment or empty line, correct it.
while end:
line = source.lines[end - 1].lstrip()
if line.startswith("#") or not line: