aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/pytest/py3/_pytest/_code/source.py
diff options
context:
space:
mode:
authordeshevoy <deshevoy@yandex-team.ru>2022-02-10 16:46:56 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:56 +0300
commite988f30484abe5fdeedcc7a5d3c226c01a21800c (patch)
tree0a217b173aabb57b7e51f8a169989b1a3e0309fe /contrib/python/pytest/py3/_pytest/_code/source.py
parent33ee501c05d3f24036ae89766a858930ae66c548 (diff)
downloadydb-e988f30484abe5fdeedcc7a5d3c226c01a21800c.tar.gz
Restoring authorship annotation for <deshevoy@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/_code/source.py')
-rw-r--r--contrib/python/pytest/py3/_pytest/_code/source.py240
1 files changed, 120 insertions, 120 deletions
diff --git a/contrib/python/pytest/py3/_pytest/_code/source.py b/contrib/python/pytest/py3/_pytest/_code/source.py
index 6f54057c0a..56bf0fdc20 100644
--- a/contrib/python/pytest/py3/_pytest/_code/source.py
+++ b/contrib/python/pytest/py3/_pytest/_code/source.py
@@ -1,10 +1,10 @@
-import ast
-import inspect
-import textwrap
-import tokenize
+import ast
+import inspect
+import textwrap
+import tokenize
import types
-import warnings
-from bisect import bisect_right
+import warnings
+from bisect import bisect_right
from typing import Iterable
from typing import Iterator
from typing import List
@@ -12,14 +12,14 @@ from typing import Optional
from typing import overload
from typing import Tuple
from typing import Union
-
-
+
+
class Source:
"""An immutable object holding a source code fragment.
-
+
When using Source(...), the source lines are deindented.
- """
-
+ """
+
def __init__(self, obj: object = None) -> None:
if not obj:
self.lines: List[str] = []
@@ -36,15 +36,15 @@ class Source:
except TypeError:
src = inspect.getsource(obj) # type: ignore[arg-type]
self.lines = deindent(src.split("\n"))
-
+
def __eq__(self, other: object) -> bool:
if not isinstance(other, Source):
return NotImplemented
return self.lines == other.lines
-
+
# Ignore type because of https://github.com/python/mypy/issues/4266.
__hash__ = None # type: ignore
-
+
@overload
def __getitem__(self, key: int) -> str:
...
@@ -54,81 +54,81 @@ class Source:
...
def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]:
- if isinstance(key, int):
- return self.lines[key]
- else:
- if key.step not in (None, 1):
- raise IndexError("cannot slice a Source with a step")
- newsource = Source()
- newsource.lines = self.lines[key.start : key.stop]
- return newsource
-
+ if isinstance(key, int):
+ return self.lines[key]
+ else:
+ if key.step not in (None, 1):
+ raise IndexError("cannot slice a Source with a step")
+ newsource = Source()
+ newsource.lines = self.lines[key.start : key.stop]
+ return newsource
+
def __iter__(self) -> Iterator[str]:
return iter(self.lines)
def __len__(self) -> int:
- return len(self.lines)
-
+ return len(self.lines)
+
def strip(self) -> "Source":
"""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
- while end > start and not self.lines[end - 1].strip():
- end -= 1
- source = Source()
- source.lines[:] = self.lines[start:end]
- return source
-
+ start, end = 0, len(self)
+ while start < end and not self.lines[start].strip():
+ start += 1
+ while end > start and not self.lines[end - 1].strip():
+ end -= 1
+ source = Source()
+ source.lines[:] = self.lines[start:end]
+ 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."""
- newsource = Source()
- newsource.lines = [(indent + line) for line in self.lines]
- return newsource
-
+ 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)."""
- start, end = self.getstatementrange(lineno)
- return self[start:end]
-
+ 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."""
- if not (0 <= lineno < len(self)):
- raise IndexError("lineno out of range")
- ast, start, end = getstatementrange_ast(lineno, self)
- return start, end
-
+ 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."""
- newsource = Source()
- newsource.lines[:] = deindent(self.lines)
- return newsource
-
+ newsource = Source()
+ newsource.lines[:] = deindent(self.lines)
+ return newsource
+
def __str__(self) -> str:
- return "\n".join(self.lines)
-
-
-#
-# helper functions
-#
-
-
+ return "\n".join(self.lines)
+
+
+#
+# helper functions
+#
+
+
def findsource(obj) -> Tuple[Optional[Source], int]:
- try:
- sourcelines, lineno = inspect.findsource(obj)
+ try:
+ sourcelines, lineno = inspect.findsource(obj)
except Exception:
- return None, -1
- source = Source()
- source.lines = [line.rstrip() for line in sourcelines]
- return source, lineno
-
-
+ return None, -1
+ source = Source()
+ source.lines = [line.rstrip() for line in sourcelines]
+ return source, lineno
+
+
def getrawcode(obj: object, trycall: bool = True) -> types.CodeType:
"""Return code object for given function."""
- try:
+ try:
return obj.__code__ # type: ignore[attr-defined,no-any-return]
except AttributeError:
pass
@@ -137,76 +137,76 @@ def getrawcode(obj: object, trycall: bool = True) -> types.CodeType:
if call and not isinstance(obj, type):
return getrawcode(call, trycall=False)
raise TypeError(f"could not get code object for {obj!r}")
-
-
+
+
def deindent(lines: Iterable[str]) -> List[str]:
- return textwrap.dedent("\n".join(lines)).splitlines()
-
-
+ return textwrap.dedent("\n".join(lines)).splitlines()
+
+
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.
values: List[int] = []
- for x in ast.walk(node):
- if isinstance(x, (ast.stmt, ast.ExceptHandler)):
- values.append(x.lineno - 1)
- for name in ("finalbody", "orelse"):
+ for x in ast.walk(node):
+ if isinstance(x, (ast.stmt, ast.ExceptHandler)):
+ values.append(x.lineno - 1)
+ for name in ("finalbody", "orelse"):
val: Optional[List[ast.stmt]] = getattr(x, name, None)
- if val:
+ if val:
# Treat the finally/orelse part as its own statement.
- values.append(val[0].lineno - 1 - 1)
- values.sort()
- insert_index = bisect_right(values, lineno)
- start = values[insert_index - 1]
- if insert_index >= len(values):
- end = None
- else:
- end = values[insert_index]
- return start, end
-
-
+ values.append(val[0].lineno - 1 - 1)
+ values.sort()
+ insert_index = bisect_right(values, lineno)
+ start = values[insert_index - 1]
+ if insert_index >= len(values):
+ end = None
+ else:
+ end = values[insert_index]
+ return start, end
+
+
def getstatementrange_ast(
lineno: int,
source: Source,
assertion: bool = False,
astnode: Optional[ast.AST] = None,
) -> Tuple[ast.AST, int, int]:
- if astnode is None:
- content = str(source)
- # See #4260:
+ if astnode is None:
+ content = str(source)
+ # See #4260:
# Don't produce duplicate warnings when compiling source to find AST.
- with warnings.catch_warnings():
- warnings.simplefilter("ignore")
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
astnode = ast.parse(content, "source", "exec")
-
- start, end = get_statement_startend2(lineno, astnode)
+
+ start, end = get_statement_startend2(lineno, astnode)
# 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
- if end is None:
- end = len(source.lines)
-
- if end > start + 1:
+ # - ast-parsing strips comments
+ # - there might be empty lines
+ # - we might have lesser indented code blocks at the end
+ if end is None:
+ 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.
- block_finder = inspect.BlockFinder()
+ block_finder = inspect.BlockFinder()
# 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:
- for tok in tokenize.generate_tokens(lambda: next(it)):
- block_finder.tokeneater(*tok)
- except (inspect.EndOfBlock, IndentationError):
- end = block_finder.last + start
- except Exception:
- pass
-
+ block_finder.started = source.lines[start][0].isspace()
+ it = ((x + "\n") for x in source.lines[start:end])
+ try:
+ for tok in tokenize.generate_tokens(lambda: next(it)):
+ block_finder.tokeneater(*tok)
+ except (inspect.EndOfBlock, IndentationError):
+ end = block_finder.last + start
+ except Exception:
+ pass
+
# 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:
- end -= 1
- else:
- break
- return astnode, start, end
+ while end:
+ line = source.lines[end - 1].lstrip()
+ if line.startswith("#") or not line:
+ end -= 1
+ else:
+ break
+ return astnode, start, end