diff options
author | deshevoy <deshevoy@yandex-team.ru> | 2022-02-10 16:46:57 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:57 +0300 |
commit | 28148f76dbfcc644d96427d41c92f36cbf2fdc6e (patch) | |
tree | b83306b6e37edeea782e9eed673d89286c4fef35 /contrib/python/pytest/py3/_pytest/assertion/util.py | |
parent | e988f30484abe5fdeedcc7a5d3c226c01a21800c (diff) | |
download | ydb-28148f76dbfcc644d96427d41c92f36cbf2fdc6e.tar.gz |
Restoring authorship annotation for <deshevoy@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/assertion/util.py')
-rw-r--r-- | contrib/python/pytest/py3/_pytest/assertion/util.py | 344 |
1 files changed, 172 insertions, 172 deletions
diff --git a/contrib/python/pytest/py3/_pytest/assertion/util.py b/contrib/python/pytest/py3/_pytest/assertion/util.py index 0774d36fbc..da1ffd15e3 100644 --- a/contrib/python/pytest/py3/_pytest/assertion/util.py +++ b/contrib/python/pytest/py3/_pytest/assertion/util.py @@ -1,6 +1,6 @@ """Utilities for assertion debugging.""" import collections.abc -import pprint +import pprint from typing import AbstractSet from typing import Any from typing import Callable @@ -9,106 +9,106 @@ from typing import List from typing import Mapping from typing import Optional from typing import Sequence - -import _pytest._code + +import _pytest._code from _pytest import outcomes from _pytest._io.saferepr import _pformat_dispatch from _pytest._io.saferepr import safeformat from _pytest._io.saferepr import saferepr - -# The _reprcompare attribute on the util module is used by the new assertion -# interpretation code and assertion rewriter to detect this plugin was -# loaded and in turn call the hooks defined here as part of the -# DebugInterpreter. + +# The _reprcompare attribute on the util module is used by the new assertion +# interpretation code and assertion rewriter to detect this plugin was +# loaded and in turn call the hooks defined here as part of the +# DebugInterpreter. _reprcompare: Optional[Callable[[str, object, object], Optional[str]]] = None - + # Works similarly as _reprcompare attribute. Is populated with the hook call # when pytest_runtest_setup is called. _assertion_pass: Optional[Callable[[int, str, str], None]] = None - - + + def format_explanation(explanation: str) -> str: r"""Format an explanation. - - Normally all embedded newlines are escaped, however there are - three exceptions: \n{, \n} and \n~. The first two are intended - cover nested explanations, see function and attribute explanations - for examples (.visit_Call(), visit_Attribute()). The last one is - for when one explanation needs to span multiple lines, e.g. when - displaying diffs. - """ - lines = _split_explanation(explanation) - result = _format_lines(lines) + + Normally all embedded newlines are escaped, however there are + three exceptions: \n{, \n} and \n~. The first two are intended + cover nested explanations, see function and attribute explanations + for examples (.visit_Call(), visit_Attribute()). The last one is + for when one explanation needs to span multiple lines, e.g. when + displaying diffs. + """ + lines = _split_explanation(explanation) + result = _format_lines(lines) return "\n".join(result) - - + + def _split_explanation(explanation: str) -> List[str]: r"""Return a list of individual lines in the explanation. - - This will return a list of lines split on '\n{', '\n}' and '\n~'. - Any other newlines will be escaped and appear in the line as the - literal '\n' characters. - """ + + This will return a list of lines split on '\n{', '\n}' and '\n~'. + Any other newlines will be escaped and appear in the line as the + literal '\n' characters. + """ raw_lines = (explanation or "").split("\n") - lines = [raw_lines[0]] - for values in raw_lines[1:]: - if values and values[0] in ["{", "}", "~", ">"]: - lines.append(values) - else: - lines[-1] += "\\n" + values - return lines - - + lines = [raw_lines[0]] + for values in raw_lines[1:]: + if values and values[0] in ["{", "}", "~", ">"]: + lines.append(values) + else: + lines[-1] += "\\n" + values + return lines + + def _format_lines(lines: Sequence[str]) -> List[str]: """Format the individual lines. - + This will replace the '{', '}' and '~' characters of our mini formatting language with the proper 'where ...', 'and ...' and ' + ...' text, taking care of indentation along the way. - - Return a list of formatted lines. - """ + + Return a list of formatted lines. + """ result = list(lines[:1]) - stack = [0] - stackcnt = [0] - for line in lines[1:]: - if line.startswith("{"): - if stackcnt[-1]: + stack = [0] + stackcnt = [0] + for line in lines[1:]: + if line.startswith("{"): + if stackcnt[-1]: s = "and " - else: + else: s = "where " - stack.append(len(result)) - stackcnt[-1] += 1 - stackcnt.append(0) + stack.append(len(result)) + stackcnt[-1] += 1 + stackcnt.append(0) result.append(" +" + " " * (len(stack) - 1) + s + line[1:]) - elif line.startswith("}"): - stack.pop() - stackcnt.pop() - result[stack[-1]] += line[1:] - else: - assert line[0] in ["~", ">"] - stack[-1] += 1 - indent = len(stack) if line.startswith("~") else len(stack) - 1 + elif line.startswith("}"): + stack.pop() + stackcnt.pop() + result[stack[-1]] += line[1:] + else: + assert line[0] in ["~", ">"] + stack[-1] += 1 + indent = len(stack) if line.startswith("~") else len(stack) - 1 result.append(" " * indent + line[1:]) - assert len(stack) == 1 - return result - - + assert len(stack) == 1 + return result + + def issequence(x: Any) -> bool: return isinstance(x, collections.abc.Sequence) and not isinstance(x, str) - - + + def istext(x: Any) -> bool: return isinstance(x, str) - - + + def isdict(x: Any) -> bool: return isinstance(x, dict) - - + + def isset(x: Any) -> bool: return isinstance(x, (set, frozenset)) - + def isnamedtuple(obj: Any) -> bool: return isinstance(obj, tuple) and getattr(obj, "_fields", None) is not None @@ -147,29 +147,29 @@ def assertrepr_compare(config, op: str, left: Any, right: Any) -> Optional[List[ summary = f"{left_repr} {op} {right_repr}" - explanation = None - try: - if op == "==": + explanation = None + try: + if op == "==": explanation = _compare_eq_any(left, right, verbose) - elif op == "not in": - if istext(left) and istext(right): - explanation = _notin_text(left, right, verbose) + elif op == "not in": + if istext(left) and istext(right): + explanation = _notin_text(left, right, verbose) except outcomes.Exit: raise - except Exception: - explanation = [ + except Exception: + explanation = [ "(pytest_assertion plugin: representation of details failed: {}.".format( _pytest._code.ExceptionInfo.from_current()._getreprcrash() ), " Probably an object has a faulty __repr__.)", - ] - - if not explanation: - return None - - return [summary] + explanation - - + ] + + if not explanation: + return None + + return [summary] + explanation + + def _compare_eq_any(left: Any, right: Any, verbose: int = 0) -> List[str]: explanation = [] if istext(left) and istext(right): @@ -199,52 +199,52 @@ def _compare_eq_any(left: Any, right: Any, verbose: int = 0) -> List[str]: def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]: """Return the explanation for the diff between text. - - Unless --verbose is used this will skip leading and trailing - characters which are identical to keep the diff minimal. - """ - from difflib import ndiff - + + Unless --verbose is used this will skip leading and trailing + characters which are identical to keep the diff minimal. + """ + from difflib import ndiff + explanation: List[str] = [] - + if verbose < 1: - i = 0 # just in case left or right has zero length - for i in range(min(len(left), len(right))): - if left[i] != right[i]: - break - if i > 42: - i -= 10 # Provide some context - explanation = [ + i = 0 # just in case left or right has zero length + for i in range(min(len(left), len(right))): + if left[i] != right[i]: + break + if i > 42: + i -= 10 # Provide some context + explanation = [ "Skipping %s identical leading characters in diff, use -v to show" % i - ] - left = left[i:] - right = right[i:] - if len(left) == len(right): - for i in range(len(left)): - if left[-i] != right[-i]: - break - if i > 42: - i -= 10 # Provide some context - explanation += [ + ] + left = left[i:] + right = right[i:] + if len(left) == len(right): + for i in range(len(left)): + if left[-i] != right[-i]: + break + if i > 42: + i -= 10 # Provide some context + explanation += [ "Skipping {} identical trailing " "characters in diff, use -v to show".format(i) - ] - left = left[:-i] - right = right[:-i] - keepends = True - if left.isspace() or right.isspace(): - left = repr(str(left)) - right = repr(str(right)) + ] + left = left[:-i] + right = right[:-i] + keepends = True + if left.isspace() or right.isspace(): + left = repr(str(left)) + right = repr(str(right)) explanation += ["Strings contain only whitespace, escaping them using repr()"] # "right" is the expected base against which we compare "left", # see https://github.com/pytest-dev/pytest/issues/3333 - explanation += [ - line.strip("\n") + explanation += [ + line.strip("\n") for line in ndiff(right.splitlines(keepends), left.splitlines(keepends)) - ] - return explanation - - + ] + return explanation + + def _compare_eq_verbose(left: Any, right: Any) -> List[str]: keepends = True left_lines = repr(left).splitlines(keepends) @@ -272,11 +272,11 @@ def _surrounding_parens_on_own_lines(lines: List[str]) -> None: def _compare_eq_iterable( left: Iterable[Any], right: Iterable[Any], verbose: int = 0 ) -> List[str]: - if not verbose: + if not verbose: return ["Use -v to get the full diff"] - # dynamic import to speedup pytest - import difflib - + # dynamic import to speedup pytest + import difflib + left_formatting = pprint.pformat(left).splitlines() right_formatting = pprint.pformat(right).splitlines() @@ -294,12 +294,12 @@ def _compare_eq_iterable( explanation = ["Full diff:"] # "right" is the expected base against which we compare "left", # see https://github.com/pytest-dev/pytest/issues/3333 - explanation.extend( + explanation.extend( line.rstrip() for line in difflib.ndiff(right_formatting, left_formatting) - ) - return explanation - - + ) + return explanation + + def _compare_eq_sequence( left: Sequence[Any], right: Sequence[Any], verbose: int = 0 ) -> List[str]: @@ -308,7 +308,7 @@ def _compare_eq_sequence( len_left = len(left) len_right = len(right) for i in range(min(len_left, len_right)): - if left[i] != right[i]: + if left[i] != right[i]: if comparing_bytes: # when comparing bytes, we want to see their ascii representation # instead of their numeric values (#5260) @@ -325,7 +325,7 @@ def _compare_eq_sequence( right_value = right[i] explanation += [f"At index {i} diff: {left_value!r} != {right_value!r}"] - break + break if comparing_bytes: # when comparing bytes, it doesn't help to show the "sides contain one or more @@ -350,26 +350,26 @@ def _compare_eq_sequence( "%s contains %d more items, first extra item: %s" % (dir_with_more, len_diff, extra) ] - return explanation - - + return explanation + + def _compare_eq_set( left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 ) -> List[str]: - explanation = [] - diff_left = left - right - diff_right = right - left - if diff_left: + explanation = [] + diff_left = left - right + diff_right = right - left + if diff_left: explanation.append("Extra items in the left set:") - for item in diff_left: + for item in diff_left: explanation.append(saferepr(item)) - if diff_right: + if diff_right: explanation.append("Extra items in the right set:") - for item in diff_right: + for item in diff_right: explanation.append(saferepr(item)) - return explanation - - + return explanation + + def _compare_eq_dict( left: Mapping[Any, Any], right: Mapping[Any, Any], verbose: int = 0 ) -> List[str]: @@ -377,16 +377,16 @@ def _compare_eq_dict( set_left = set(left) set_right = set(right) common = set_left.intersection(set_right) - same = {k: left[k] for k in common if left[k] == right[k]} - if same and verbose < 2: + same = {k: left[k] for k in common if left[k] == right[k]} + if same and verbose < 2: explanation += ["Omitting %s identical items, use -vv to show" % len(same)] - elif same: + elif same: explanation += ["Common items:"] - explanation += pprint.pformat(same).splitlines() - diff = {k for k in common if left[k] != right[k]} - if diff: + explanation += pprint.pformat(same).splitlines() + diff = {k for k in common if left[k] != right[k]} + if diff: explanation += ["Differing items:"] - for k in diff: + for k in diff: explanation += [saferepr({k: left[k]}) + " != " + saferepr({k: right[k]})] extra_left = set_left - set_right len_extra_left = len(extra_left) @@ -395,9 +395,9 @@ def _compare_eq_dict( "Left contains %d more item%s:" % (len_extra_left, "" if len_extra_left == 1 else "s") ) - explanation.extend( - pprint.pformat({k: left[k] for k in extra_left}).splitlines() - ) + explanation.extend( + pprint.pformat({k: left[k] for k in extra_left}).splitlines() + ) extra_right = set_right - set_left len_extra_right = len(extra_right) if len_extra_right: @@ -405,12 +405,12 @@ def _compare_eq_dict( "Right contains %d more item%s:" % (len_extra_right, "" if len_extra_right == 1 else "s") ) - explanation.extend( - pprint.pformat({k: right[k] for k in extra_right}).splitlines() - ) - return explanation - - + explanation.extend( + pprint.pformat({k: right[k] for k in extra_right}).splitlines() + ) + return explanation + + def _compare_eq_cls(left: Any, right: Any, verbose: int) -> List[str]: if isdatacls(left): all_fields = left.__dataclass_fields__ @@ -459,19 +459,19 @@ def _compare_eq_cls(left: Any, right: Any, verbose: int) -> List[str]: def _notin_text(term: str, text: str, verbose: int = 0) -> List[str]: - index = text.find(term) - head = text[:index] - tail = text[index + len(term) :] - correct_text = head + tail + index = text.find(term) + head = text[:index] + tail = text[index + len(term) :] + correct_text = head + tail diff = _diff_text(text, correct_text, verbose) newdiff = ["%s is contained here:" % saferepr(term, maxsize=42)] - for line in diff: + for line in diff: if line.startswith("Skipping"): - continue + continue if line.startswith("- "): - continue + continue if line.startswith("+ "): newdiff.append(" " + line[2:]) - else: - newdiff.append(line) - return newdiff + else: + newdiff.append(line) + return newdiff |