summaryrefslogtreecommitdiffstats
path: root/contrib/python/pytest/py2/_pytest/assertion
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-02-10 16:44:39 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:44:39 +0300
commite9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch)
tree64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/python/pytest/py2/_pytest/assertion
parent2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff)
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/pytest/py2/_pytest/assertion')
-rw-r--r--contrib/python/pytest/py2/_pytest/assertion/__init__.py2
-rw-r--r--contrib/python/pytest/py2/_pytest/assertion/rewrite.py164
-rw-r--r--contrib/python/pytest/py2/_pytest/assertion/truncate.py2
-rw-r--r--contrib/python/pytest/py2/_pytest/assertion/util.py282
4 files changed, 225 insertions, 225 deletions
diff --git a/contrib/python/pytest/py2/_pytest/assertion/__init__.py b/contrib/python/pytest/py2/_pytest/assertion/__init__.py
index f83f862cdac..6b6abb863a3 100644
--- a/contrib/python/pytest/py2/_pytest/assertion/__init__.py
+++ b/contrib/python/pytest/py2/_pytest/assertion/__init__.py
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""
support for presenting detailed information in failing assertions.
"""
diff --git a/contrib/python/pytest/py2/_pytest/assertion/rewrite.py b/contrib/python/pytest/py2/_pytest/assertion/rewrite.py
index 0c1822b529a..6cfd81a32f5 100644
--- a/contrib/python/pytest/py2/_pytest/assertion/rewrite.py
+++ b/contrib/python/pytest/py2/_pytest/assertion/rewrite.py
@@ -1,12 +1,12 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""Rewrite assertion AST to produce nice error messages"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
-import warnings
-warnings.filterwarnings("ignore", category=DeprecationWarning, module="_pytest.assertion.rewrite")
-
+import warnings
+warnings.filterwarnings("ignore", category=DeprecationWarning, module="_pytest.assertion.rewrite")
+
import ast
import errno
import imp
@@ -23,11 +23,11 @@ import atomicwrites
import py
import six
-from _pytest._io.saferepr import saferepr
+from _pytest._io.saferepr import saferepr
from _pytest.assertion import util
-from _pytest.assertion.util import ( # noqa: F401
- format_explanation as _format_explanation,
-)
+from _pytest.assertion.util import ( # noqa: F401
+ format_explanation as _format_explanation,
+)
from _pytest.compat import spec_from_file_location
from _pytest.pathlib import fnmatch_ex
from _pytest.pathlib import PurePath
@@ -64,10 +64,10 @@ class AssertionRewritingHook(object):
def __init__(self, config):
self.config = config
- try:
- self.fnpats = config.getini("python_files")
- except ValueError:
- self.fnpats = ["test_*.py", "*_test.py"]
+ try:
+ self.fnpats = config.getini("python_files")
+ except ValueError:
+ self.fnpats = ["test_*.py", "*_test.py"]
self.session = None
self.modules = {}
self._rewritten_names = set()
@@ -274,14 +274,14 @@ class AssertionRewritingHook(object):
self._marked_for_rewrite_cache.clear()
def _warn_already_imported(self, name):
- from _pytest.warning_types import PytestAssertRewriteWarning
- from _pytest.warnings import _issue_warning_captured
+ from _pytest.warning_types import PytestAssertRewriteWarning
+ from _pytest.warnings import _issue_warning_captured
- _issue_warning_captured(
- PytestAssertRewriteWarning(
- "Module already imported so cannot be rewritten: %s" % name
- ),
- self.config.hook,
+ _issue_warning_captured(
+ PytestAssertRewriteWarning(
+ "Module already imported so cannot be rewritten: %s" % name
+ ),
+ self.config.hook,
stacklevel=5,
)
@@ -304,7 +304,7 @@ class AssertionRewritingHook(object):
mod.__loader__ = self
# Normally, this attribute is 3.4+
mod.__spec__ = spec_from_file_location(name, co.co_filename, loader=self)
- exec(co, mod.__dict__)
+ exec(co, mod.__dict__)
except: # noqa
if name in sys.modules:
del sys.modules[name]
@@ -337,11 +337,11 @@ def _write_pyc(state, co, source_stat, pyc):
try:
with atomicwrites.atomic_write(pyc, mode="wb", overwrite=True) as fp:
fp.write(imp.get_magic())
- # as of now, bytecode header expects 32-bit numbers for size and mtime (#4903)
- mtime = int(source_stat.mtime) & 0xFFFFFFFF
+ # as of now, bytecode header expects 32-bit numbers for size and mtime (#4903)
+ mtime = int(source_stat.mtime) & 0xFFFFFFFF
size = source_stat.size & 0xFFFFFFFF
- # "<LL" stands for 2 unsigned longs, little-ending
- fp.write(struct.pack("<LL", mtime, size))
+ # "<LL" stands for 2 unsigned longs, little-ending
+ fp.write(struct.pack("<LL", mtime, size))
fp.write(marshal.dumps(co))
except EnvironmentError as e:
state.trace("error writing pyc file at %s: errno=%s" % (pyc, e.errno))
@@ -436,7 +436,7 @@ def _read_pyc(source, pyc, trace=lambda x: None):
if (
len(data) != 12
or data[:4] != imp.get_magic()
- or struct.unpack("<LL", data[4:]) != (mtime & 0xFFFFFFFF, size & 0xFFFFFFFF)
+ or struct.unpack("<LL", data[4:]) != (mtime & 0xFFFFFFFF, size & 0xFFFFFFFF)
):
trace("_read_pyc(%s): invalid or out of date pyc" % source)
return None
@@ -467,7 +467,7 @@ def _saferepr(obj):
JSON reprs.
"""
- r = saferepr(obj)
+ r = saferepr(obj)
# only occurs in python2.x, repr must return text in python3+
if isinstance(r, bytes):
# Represent unprintable bytes as `\x##`
@@ -483,7 +483,7 @@ def _format_assertmsg(obj):
For strings this simply replaces newlines with '\n~' so that
util.format_explanation() will preserve them instead of escaping
- newlines. For other objects saferepr() is used first.
+ newlines. For other objects saferepr() is used first.
"""
# reprlib appears to have a bug which means that if a string
@@ -492,7 +492,7 @@ def _format_assertmsg(obj):
# However in either case we want to preserve the newline.
replaces = [(u"\n", u"\n~"), (u"%", u"%%")]
if not isinstance(obj, six.string_types):
- obj = saferepr(obj)
+ obj = saferepr(obj)
replaces.append((u"\\n", u"\n~"))
if isinstance(obj, bytes):
@@ -505,15 +505,15 @@ def _format_assertmsg(obj):
def _should_repr_global_name(obj):
- if callable(obj):
- return False
+ if callable(obj):
+ return False
+
+ try:
+ return not hasattr(obj, "__name__")
+ except Exception:
+ return True
- try:
- return not hasattr(obj, "__name__")
- except Exception:
- return True
-
def _format_boolop(explanations, is_or):
explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")"
if isinstance(explanation, six.text_type):
@@ -658,7 +658,7 @@ class AssertionRewriter(ast.NodeVisitor):
# Insert some special imports at the top of the module but after any
# docstrings and __future__ imports.
aliases = [
- ast.alias(six.moves.builtins.__name__, "@py_builtins"),
+ ast.alias(six.moves.builtins.__name__, "@py_builtins"),
ast.alias("_pytest.assertion.rewrite", "@pytest_ar"),
]
doc = getattr(mod, "docstring", None)
@@ -733,13 +733,13 @@ class AssertionRewriter(ast.NodeVisitor):
return ast.Name(name, ast.Load())
def display(self, expr):
- """Call saferepr on the expression."""
- return self.helper("_saferepr", expr)
+ """Call saferepr on the expression."""
+ return self.helper("_saferepr", expr)
def helper(self, name, *args):
"""Call a helper in this module."""
py_name = ast.Name("@pytest_ar", ast.Load())
- attr = ast.Attribute(py_name, name, ast.Load())
+ attr = ast.Attribute(py_name, name, ast.Load())
return ast_Call(attr, list(args), [])
def builtin(self, name):
@@ -809,13 +809,13 @@ class AssertionRewriter(ast.NodeVisitor):
"""
if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1:
- from _pytest.warning_types import PytestAssertRewriteWarning
+ from _pytest.warning_types import PytestAssertRewriteWarning
import warnings
warnings.warn_explicit(
- PytestAssertRewriteWarning(
- "assertion is always true, perhaps remove parentheses?"
- ),
+ PytestAssertRewriteWarning(
+ "assertion is always true, perhaps remove parentheses?"
+ ),
category=None,
filename=str(self.module_path),
lineno=assert_.lineno,
@@ -829,26 +829,26 @@ class AssertionRewriter(ast.NodeVisitor):
self.push_format_context()
# Rewrite assert into a bunch of statements.
top_condition, explanation = self.visit(assert_.test)
- # If in a test module, check if directly asserting None, in order to warn [Issue #3191]
- if self.module_path is not None:
- self.statements.append(
- self.warn_about_none_ast(
- top_condition, module_path=self.module_path, lineno=assert_.lineno
- )
- )
+ # If in a test module, check if directly asserting None, in order to warn [Issue #3191]
+ if self.module_path is not None:
+ self.statements.append(
+ self.warn_about_none_ast(
+ top_condition, module_path=self.module_path, lineno=assert_.lineno
+ )
+ )
# Create failure message.
body = self.on_failure
negation = ast.UnaryOp(ast.Not(), top_condition)
self.statements.append(ast.If(negation, body, []))
if assert_.msg:
- assertmsg = self.helper("_format_assertmsg", assert_.msg)
+ assertmsg = self.helper("_format_assertmsg", assert_.msg)
explanation = "\n>assert " + explanation
else:
assertmsg = ast.Str("")
explanation = "assert " + explanation
template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
msg = self.pop_format_context(template)
- fmt = self.helper("_format_explanation", msg)
+ fmt = self.helper("_format_explanation", msg)
err_name = ast.Name("AssertionError", ast.Load())
exc = ast_Call(err_name, [fmt], [])
if sys.version_info[0] >= 3:
@@ -866,39 +866,39 @@ class AssertionRewriter(ast.NodeVisitor):
set_location(stmt, assert_.lineno, assert_.col_offset)
return self.statements
- def warn_about_none_ast(self, node, module_path, lineno):
- """
- Returns an AST issuing a warning if the value of node is `None`.
- This is used to warn the user when asserting a function that asserts
- internally already.
- See issue #3191 for more details.
- """
-
- # Using parse because it is different between py2 and py3.
- AST_NONE = ast.parse("None").body[0].value
- val_is_none = ast.Compare(node, [ast.Is()], [AST_NONE])
- send_warning = ast.parse(
- """
-from _pytest.warning_types import PytestAssertRewriteWarning
-from warnings import warn_explicit
-warn_explicit(
- PytestAssertRewriteWarning('asserting the value None, please use "assert is None"'),
- category=None,
- filename={filename!r},
- lineno={lineno},
-)
- """.format(
- filename=module_path.strpath, lineno=lineno
- )
- ).body
- return ast.If(val_is_none, send_warning, [])
-
+ def warn_about_none_ast(self, node, module_path, lineno):
+ """
+ Returns an AST issuing a warning if the value of node is `None`.
+ This is used to warn the user when asserting a function that asserts
+ internally already.
+ See issue #3191 for more details.
+ """
+
+ # Using parse because it is different between py2 and py3.
+ AST_NONE = ast.parse("None").body[0].value
+ val_is_none = ast.Compare(node, [ast.Is()], [AST_NONE])
+ send_warning = ast.parse(
+ """
+from _pytest.warning_types import PytestAssertRewriteWarning
+from warnings import warn_explicit
+warn_explicit(
+ PytestAssertRewriteWarning('asserting the value None, please use "assert is None"'),
+ category=None,
+ filename={filename!r},
+ lineno={lineno},
+)
+ """.format(
+ filename=module_path.strpath, lineno=lineno
+ )
+ ).body
+ return ast.If(val_is_none, send_warning, [])
+
def visit_Name(self, name):
# Display the repr of the name if it's a local variable or
# _should_repr_global_name() thinks it's acceptable.
locs = ast_Call(self.builtin("locals"), [], [])
inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs])
- dorepr = self.helper("_should_repr_global_name", name)
+ dorepr = self.helper("_should_repr_global_name", name)
test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
expr = ast.IfExp(test, self.display(name), ast.Str(name.id))
return name, self.explanation_param(expr)
@@ -934,7 +934,7 @@ warn_explicit(
self.statements = body = inner
self.statements = save
self.on_failure = fail_save
- expl_template = self.helper("_format_boolop", expl_list, ast.Num(is_or))
+ expl_template = self.helper("_format_boolop", expl_list, ast.Num(is_or))
expl = self.pop_format_context(expl_template)
return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
@@ -1059,7 +1059,7 @@ warn_explicit(
left_res, left_expl = next_res, next_expl
# Use pytest.assertion.util._reprcompare if that's available.
expl_call = self.helper(
- "_call_reprcompare",
+ "_call_reprcompare",
ast.Tuple(syms, ast.Load()),
ast.Tuple(load_names, ast.Load()),
ast.Tuple(expls, ast.Load()),
diff --git a/contrib/python/pytest/py2/_pytest/assertion/truncate.py b/contrib/python/pytest/py2/_pytest/assertion/truncate.py
index 0451daa0910..525896ea9ad 100644
--- a/contrib/python/pytest/py2/_pytest/assertion/truncate.py
+++ b/contrib/python/pytest/py2/_pytest/assertion/truncate.py
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""
Utilities for truncating assertion output.
diff --git a/contrib/python/pytest/py2/_pytest/assertion/util.py b/contrib/python/pytest/py2/_pytest/assertion/util.py
index 12d59c0e02c..c382f1c6091 100644
--- a/contrib/python/pytest/py2/_pytest/assertion/util.py
+++ b/contrib/python/pytest/py2/_pytest/assertion/util.py
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""Utilities for assertion debugging"""
from __future__ import absolute_import
from __future__ import division
@@ -10,9 +10,9 @@ import six
import _pytest._code
from ..compat import Sequence
-from _pytest import outcomes
-from _pytest._io.saferepr import saferepr
-from _pytest.compat import ATTRS_EQ_FIELD
+from _pytest import outcomes
+from _pytest._io.saferepr import saferepr
+from _pytest.compat import ATTRS_EQ_FIELD
# The _reprcompare attribute on the util module is used by the new assertion
# interpretation code and assertion rewriter to detect this plugin was
@@ -105,46 +105,46 @@ except NameError:
basestring = str
-def issequence(x):
- return isinstance(x, Sequence) and not isinstance(x, basestring)
+def issequence(x):
+ return isinstance(x, Sequence) and not isinstance(x, basestring)
-def istext(x):
- return isinstance(x, basestring)
+def istext(x):
+ return isinstance(x, basestring)
-def isdict(x):
- return isinstance(x, dict)
+def isdict(x):
+ return isinstance(x, dict)
-def isset(x):
- return isinstance(x, (set, frozenset))
+def isset(x):
+ return isinstance(x, (set, frozenset))
+
+
+def isdatacls(obj):
+ return getattr(obj, "__dataclass_fields__", None) is not None
+
+
+def isattrs(obj):
+ return getattr(obj, "__attrs_attrs__", None) is not None
+
+
+def isiterable(obj):
+ try:
+ iter(obj)
+ return not istext(obj)
+ except TypeError:
+ return False
+
+
+def assertrepr_compare(config, op, left, right):
+ """Return specialised explanations for some operators/operands"""
+ width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
+ left_repr = saferepr(left, maxsize=int(width // 2))
+ right_repr = saferepr(right, maxsize=width - len(left_repr))
+
+ summary = u"%s %s %s" % (ecu(left_repr), op, ecu(right_repr))
-
-def isdatacls(obj):
- return getattr(obj, "__dataclass_fields__", None) is not None
-
-
-def isattrs(obj):
- return getattr(obj, "__attrs_attrs__", None) is not None
-
-
-def isiterable(obj):
- try:
- iter(obj)
- return not istext(obj)
- except TypeError:
- return False
-
-
-def assertrepr_compare(config, op, left, right):
- """Return specialised explanations for some operators/operands"""
- width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
- left_repr = saferepr(left, maxsize=int(width // 2))
- right_repr = saferepr(right, maxsize=width - len(left_repr))
-
- summary = u"%s %s %s" % (ecu(left_repr), op, ecu(right_repr))
-
verbose = config.getoption("verbose")
explanation = None
try:
@@ -158,11 +158,11 @@ def assertrepr_compare(config, op, left, right):
explanation = _compare_eq_set(left, right, verbose)
elif isdict(left) and isdict(right):
explanation = _compare_eq_dict(left, right, verbose)
- elif type(left) == type(right) and (isdatacls(left) or isattrs(left)):
- type_fn = (isdatacls, isattrs)
- explanation = _compare_eq_cls(left, right, verbose, type_fn)
- elif verbose > 0:
- explanation = _compare_eq_verbose(left, right)
+ elif type(left) == type(right) and (isdatacls(left) or isattrs(left)):
+ type_fn = (isdatacls, isattrs)
+ explanation = _compare_eq_cls(left, right, verbose, type_fn)
+ elif verbose > 0:
+ explanation = _compare_eq_verbose(left, right)
if isiterable(left) and isiterable(right):
expl = _compare_eq_iterable(left, right, verbose)
if explanation is not None:
@@ -172,13 +172,13 @@ def assertrepr_compare(config, op, left, right):
elif op == "not in":
if istext(left) and istext(right):
explanation = _notin_text(left, right, verbose)
- except outcomes.Exit:
- raise
+ except outcomes.Exit:
+ raise
except Exception:
explanation = [
u"(pytest_assertion plugin: representation of details failed. "
u"Probably an object has a faulty __repr__.)",
- six.text_type(_pytest._code.ExceptionInfo.from_current()),
+ six.text_type(_pytest._code.ExceptionInfo.from_current()),
]
if not explanation:
@@ -187,8 +187,8 @@ def assertrepr_compare(config, op, left, right):
return [summary] + explanation
-def _diff_text(left, right, verbose=0):
- """Return the explanation for the diff between text or bytes.
+def _diff_text(left, right, verbose=0):
+ """Return the explanation for the diff between text or bytes.
Unless --verbose is used this will skip leading and trailing
characters which are identical to keep the diff minimal.
@@ -214,7 +214,7 @@ def _diff_text(left, right, verbose=0):
left = escape_for_readable_diff(left)
if isinstance(right, bytes):
right = escape_for_readable_diff(right)
- if verbose < 1:
+ 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]:
@@ -250,19 +250,19 @@ def _diff_text(left, right, verbose=0):
return explanation
-def _compare_eq_verbose(left, right):
- keepends = True
- left_lines = repr(left).splitlines(keepends)
- right_lines = repr(right).splitlines(keepends)
-
- explanation = []
- explanation += [u"-" + line for line in left_lines]
- explanation += [u"+" + line for line in right_lines]
-
- return explanation
-
-
-def _compare_eq_iterable(left, right, verbose=0):
+def _compare_eq_verbose(left, right):
+ keepends = True
+ left_lines = repr(left).splitlines(keepends)
+ right_lines = repr(right).splitlines(keepends)
+
+ explanation = []
+ explanation += [u"-" + line for line in left_lines]
+ explanation += [u"+" + line for line in right_lines]
+
+ return explanation
+
+
+def _compare_eq_iterable(left, right, verbose=0):
if not verbose:
return [u"Use -v to get the full diff"]
# dynamic import to speedup pytest
@@ -285,55 +285,55 @@ def _compare_eq_iterable(left, right, verbose=0):
return explanation
-def _compare_eq_sequence(left, right, verbose=0):
+def _compare_eq_sequence(left, right, verbose=0):
explanation = []
- len_left = len(left)
- len_right = len(right)
- for i in range(min(len_left, len_right)):
+ len_left = len(left)
+ len_right = len(right)
+ for i in range(min(len_left, len_right)):
if left[i] != right[i]:
explanation += [u"At index %s diff: %r != %r" % (i, left[i], right[i])]
break
- len_diff = len_left - len_right
-
- if len_diff:
- if len_diff > 0:
- dir_with_more = "Left"
- extra = saferepr(left[len_right])
- else:
- len_diff = 0 - len_diff
- dir_with_more = "Right"
- extra = saferepr(right[len_left])
-
- if len_diff == 1:
- explanation += [u"%s contains one more item: %s" % (dir_with_more, extra)]
- else:
- explanation += [
- u"%s contains %d more items, first extra item: %s"
- % (dir_with_more, len_diff, extra)
- ]
+ len_diff = len_left - len_right
+
+ if len_diff:
+ if len_diff > 0:
+ dir_with_more = "Left"
+ extra = saferepr(left[len_right])
+ else:
+ len_diff = 0 - len_diff
+ dir_with_more = "Right"
+ extra = saferepr(right[len_left])
+
+ if len_diff == 1:
+ explanation += [u"%s contains one more item: %s" % (dir_with_more, extra)]
+ else:
+ explanation += [
+ u"%s contains %d more items, first extra item: %s"
+ % (dir_with_more, len_diff, extra)
+ ]
return explanation
-def _compare_eq_set(left, right, verbose=0):
+def _compare_eq_set(left, right, verbose=0):
explanation = []
diff_left = left - right
diff_right = right - left
if diff_left:
explanation.append(u"Extra items in the left set:")
for item in diff_left:
- explanation.append(saferepr(item))
+ explanation.append(saferepr(item))
if diff_right:
explanation.append(u"Extra items in the right set:")
for item in diff_right:
- explanation.append(saferepr(item))
+ explanation.append(saferepr(item))
return explanation
-def _compare_eq_dict(left, right, verbose=0):
+def _compare_eq_dict(left, right, verbose=0):
explanation = []
- set_left = set(left)
- set_right = set(right)
- common = set_left.intersection(set_right)
+ 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:
explanation += [u"Omitting %s identical items, use -vv to show" % len(same)]
@@ -344,71 +344,71 @@ def _compare_eq_dict(left, right, verbose=0):
if diff:
explanation += [u"Differing items:"]
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)
- if len_extra_left:
- explanation.append(
- u"Left contains %d more item%s:"
- % (len_extra_left, "" if len_extra_left == 1 else "s")
- )
+ explanation += [saferepr({k: left[k]}) + " != " + saferepr({k: right[k]})]
+ extra_left = set_left - set_right
+ len_extra_left = len(extra_left)
+ if len_extra_left:
+ explanation.append(
+ u"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()
)
- extra_right = set_right - set_left
- len_extra_right = len(extra_right)
- if len_extra_right:
- explanation.append(
- u"Right contains %d more item%s:"
- % (len_extra_right, "" if len_extra_right == 1 else "s")
- )
+ extra_right = set_right - set_left
+ len_extra_right = len(extra_right)
+ if len_extra_right:
+ explanation.append(
+ u"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
-def _compare_eq_cls(left, right, verbose, type_fns):
- isdatacls, isattrs = type_fns
- if isdatacls(left):
- all_fields = left.__dataclass_fields__
- fields_to_check = [field for field, info in all_fields.items() if info.compare]
- elif isattrs(left):
- all_fields = left.__attrs_attrs__
- fields_to_check = [
- field.name for field in all_fields if getattr(field, ATTRS_EQ_FIELD)
- ]
-
- same = []
- diff = []
- for field in fields_to_check:
- if getattr(left, field) == getattr(right, field):
- same.append(field)
- else:
- diff.append(field)
-
- explanation = []
- if same and verbose < 2:
- explanation.append(u"Omitting %s identical items, use -vv to show" % len(same))
- elif same:
- explanation += [u"Matching attributes:"]
- explanation += pprint.pformat(same).splitlines()
- if diff:
- explanation += [u"Differing attributes:"]
- for field in diff:
- explanation += [
- (u"%s: %r != %r") % (field, getattr(left, field), getattr(right, field))
- ]
- return explanation
-
-
-def _notin_text(term, text, verbose=0):
+def _compare_eq_cls(left, right, verbose, type_fns):
+ isdatacls, isattrs = type_fns
+ if isdatacls(left):
+ all_fields = left.__dataclass_fields__
+ fields_to_check = [field for field, info in all_fields.items() if info.compare]
+ elif isattrs(left):
+ all_fields = left.__attrs_attrs__
+ fields_to_check = [
+ field.name for field in all_fields if getattr(field, ATTRS_EQ_FIELD)
+ ]
+
+ same = []
+ diff = []
+ for field in fields_to_check:
+ if getattr(left, field) == getattr(right, field):
+ same.append(field)
+ else:
+ diff.append(field)
+
+ explanation = []
+ if same and verbose < 2:
+ explanation.append(u"Omitting %s identical items, use -vv to show" % len(same))
+ elif same:
+ explanation += [u"Matching attributes:"]
+ explanation += pprint.pformat(same).splitlines()
+ if diff:
+ explanation += [u"Differing attributes:"]
+ for field in diff:
+ explanation += [
+ (u"%s: %r != %r") % (field, getattr(left, field), getattr(right, field))
+ ]
+ return explanation
+
+
+def _notin_text(term, text, verbose=0):
index = text.find(term)
head = text[:index]
tail = text[index + len(term) :]
correct_text = head + tail
diff = _diff_text(correct_text, text, verbose)
- newdiff = [u"%s is contained here:" % saferepr(term, maxsize=42)]
+ newdiff = [u"%s is contained here:" % saferepr(term, maxsize=42)]
for line in diff:
if line.startswith(u"Skipping"):
continue