Improve the full diff by having more consistent indentation in the PrettyPrinter (#11571)
The normal default pretty printer is not great when objects are nested and it can get hard to read the diff. Instead, provide a pretty printer that behaves more like when json get indented, which allows for smaller, more meaningful differences, at the expense of a slightly longer diff. This does not touch the other places where the pretty printer is used, and only updated the full diff one.
This commit is contained in:
parent
fe8cda051b
commit
2d1710e0e9
|
@ -0,0 +1,4 @@
|
||||||
|
Improved the very verbose diff for every standard library container types: the indentation is now consistent and the markers are on their own separate lines, which should reduce the diffs shown to users.
|
||||||
|
|
||||||
|
Previously, the default python pretty printer was used to generate the output, which puts opening and closing
|
||||||
|
markers on the same line as the first/last entry, in addition to not having consistent indentation.
|
|
@ -58,7 +58,7 @@ def _safe_tuple(t):
|
||||||
class PrettyPrinter:
|
class PrettyPrinter:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
indent=1,
|
indent=4,
|
||||||
width=80,
|
width=80,
|
||||||
depth=None,
|
depth=None,
|
||||||
stream=None,
|
stream=None,
|
||||||
|
@ -146,7 +146,6 @@ class PrettyPrinter:
|
||||||
|
|
||||||
def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
|
def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
|
||||||
cls_name = object.__class__.__name__
|
cls_name = object.__class__.__name__
|
||||||
indent += len(cls_name) + 1
|
|
||||||
items = [
|
items = [
|
||||||
(f.name, getattr(object, f.name))
|
(f.name, getattr(object, f.name))
|
||||||
for f in _dataclasses.fields(object)
|
for f in _dataclasses.fields(object)
|
||||||
|
@ -164,17 +163,11 @@ class PrettyPrinter:
|
||||||
def _pprint_dict(self, object, stream, indent, allowance, context, level):
|
def _pprint_dict(self, object, stream, indent, allowance, context, level):
|
||||||
write = stream.write
|
write = stream.write
|
||||||
write("{")
|
write("{")
|
||||||
if self._indent_per_level > 1:
|
if self._sort_dicts:
|
||||||
write((self._indent_per_level - 1) * " ")
|
items = sorted(object.items(), key=_safe_tuple)
|
||||||
length = len(object)
|
else:
|
||||||
if length:
|
items = object.items()
|
||||||
if self._sort_dicts:
|
self._format_dict_items(items, stream, indent, allowance, context, level)
|
||||||
items = sorted(object.items(), key=_safe_tuple)
|
|
||||||
else:
|
|
||||||
items = object.items()
|
|
||||||
self._format_dict_items(
|
|
||||||
items, stream, indent, allowance + 1, context, level
|
|
||||||
)
|
|
||||||
write("}")
|
write("}")
|
||||||
|
|
||||||
_dispatch[dict.__repr__] = _pprint_dict
|
_dispatch[dict.__repr__] = _pprint_dict
|
||||||
|
@ -185,32 +178,22 @@ class PrettyPrinter:
|
||||||
return
|
return
|
||||||
cls = object.__class__
|
cls = object.__class__
|
||||||
stream.write(cls.__name__ + "(")
|
stream.write(cls.__name__ + "(")
|
||||||
self._format(
|
self._pprint_dict(object, stream, indent, allowance, context, level)
|
||||||
list(object.items()),
|
|
||||||
stream,
|
|
||||||
indent + len(cls.__name__) + 1,
|
|
||||||
allowance + 1,
|
|
||||||
context,
|
|
||||||
level,
|
|
||||||
)
|
|
||||||
stream.write(")")
|
stream.write(")")
|
||||||
|
|
||||||
_dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict
|
_dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict
|
||||||
|
|
||||||
def _pprint_list(self, object, stream, indent, allowance, context, level):
|
def _pprint_list(self, object, stream, indent, allowance, context, level):
|
||||||
stream.write("[")
|
stream.write("[")
|
||||||
self._format_items(object, stream, indent, allowance + 1, context, level)
|
self._format_items(object, stream, indent, allowance, context, level)
|
||||||
stream.write("]")
|
stream.write("]")
|
||||||
|
|
||||||
_dispatch[list.__repr__] = _pprint_list
|
_dispatch[list.__repr__] = _pprint_list
|
||||||
|
|
||||||
def _pprint_tuple(self, object, stream, indent, allowance, context, level):
|
def _pprint_tuple(self, object, stream, indent, allowance, context, level):
|
||||||
stream.write("(")
|
stream.write("(")
|
||||||
endchar = ",)" if len(object) == 1 else ")"
|
self._format_items(object, stream, indent, allowance, context, level)
|
||||||
self._format_items(
|
stream.write(")")
|
||||||
object, stream, indent, allowance + len(endchar), context, level
|
|
||||||
)
|
|
||||||
stream.write(endchar)
|
|
||||||
|
|
||||||
_dispatch[tuple.__repr__] = _pprint_tuple
|
_dispatch[tuple.__repr__] = _pprint_tuple
|
||||||
|
|
||||||
|
@ -225,11 +208,8 @@ class PrettyPrinter:
|
||||||
else:
|
else:
|
||||||
stream.write(typ.__name__ + "({")
|
stream.write(typ.__name__ + "({")
|
||||||
endchar = "})"
|
endchar = "})"
|
||||||
indent += len(typ.__name__) + 1
|
|
||||||
object = sorted(object, key=_safe_key)
|
object = sorted(object, key=_safe_key)
|
||||||
self._format_items(
|
self._format_items(object, stream, indent, allowance, context, level)
|
||||||
object, stream, indent, allowance + len(endchar), context, level
|
|
||||||
)
|
|
||||||
stream.write(endchar)
|
stream.write(endchar)
|
||||||
|
|
||||||
_dispatch[set.__repr__] = _pprint_set
|
_dispatch[set.__repr__] = _pprint_set
|
||||||
|
@ -319,7 +299,7 @@ class PrettyPrinter:
|
||||||
|
|
||||||
def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level):
|
def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level):
|
||||||
stream.write("mappingproxy(")
|
stream.write("mappingproxy(")
|
||||||
self._format(object.copy(), stream, indent + 13, allowance + 1, context, level)
|
self._format(object.copy(), stream, indent, allowance, context, level)
|
||||||
stream.write(")")
|
stream.write(")")
|
||||||
|
|
||||||
_dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy
|
_dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy
|
||||||
|
@ -333,7 +313,6 @@ class PrettyPrinter:
|
||||||
cls_name = "namespace"
|
cls_name = "namespace"
|
||||||
else:
|
else:
|
||||||
cls_name = object.__class__.__name__
|
cls_name = object.__class__.__name__
|
||||||
indent += len(cls_name) + 1
|
|
||||||
items = object.__dict__.items()
|
items = object.__dict__.items()
|
||||||
stream.write(cls_name + "(")
|
stream.write(cls_name + "(")
|
||||||
self._format_namespace_items(items, stream, indent, allowance, context, level)
|
self._format_namespace_items(items, stream, indent, allowance, context, level)
|
||||||
|
@ -342,32 +321,30 @@ class PrettyPrinter:
|
||||||
_dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
|
_dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
|
||||||
|
|
||||||
def _format_dict_items(self, items, stream, indent, allowance, context, level):
|
def _format_dict_items(self, items, stream, indent, allowance, context, level):
|
||||||
|
if not items:
|
||||||
|
return
|
||||||
|
|
||||||
write = stream.write
|
write = stream.write
|
||||||
indent += self._indent_per_level
|
item_indent = indent + self._indent_per_level
|
||||||
delimnl = ",\n" + " " * indent
|
delimnl = "\n" + " " * item_indent
|
||||||
last_index = len(items) - 1
|
for key, ent in items:
|
||||||
for i, (key, ent) in enumerate(items):
|
write(delimnl)
|
||||||
last = i == last_index
|
write(self._repr(key, context, level))
|
||||||
rep = self._repr(key, context, level)
|
|
||||||
write(rep)
|
|
||||||
write(": ")
|
write(": ")
|
||||||
self._format(
|
self._format(ent, stream, item_indent, 1, context, level)
|
||||||
ent,
|
write(",")
|
||||||
stream,
|
|
||||||
indent + len(rep) + 2,
|
write("\n" + " " * indent)
|
||||||
allowance if last else 1,
|
|
||||||
context,
|
|
||||||
level,
|
|
||||||
)
|
|
||||||
if not last:
|
|
||||||
write(delimnl)
|
|
||||||
|
|
||||||
def _format_namespace_items(self, items, stream, indent, allowance, context, level):
|
def _format_namespace_items(self, items, stream, indent, allowance, context, level):
|
||||||
|
if not items:
|
||||||
|
return
|
||||||
|
|
||||||
write = stream.write
|
write = stream.write
|
||||||
delimnl = ",\n" + " " * indent
|
item_indent = indent + self._indent_per_level
|
||||||
last_index = len(items) - 1
|
delimnl = "\n" + " " * item_indent
|
||||||
for i, (key, ent) in enumerate(items):
|
for key, ent in items:
|
||||||
last = i == last_index
|
write(delimnl)
|
||||||
write(key)
|
write(key)
|
||||||
write("=")
|
write("=")
|
||||||
if id(ent) in context:
|
if id(ent) in context:
|
||||||
|
@ -378,52 +355,30 @@ class PrettyPrinter:
|
||||||
self._format(
|
self._format(
|
||||||
ent,
|
ent,
|
||||||
stream,
|
stream,
|
||||||
indent + len(key) + 1,
|
item_indent + len(key) + 1,
|
||||||
allowance if last else 1,
|
1,
|
||||||
context,
|
context,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
if not last:
|
|
||||||
write(delimnl)
|
write(",")
|
||||||
|
|
||||||
|
write("\n" + " " * indent)
|
||||||
|
|
||||||
def _format_items(self, items, stream, indent, allowance, context, level):
|
def _format_items(self, items, stream, indent, allowance, context, level):
|
||||||
write = stream.write
|
if not items:
|
||||||
indent += self._indent_per_level
|
|
||||||
if self._indent_per_level > 1:
|
|
||||||
write((self._indent_per_level - 1) * " ")
|
|
||||||
delimnl = ",\n" + " " * indent
|
|
||||||
delim = ""
|
|
||||||
width = max_width = self._width - indent + 1
|
|
||||||
it = iter(items)
|
|
||||||
try:
|
|
||||||
next_ent = next(it)
|
|
||||||
except StopIteration:
|
|
||||||
return
|
return
|
||||||
last = False
|
|
||||||
while not last:
|
write = stream.write
|
||||||
ent = next_ent
|
item_indent = indent + self._indent_per_level
|
||||||
try:
|
delimnl = "\n" + " " * item_indent
|
||||||
next_ent = next(it)
|
|
||||||
except StopIteration:
|
for item in items:
|
||||||
last = True
|
write(delimnl)
|
||||||
max_width -= allowance
|
self._format(item, stream, item_indent, 1, context, level)
|
||||||
width -= allowance
|
write(",")
|
||||||
if self._compact:
|
|
||||||
rep = self._repr(ent, context, level)
|
write("\n" + " " * indent)
|
||||||
w = len(rep) + 2
|
|
||||||
if width < w:
|
|
||||||
width = max_width
|
|
||||||
if delim:
|
|
||||||
delim = delimnl
|
|
||||||
if width >= w:
|
|
||||||
width -= w
|
|
||||||
write(delim)
|
|
||||||
delim = ", "
|
|
||||||
write(rep)
|
|
||||||
continue
|
|
||||||
write(delim)
|
|
||||||
delim = delimnl
|
|
||||||
self._format(ent, stream, indent, allowance if last else 1, context, level)
|
|
||||||
|
|
||||||
def _repr(self, object, context, level):
|
def _repr(self, object, context, level):
|
||||||
repr, readable, recursive = self.format(
|
repr, readable, recursive = self.format(
|
||||||
|
@ -443,66 +398,45 @@ class PrettyPrinter:
|
||||||
return self._safe_repr(object, context, maxlevels, level)
|
return self._safe_repr(object, context, maxlevels, level)
|
||||||
|
|
||||||
def _pprint_default_dict(self, object, stream, indent, allowance, context, level):
|
def _pprint_default_dict(self, object, stream, indent, allowance, context, level):
|
||||||
if not len(object):
|
|
||||||
stream.write(repr(object))
|
|
||||||
return
|
|
||||||
rdf = self._repr(object.default_factory, context, level)
|
rdf = self._repr(object.default_factory, context, level)
|
||||||
cls = object.__class__
|
stream.write(f"{object.__class__.__name__}({rdf}, ")
|
||||||
indent += len(cls.__name__) + 1
|
self._pprint_dict(object, stream, indent, allowance, context, level)
|
||||||
stream.write(f"{cls.__name__}({rdf},\n{' ' * indent}")
|
|
||||||
self._pprint_dict(object, stream, indent, allowance + 1, context, level)
|
|
||||||
stream.write(")")
|
stream.write(")")
|
||||||
|
|
||||||
_dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict
|
_dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict
|
||||||
|
|
||||||
def _pprint_counter(self, object, stream, indent, allowance, context, level):
|
def _pprint_counter(self, object, stream, indent, allowance, context, level):
|
||||||
if not len(object):
|
stream.write(object.__class__.__name__ + "(")
|
||||||
stream.write(repr(object))
|
|
||||||
return
|
if object:
|
||||||
cls = object.__class__
|
stream.write("{")
|
||||||
stream.write(cls.__name__ + "({")
|
items = object.most_common()
|
||||||
if self._indent_per_level > 1:
|
self._format_dict_items(items, stream, indent, allowance, context, level)
|
||||||
stream.write((self._indent_per_level - 1) * " ")
|
stream.write("}")
|
||||||
items = object.most_common()
|
|
||||||
self._format_dict_items(
|
stream.write(")")
|
||||||
items, stream, indent + len(cls.__name__) + 1, allowance + 2, context, level
|
|
||||||
)
|
|
||||||
stream.write("})")
|
|
||||||
|
|
||||||
_dispatch[_collections.Counter.__repr__] = _pprint_counter
|
_dispatch[_collections.Counter.__repr__] = _pprint_counter
|
||||||
|
|
||||||
def _pprint_chain_map(self, object, stream, indent, allowance, context, level):
|
def _pprint_chain_map(self, object, stream, indent, allowance, context, level):
|
||||||
if not len(object.maps):
|
if not len(object.maps) or (len(object.maps) == 1 and not len(object.maps[0])):
|
||||||
stream.write(repr(object))
|
stream.write(repr(object))
|
||||||
return
|
return
|
||||||
cls = object.__class__
|
|
||||||
stream.write(cls.__name__ + "(")
|
stream.write(object.__class__.__name__ + "(")
|
||||||
indent += len(cls.__name__) + 1
|
self._format_items(object.maps, stream, indent, allowance, context, level)
|
||||||
for i, m in enumerate(object.maps):
|
stream.write(")")
|
||||||
if i == len(object.maps) - 1:
|
|
||||||
self._format(m, stream, indent, allowance + 1, context, level)
|
|
||||||
stream.write(")")
|
|
||||||
else:
|
|
||||||
self._format(m, stream, indent, 1, context, level)
|
|
||||||
stream.write(",\n" + " " * indent)
|
|
||||||
|
|
||||||
_dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map
|
_dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map
|
||||||
|
|
||||||
def _pprint_deque(self, object, stream, indent, allowance, context, level):
|
def _pprint_deque(self, object, stream, indent, allowance, context, level):
|
||||||
if not len(object):
|
stream.write(object.__class__.__name__ + "(")
|
||||||
stream.write(repr(object))
|
if object.maxlen is not None:
|
||||||
return
|
stream.write("maxlen=%d, " % object.maxlen)
|
||||||
cls = object.__class__
|
|
||||||
stream.write(cls.__name__ + "(")
|
|
||||||
indent += len(cls.__name__) + 1
|
|
||||||
stream.write("[")
|
stream.write("[")
|
||||||
if object.maxlen is None:
|
|
||||||
self._format_items(object, stream, indent, allowance + 2, context, level)
|
self._format_items(object, stream, indent, allowance + 1, context, level)
|
||||||
stream.write("])")
|
stream.write("])")
|
||||||
else:
|
|
||||||
self._format_items(object, stream, indent, 2, context, level)
|
|
||||||
rml = self._repr(object.maxlen, context, level)
|
|
||||||
stream.write(f"],\n{' ' * indent}maxlen={rml})")
|
|
||||||
|
|
||||||
_dispatch[_collections.deque.__repr__] = _pprint_deque
|
_dispatch[_collections.deque.__repr__] = _pprint_deque
|
||||||
|
|
||||||
|
|
|
@ -318,18 +318,6 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]:
|
||||||
return explanation
|
return explanation
|
||||||
|
|
||||||
|
|
||||||
def _surrounding_parens_on_own_lines(lines: List[str]) -> None:
|
|
||||||
"""Move opening/closing parenthesis/bracket to own lines."""
|
|
||||||
opening = lines[0][:1]
|
|
||||||
if opening in ["(", "[", "{"]:
|
|
||||||
lines[0] = " " + lines[0][1:]
|
|
||||||
lines[:] = [opening] + lines
|
|
||||||
closing = lines[-1][-1:]
|
|
||||||
if closing in [")", "]", "}"]:
|
|
||||||
lines[-1] = lines[-1][:-1] + ","
|
|
||||||
lines[:] = lines + [closing]
|
|
||||||
|
|
||||||
|
|
||||||
def _compare_eq_iterable(
|
def _compare_eq_iterable(
|
||||||
left: Iterable[Any],
|
left: Iterable[Any],
|
||||||
right: Iterable[Any],
|
right: Iterable[Any],
|
||||||
|
@ -341,20 +329,8 @@ def _compare_eq_iterable(
|
||||||
# dynamic import to speedup pytest
|
# dynamic import to speedup pytest
|
||||||
import difflib
|
import difflib
|
||||||
|
|
||||||
left_formatting = pprint.pformat(left).splitlines()
|
left_formatting = PrettyPrinter().pformat(left).splitlines()
|
||||||
right_formatting = pprint.pformat(right).splitlines()
|
right_formatting = PrettyPrinter().pformat(right).splitlines()
|
||||||
|
|
||||||
# Re-format for different output lengths.
|
|
||||||
lines_left = len(left_formatting)
|
|
||||||
lines_right = len(right_formatting)
|
|
||||||
if lines_left != lines_right:
|
|
||||||
printer = PrettyPrinter()
|
|
||||||
left_formatting = printer.pformat(left).splitlines()
|
|
||||||
right_formatting = printer.pformat(right).splitlines()
|
|
||||||
|
|
||||||
if lines_left > 1 or lines_right > 1:
|
|
||||||
_surrounding_parens_on_own_lines(left_formatting)
|
|
||||||
_surrounding_parens_on_own_lines(right_formatting)
|
|
||||||
|
|
||||||
explanation = ["Full diff:"]
|
explanation = ["Full diff:"]
|
||||||
# "right" is the expected base against which we compare "left",
|
# "right" is the expected base against which we compare "left",
|
||||||
|
|
|
@ -40,15 +40,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
DataclassWithOneItem(foo="bar"),
|
DataclassWithOneItem(foo="bar"),
|
||||||
"""
|
"""
|
||||||
DataclassWithOneItem(foo='bar')
|
DataclassWithOneItem(
|
||||||
|
foo='bar',
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
id="dataclass-one-item",
|
id="dataclass-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
DataclassWithTwoItems(foo="foo", bar="bar"),
|
DataclassWithTwoItems(foo="foo", bar="bar"),
|
||||||
"""
|
"""
|
||||||
DataclassWithTwoItems(foo='foo',
|
DataclassWithTwoItems(
|
||||||
bar='bar')
|
foo='foo',
|
||||||
|
bar='bar',
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
id="dataclass-two-items",
|
id="dataclass-two-items",
|
||||||
),
|
),
|
||||||
|
@ -60,15 +64,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
{"one": 1},
|
{"one": 1},
|
||||||
"""
|
"""
|
||||||
{'one': 1}
|
{
|
||||||
|
'one': 1,
|
||||||
|
}
|
||||||
""",
|
""",
|
||||||
id="dict-one-item",
|
id="dict-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
{"one": 1, "two": 2},
|
{"one": 1, "two": 2},
|
||||||
"""
|
"""
|
||||||
{'one': 1,
|
{
|
||||||
'two': 2}
|
'one': 1,
|
||||||
|
'two': 2,
|
||||||
|
}
|
||||||
""",
|
""",
|
||||||
id="dict-two-items",
|
id="dict-two-items",
|
||||||
),
|
),
|
||||||
|
@ -76,18 +84,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
OrderedDict({"one": 1}),
|
OrderedDict({"one": 1}),
|
||||||
"""
|
"""
|
||||||
OrderedDict([('one',
|
OrderedDict({
|
||||||
1)])
|
'one': 1,
|
||||||
|
})
|
||||||
""",
|
""",
|
||||||
id="ordereddict-one-item",
|
id="ordereddict-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
OrderedDict({"one": 1, "two": 2}),
|
OrderedDict({"one": 1, "two": 2}),
|
||||||
"""
|
"""
|
||||||
OrderedDict([('one',
|
OrderedDict({
|
||||||
1),
|
'one': 1,
|
||||||
('two',
|
'two': 2,
|
||||||
2)])
|
})
|
||||||
""",
|
""",
|
||||||
id="ordereddict-two-items",
|
id="ordereddict-two-items",
|
||||||
),
|
),
|
||||||
|
@ -99,15 +108,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
[1],
|
[1],
|
||||||
"""
|
"""
|
||||||
[1]
|
[
|
||||||
|
1,
|
||||||
|
]
|
||||||
""",
|
""",
|
||||||
id="list-one-item",
|
id="list-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
[1, 2],
|
[1, 2],
|
||||||
"""
|
"""
|
||||||
[1,
|
[
|
||||||
2]
|
1,
|
||||||
|
2,
|
||||||
|
]
|
||||||
""",
|
""",
|
||||||
id="list-two-items",
|
id="list-two-items",
|
||||||
),
|
),
|
||||||
|
@ -119,15 +132,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
(1,),
|
(1,),
|
||||||
"""
|
"""
|
||||||
(1,)
|
(
|
||||||
|
1,
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
id="tuple-one-item",
|
id="tuple-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
(1, 2),
|
(1, 2),
|
||||||
"""
|
"""
|
||||||
(1,
|
(
|
||||||
2)
|
1,
|
||||||
|
2,
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
id="tuple-two-items",
|
id="tuple-two-items",
|
||||||
),
|
),
|
||||||
|
@ -139,15 +156,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
{1},
|
{1},
|
||||||
"""
|
"""
|
||||||
{1}
|
{
|
||||||
|
1,
|
||||||
|
}
|
||||||
""",
|
""",
|
||||||
id="set-one-item",
|
id="set-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
{1, 2},
|
{1, 2},
|
||||||
"""
|
"""
|
||||||
{1,
|
{
|
||||||
2}
|
1,
|
||||||
|
2,
|
||||||
|
}
|
||||||
""",
|
""",
|
||||||
id="set-two-items",
|
id="set-two-items",
|
||||||
),
|
),
|
||||||
|
@ -159,15 +180,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
MappingProxyType({"one": 1}),
|
MappingProxyType({"one": 1}),
|
||||||
"""
|
"""
|
||||||
mappingproxy({'one': 1})
|
mappingproxy({
|
||||||
|
'one': 1,
|
||||||
|
})
|
||||||
""",
|
""",
|
||||||
id="mappingproxy-one-item",
|
id="mappingproxy-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
MappingProxyType({"one": 1, "two": 2}),
|
MappingProxyType({"one": 1, "two": 2}),
|
||||||
"""
|
"""
|
||||||
mappingproxy({'one': 1,
|
mappingproxy({
|
||||||
'two': 2})
|
'one': 1,
|
||||||
|
'two': 2,
|
||||||
|
})
|
||||||
""",
|
""",
|
||||||
id="mappingproxy-two-items",
|
id="mappingproxy-two-items",
|
||||||
),
|
),
|
||||||
|
@ -179,15 +204,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
SimpleNamespace(one=1),
|
SimpleNamespace(one=1),
|
||||||
"""
|
"""
|
||||||
namespace(one=1)
|
namespace(
|
||||||
|
one=1,
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
id="simplenamespace-one-item",
|
id="simplenamespace-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
SimpleNamespace(one=1, two=2),
|
SimpleNamespace(one=1, two=2),
|
||||||
"""
|
"""
|
||||||
namespace(one=1,
|
namespace(
|
||||||
two=2)
|
one=1,
|
||||||
|
two=2,
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
id="simplenamespace-two-items",
|
id="simplenamespace-two-items",
|
||||||
),
|
),
|
||||||
|
@ -197,17 +226,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
defaultdict(str, {"one": "1"}),
|
defaultdict(str, {"one": "1"}),
|
||||||
"""
|
"""
|
||||||
defaultdict(<class 'str'>,
|
defaultdict(<class 'str'>, {
|
||||||
{'one': '1'})
|
'one': '1',
|
||||||
|
})
|
||||||
""",
|
""",
|
||||||
id="defaultdict-one-item",
|
id="defaultdict-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
defaultdict(str, {"one": "1", "two": "2"}),
|
defaultdict(str, {"one": "1", "two": "2"}),
|
||||||
"""
|
"""
|
||||||
defaultdict(<class 'str'>,
|
defaultdict(<class 'str'>, {
|
||||||
{'one': '1',
|
'one': '1',
|
||||||
'two': '2'})
|
'two': '2',
|
||||||
|
})
|
||||||
""",
|
""",
|
||||||
id="defaultdict-two-items",
|
id="defaultdict-two-items",
|
||||||
),
|
),
|
||||||
|
@ -219,15 +250,19 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
Counter("1"),
|
Counter("1"),
|
||||||
"""
|
"""
|
||||||
Counter({'1': 1})
|
Counter({
|
||||||
|
'1': 1,
|
||||||
|
})
|
||||||
""",
|
""",
|
||||||
id="counter-one-item",
|
id="counter-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
Counter("121"),
|
Counter("121"),
|
||||||
"""
|
"""
|
||||||
Counter({'1': 2,
|
Counter({
|
||||||
'2': 1})
|
'1': 2,
|
||||||
|
'2': 1,
|
||||||
|
})
|
||||||
""",
|
""",
|
||||||
id="counter-two-items",
|
id="counter-two-items",
|
||||||
),
|
),
|
||||||
|
@ -235,16 +270,26 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
ChainMap({"one": 1, "two": 2}),
|
ChainMap({"one": 1, "two": 2}),
|
||||||
"""
|
"""
|
||||||
ChainMap({'one': 1,
|
ChainMap(
|
||||||
'two': 2})
|
{
|
||||||
|
'one': 1,
|
||||||
|
'two': 2,
|
||||||
|
},
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
id="chainmap-one-item",
|
id="chainmap-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
ChainMap({"one": 1}, {"two": 2}),
|
ChainMap({"one": 1}, {"two": 2}),
|
||||||
"""
|
"""
|
||||||
ChainMap({'one': 1},
|
ChainMap(
|
||||||
{'two': 2})
|
{
|
||||||
|
'one': 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'two': 2,
|
||||||
|
},
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
id="chainmap-two-items",
|
id="chainmap-two-items",
|
||||||
),
|
),
|
||||||
|
@ -256,24 +301,29 @@ class DataclassWithTwoItems:
|
||||||
pytest.param(
|
pytest.param(
|
||||||
deque([1]),
|
deque([1]),
|
||||||
"""
|
"""
|
||||||
deque([1])
|
deque([
|
||||||
|
1,
|
||||||
|
])
|
||||||
""",
|
""",
|
||||||
id="deque-one-item",
|
id="deque-one-item",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
deque([1, 2]),
|
deque([1, 2]),
|
||||||
"""
|
"""
|
||||||
deque([1,
|
deque([
|
||||||
2])
|
1,
|
||||||
|
2,
|
||||||
|
])
|
||||||
""",
|
""",
|
||||||
id="deque-two-items",
|
id="deque-two-items",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
deque([1, 2], maxlen=3),
|
deque([1, 2], maxlen=3),
|
||||||
"""
|
"""
|
||||||
deque([1,
|
deque(maxlen=3, [
|
||||||
2],
|
1,
|
||||||
maxlen=3)
|
2,
|
||||||
|
])
|
||||||
""",
|
""",
|
||||||
id="deque-maxlen",
|
id="deque-maxlen",
|
||||||
),
|
),
|
||||||
|
@ -293,34 +343,60 @@ class DataclassWithTwoItems:
|
||||||
"tuple": (1, 2),
|
"tuple": (1, 2),
|
||||||
},
|
},
|
||||||
"""
|
"""
|
||||||
{'chainmap': ChainMap({'one': 1},
|
{
|
||||||
{'two': 2}),
|
'chainmap': ChainMap(
|
||||||
'counter': Counter({'2': 2,
|
{
|
||||||
'1': 1}),
|
'one': 1,
|
||||||
'dataclass': DataclassWithTwoItems(foo='foo',
|
},
|
||||||
bar='bar'),
|
{
|
||||||
'defaultdict': defaultdict(<class 'str'>,
|
'two': 2,
|
||||||
{'one': '1',
|
},
|
||||||
'two': '2'}),
|
),
|
||||||
'deque': deque([1,
|
'counter': Counter({
|
||||||
2],
|
'2': 2,
|
||||||
maxlen=3),
|
'1': 1,
|
||||||
'dict': {'one': 1,
|
}),
|
||||||
'two': 2},
|
'dataclass': DataclassWithTwoItems(
|
||||||
'list': [1,
|
foo='foo',
|
||||||
2],
|
bar='bar',
|
||||||
'mappingproxy': mappingproxy({'one': 1,
|
),
|
||||||
'two': 2}),
|
'defaultdict': defaultdict(<class 'str'>, {
|
||||||
'ordereddict': OrderedDict([('one',
|
'one': '1',
|
||||||
1),
|
'two': '2',
|
||||||
('two',
|
}),
|
||||||
2)]),
|
'deque': deque(maxlen=3, [
|
||||||
'set': {1,
|
1,
|
||||||
2},
|
2,
|
||||||
'simplenamespace': namespace(one=1,
|
]),
|
||||||
two=2),
|
'dict': {
|
||||||
'tuple': (1,
|
'one': 1,
|
||||||
2)}
|
'two': 2,
|
||||||
|
},
|
||||||
|
'list': [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
'mappingproxy': mappingproxy({
|
||||||
|
'one': 1,
|
||||||
|
'two': 2,
|
||||||
|
}),
|
||||||
|
'ordereddict': OrderedDict({
|
||||||
|
'one': 1,
|
||||||
|
'two': 2,
|
||||||
|
}),
|
||||||
|
'set': {
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
},
|
||||||
|
'simplenamespace': namespace(
|
||||||
|
one=1,
|
||||||
|
two=2,
|
||||||
|
),
|
||||||
|
'tuple': (
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
}
|
||||||
""",
|
""",
|
||||||
id="deep-example",
|
id="deep-example",
|
||||||
),
|
),
|
||||||
|
|
|
@ -451,11 +451,14 @@ class TestAssert_reprcompare:
|
||||||
[0, 2],
|
[0, 2],
|
||||||
"""
|
"""
|
||||||
Full diff:
|
Full diff:
|
||||||
- [0, 2]
|
[
|
||||||
|
0,
|
||||||
|
- 2,
|
||||||
? ^
|
? ^
|
||||||
+ [0, 1]
|
+ 1,
|
||||||
? ^
|
? ^
|
||||||
""",
|
]
|
||||||
|
""",
|
||||||
id="lists",
|
id="lists",
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
|
@ -463,10 +466,12 @@ class TestAssert_reprcompare:
|
||||||
{0: 2},
|
{0: 2},
|
||||||
"""
|
"""
|
||||||
Full diff:
|
Full diff:
|
||||||
- {0: 2}
|
{
|
||||||
? ^
|
- 0: 2,
|
||||||
+ {0: 1}
|
? ^
|
||||||
? ^
|
+ 0: 1,
|
||||||
|
? ^
|
||||||
|
}
|
||||||
""",
|
""",
|
||||||
id="dicts",
|
id="dicts",
|
||||||
),
|
),
|
||||||
|
@ -475,10 +480,13 @@ class TestAssert_reprcompare:
|
||||||
{0, 2},
|
{0, 2},
|
||||||
"""
|
"""
|
||||||
Full diff:
|
Full diff:
|
||||||
- {0, 2}
|
{
|
||||||
|
0,
|
||||||
|
- 2,
|
||||||
? ^
|
? ^
|
||||||
+ {0, 1}
|
+ 1,
|
||||||
? ^
|
? ^
|
||||||
|
}
|
||||||
""",
|
""",
|
||||||
id="sets",
|
id="sets",
|
||||||
),
|
),
|
||||||
|
@ -542,10 +550,10 @@ class TestAssert_reprcompare:
|
||||||
"Right contains one more item: '" + long_d + "'",
|
"Right contains one more item: '" + long_d + "'",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
" [",
|
" [",
|
||||||
" 'a',",
|
" 'a',",
|
||||||
" 'b',",
|
" 'b',",
|
||||||
" 'c',",
|
" 'c',",
|
||||||
"- '" + long_d + "',",
|
"- '" + long_d + "',",
|
||||||
" ]",
|
" ]",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -555,10 +563,10 @@ class TestAssert_reprcompare:
|
||||||
"Left contains one more item: '" + long_d + "'",
|
"Left contains one more item: '" + long_d + "'",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
" [",
|
" [",
|
||||||
" 'a',",
|
" 'a',",
|
||||||
" 'b',",
|
" 'b',",
|
||||||
" 'c',",
|
" 'c',",
|
||||||
"+ '" + long_d + "',",
|
"+ '" + long_d + "',",
|
||||||
" ]",
|
" ]",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -574,10 +582,10 @@ class TestAssert_reprcompare:
|
||||||
"At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
|
"At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
" [",
|
" [",
|
||||||
"+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
|
"+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
|
||||||
" 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',",
|
" 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',",
|
||||||
" 'cccccccccccccccccccccccccccccc',",
|
" 'cccccccccccccccccccccccccccccc',",
|
||||||
"- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
|
"- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
|
||||||
" ]",
|
" ]",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -592,15 +600,15 @@ class TestAssert_reprcompare:
|
||||||
"Left contains 7 more items, first extra item: 'aaaaaaaaaa'",
|
"Left contains 7 more items, first extra item: 'aaaaaaaaaa'",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
" [",
|
" [",
|
||||||
"- 'should not get wrapped',",
|
"- 'should not get wrapped',",
|
||||||
"+ 'a',",
|
"+ 'a',",
|
||||||
"+ 'aaaaaaaaaa',",
|
"+ 'aaaaaaaaaa',",
|
||||||
"+ 'aaaaaaaaaa',",
|
"+ 'aaaaaaaaaa',",
|
||||||
"+ 'aaaaaaaaaa',",
|
"+ 'aaaaaaaaaa',",
|
||||||
"+ 'aaaaaaaaaa',",
|
"+ 'aaaaaaaaaa',",
|
||||||
"+ 'aaaaaaaaaa',",
|
"+ 'aaaaaaaaaa',",
|
||||||
"+ 'aaaaaaaaaa',",
|
"+ 'aaaaaaaaaa',",
|
||||||
"+ 'aaaaaaaaaa',",
|
"+ 'aaaaaaaaaa',",
|
||||||
" ]",
|
" ]",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -615,13 +623,17 @@ class TestAssert_reprcompare:
|
||||||
"Differing items:",
|
"Differing items:",
|
||||||
"{'env': {'env1': 1, 'env2': 2}} != {'env': {'env1': 1}}",
|
"{'env': {'env1': 1, 'env2': 2}} != {'env': {'env1': 1}}",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
"- {'common': 1, 'env': {'env1': 1}}",
|
" {",
|
||||||
"+ {'common': 1, 'env': {'env1': 1, 'env2': 2}}",
|
" 'common': 1,",
|
||||||
"? +++++++++++",
|
" 'env': {",
|
||||||
|
" 'env1': 1,",
|
||||||
|
"+ 'env2': 2,",
|
||||||
|
" },",
|
||||||
|
" }",
|
||||||
]
|
]
|
||||||
|
|
||||||
long_a = "a" * 80
|
long_a = "a" * 80
|
||||||
sub = {"long_a": long_a, "sub1": {"long_a": "substring that gets wrapped " * 2}}
|
sub = {"long_a": long_a, "sub1": {"long_a": "substring that gets wrapped " * 3}}
|
||||||
d1 = {"env": {"sub": sub}}
|
d1 = {"env": {"sub": sub}}
|
||||||
d2 = {"env": {"sub": sub}, "new": 1}
|
d2 = {"env": {"sub": sub}, "new": 1}
|
||||||
diff = callequal(d1, d2, verbose=True)
|
diff = callequal(d1, d2, verbose=True)
|
||||||
|
@ -632,10 +644,16 @@ class TestAssert_reprcompare:
|
||||||
"{'new': 1}",
|
"{'new': 1}",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
" {",
|
" {",
|
||||||
" 'env': {'sub': {'long_a': '" + long_a + "',",
|
" 'env': {",
|
||||||
" 'sub1': {'long_a': 'substring that gets wrapped substring '",
|
" 'sub': {",
|
||||||
" 'that gets wrapped '}}},",
|
f" 'long_a': '{long_a}',",
|
||||||
"- 'new': 1,",
|
" 'sub1': {",
|
||||||
|
" 'long_a': 'substring that gets wrapped substring that gets wrapped '",
|
||||||
|
" 'substring that gets wrapped ',",
|
||||||
|
" },",
|
||||||
|
" },",
|
||||||
|
" },",
|
||||||
|
"- 'new': 1,",
|
||||||
" }",
|
" }",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -677,8 +695,13 @@ class TestAssert_reprcompare:
|
||||||
"Right contains 2 more items:",
|
"Right contains 2 more items:",
|
||||||
"{'b': 1, 'c': 2}",
|
"{'b': 1, 'c': 2}",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
"- {'b': 1, 'c': 2}",
|
" {",
|
||||||
"+ {'a': 0}",
|
"- 'b': 1,",
|
||||||
|
"? ^ ^",
|
||||||
|
"+ 'a': 0,",
|
||||||
|
"? ^ ^",
|
||||||
|
"- 'c': 2,",
|
||||||
|
" }",
|
||||||
]
|
]
|
||||||
lines = callequal({"b": 1, "c": 2}, {"a": 0}, verbose=2)
|
lines = callequal({"b": 1, "c": 2}, {"a": 0}, verbose=2)
|
||||||
assert lines == [
|
assert lines == [
|
||||||
|
@ -688,8 +711,13 @@ class TestAssert_reprcompare:
|
||||||
"Right contains 1 more item:",
|
"Right contains 1 more item:",
|
||||||
"{'a': 0}",
|
"{'a': 0}",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
"- {'a': 0}",
|
" {",
|
||||||
"+ {'b': 1, 'c': 2}",
|
"- 'a': 0,",
|
||||||
|
"? ^ ^",
|
||||||
|
"+ 'b': 1,",
|
||||||
|
"? ^ ^",
|
||||||
|
"+ 'c': 2,",
|
||||||
|
" }",
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_sequence_different_items(self) -> None:
|
def test_sequence_different_items(self) -> None:
|
||||||
|
@ -699,8 +727,17 @@ class TestAssert_reprcompare:
|
||||||
"At index 0 diff: 1 != 3",
|
"At index 0 diff: 1 != 3",
|
||||||
"Right contains one more item: 5",
|
"Right contains one more item: 5",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
"- (3, 4, 5)",
|
" (",
|
||||||
"+ (1, 2)",
|
"- 3,",
|
||||||
|
"? ^",
|
||||||
|
"+ 1,",
|
||||||
|
"? ^",
|
||||||
|
"- 4,",
|
||||||
|
"? ^",
|
||||||
|
"+ 2,",
|
||||||
|
"? ^",
|
||||||
|
"- 5,",
|
||||||
|
" )",
|
||||||
]
|
]
|
||||||
lines = callequal((1, 2, 3), (4,), verbose=2)
|
lines = callequal((1, 2, 3), (4,), verbose=2)
|
||||||
assert lines == [
|
assert lines == [
|
||||||
|
@ -708,8 +745,27 @@ class TestAssert_reprcompare:
|
||||||
"At index 0 diff: 1 != 4",
|
"At index 0 diff: 1 != 4",
|
||||||
"Left contains 2 more items, first extra item: 2",
|
"Left contains 2 more items, first extra item: 2",
|
||||||
"Full diff:",
|
"Full diff:",
|
||||||
"- (4,)",
|
" (",
|
||||||
"+ (1, 2, 3)",
|
"- 4,",
|
||||||
|
"? ^",
|
||||||
|
"+ 1,",
|
||||||
|
"? ^",
|
||||||
|
"+ 2,",
|
||||||
|
"+ 3,",
|
||||||
|
" )",
|
||||||
|
]
|
||||||
|
lines = callequal((1, 2, 3), (1, 20, 3), verbose=2)
|
||||||
|
assert lines == [
|
||||||
|
"(1, 2, 3) == (1, 20, 3)",
|
||||||
|
"At index 1 diff: 2 != 20",
|
||||||
|
"Full diff:",
|
||||||
|
" (",
|
||||||
|
" 1,",
|
||||||
|
"- 20,",
|
||||||
|
"? -",
|
||||||
|
"+ 2,",
|
||||||
|
" 3,",
|
||||||
|
" )",
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_set(self) -> None:
|
def test_set(self) -> None:
|
||||||
|
@ -1844,8 +1900,8 @@ def test_reprcompare_verbose_long() -> None:
|
||||||
assert [0, 1] == [0, 2]
|
assert [0, 1] == [0, 2]
|
||||||
""",
|
""",
|
||||||
[
|
[
|
||||||
"{bold}{red}E {light-red}- [0, 2]{hl-reset}{endline}{reset}",
|
"{bold}{red}E {light-red}- 2,{hl-reset}{endline}{reset}",
|
||||||
"{bold}{red}E {light-green}+ [0, 1]{hl-reset}{endline}{reset}",
|
"{bold}{red}E {light-green}+ 1,{hl-reset}{endline}{reset}",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -1857,8 +1913,8 @@ def test_reprcompare_verbose_long() -> None:
|
||||||
""",
|
""",
|
||||||
[
|
[
|
||||||
"{bold}{red}E {light-gray} {hl-reset} {{{endline}{reset}",
|
"{bold}{red}E {light-gray} {hl-reset} {{{endline}{reset}",
|
||||||
"{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}",
|
"{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}",
|
||||||
"{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}",
|
"{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1917,14 +1973,32 @@ def test_fine_grained_assertion_verbosity(pytester: Pytester):
|
||||||
f"{p.name} .FFF [100%]",
|
f"{p.name} .FFF [100%]",
|
||||||
"E At index 2 diff: 'grapes' != 'orange'",
|
"E At index 2 diff: 'grapes' != 'orange'",
|
||||||
"E Full diff:",
|
"E Full diff:",
|
||||||
"E - ['banana', 'apple', 'orange', 'melon', 'kiwi']",
|
"E [",
|
||||||
"E ? ^ ^^",
|
"E 'banana',",
|
||||||
"E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']",
|
"E 'apple',",
|
||||||
"E ? ^ ^ +",
|
"E - 'orange',",
|
||||||
|
"E ? ^ ^^",
|
||||||
|
"E + 'grapes',",
|
||||||
|
"E ? ^ ^ +",
|
||||||
|
"E 'melon',",
|
||||||
|
"E 'kiwi',",
|
||||||
|
"E ]",
|
||||||
"E Full diff:",
|
"E Full diff:",
|
||||||
"E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}",
|
"E {",
|
||||||
"E ? - - - - - - - -",
|
"E '0': 0,",
|
||||||
"E + {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}",
|
"E - '10': 10,",
|
||||||
|
"E ? - -",
|
||||||
|
"E + '1': 1,",
|
||||||
|
"E - '20': 20,",
|
||||||
|
"E ? - -",
|
||||||
|
"E + '2': 2,",
|
||||||
|
"E - '30': 30,",
|
||||||
|
"E ? - -",
|
||||||
|
"E + '3': 3,",
|
||||||
|
"E - '40': 40,",
|
||||||
|
"E ? - -",
|
||||||
|
"E + '4': 4,",
|
||||||
|
"E }",
|
||||||
f"E AssertionError: assert 'hello world' in '{long_text}'",
|
f"E AssertionError: assert 'hello world' in '{long_text}'",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,10 +21,14 @@ TESTCASES = [
|
||||||
E assert [1, 4, 3] == [1, 2, 3]
|
E assert [1, 4, 3] == [1, 2, 3]
|
||||||
E At index 1 diff: 4 != 2
|
E At index 1 diff: 4 != 2
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - [1, 2, 3]
|
E [
|
||||||
|
E 1,
|
||||||
|
E - 2,
|
||||||
E ? ^
|
E ? ^
|
||||||
E + [1, 4, 3]
|
E + 4,
|
||||||
E ? ^
|
E ? ^
|
||||||
|
E 3,
|
||||||
|
E ]
|
||||||
""",
|
""",
|
||||||
id="Compare lists, one item differs",
|
id="Compare lists, one item differs",
|
||||||
),
|
),
|
||||||
|
@ -40,9 +44,11 @@ TESTCASES = [
|
||||||
E assert [1, 2, 3] == [1, 2]
|
E assert [1, 2, 3] == [1, 2]
|
||||||
E Left contains one more item: 3
|
E Left contains one more item: 3
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - [1, 2]
|
E [
|
||||||
E + [1, 2, 3]
|
E 1,
|
||||||
E ? +++
|
E 2,
|
||||||
|
E + 3,
|
||||||
|
E ]
|
||||||
""",
|
""",
|
||||||
id="Compare lists, one extra item",
|
id="Compare lists, one extra item",
|
||||||
),
|
),
|
||||||
|
@ -59,9 +65,11 @@ TESTCASES = [
|
||||||
E At index 1 diff: 3 != 2
|
E At index 1 diff: 3 != 2
|
||||||
E Right contains one more item: 3
|
E Right contains one more item: 3
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - [1, 2, 3]
|
E [
|
||||||
E ? ---
|
E 1,
|
||||||
E + [1, 3]
|
E - 2,
|
||||||
|
E 3,
|
||||||
|
E ]
|
||||||
""",
|
""",
|
||||||
id="Compare lists, one item missing",
|
id="Compare lists, one item missing",
|
||||||
),
|
),
|
||||||
|
@ -77,10 +85,14 @@ TESTCASES = [
|
||||||
E assert (1, 4, 3) == (1, 2, 3)
|
E assert (1, 4, 3) == (1, 2, 3)
|
||||||
E At index 1 diff: 4 != 2
|
E At index 1 diff: 4 != 2
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - (1, 2, 3)
|
E (
|
||||||
|
E 1,
|
||||||
|
E - 2,
|
||||||
E ? ^
|
E ? ^
|
||||||
E + (1, 4, 3)
|
E + 4,
|
||||||
E ? ^
|
E ? ^
|
||||||
|
E 3,
|
||||||
|
E )
|
||||||
""",
|
""",
|
||||||
id="Compare tuples",
|
id="Compare tuples",
|
||||||
),
|
),
|
||||||
|
@ -99,10 +111,12 @@ TESTCASES = [
|
||||||
E Extra items in the right set:
|
E Extra items in the right set:
|
||||||
E 2
|
E 2
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - {1, 2, 3}
|
E {
|
||||||
E ? ^ ^
|
E 1,
|
||||||
E + {1, 3, 4}
|
E - 2,
|
||||||
E ? ^ ^
|
E 3,
|
||||||
|
E + 4,
|
||||||
|
E }
|
||||||
""",
|
""",
|
||||||
id="Compare sets",
|
id="Compare sets",
|
||||||
),
|
),
|
||||||
|
@ -123,10 +137,13 @@ TESTCASES = [
|
||||||
E Right contains 1 more item:
|
E Right contains 1 more item:
|
||||||
E {2: 'eggs'}
|
E {2: 'eggs'}
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - {1: 'spam', 2: 'eggs'}
|
E {
|
||||||
E ? ^
|
E 1: 'spam',
|
||||||
E + {1: 'spam', 3: 'eggs'}
|
E - 2: 'eggs',
|
||||||
E ? ^
|
E ? ^
|
||||||
|
E + 3: 'eggs',
|
||||||
|
E ? ^
|
||||||
|
E }
|
||||||
""",
|
""",
|
||||||
id="Compare dicts with differing keys",
|
id="Compare dicts with differing keys",
|
||||||
),
|
),
|
||||||
|
@ -145,10 +162,11 @@ TESTCASES = [
|
||||||
E Differing items:
|
E Differing items:
|
||||||
E {2: 'eggs'} != {2: 'bacon'}
|
E {2: 'eggs'} != {2: 'bacon'}
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - {1: 'spam', 2: 'bacon'}
|
E {
|
||||||
E ? ^^^^^
|
E 1: 'spam',
|
||||||
E + {1: 'spam', 2: 'eggs'}
|
E - 2: 'bacon',
|
||||||
E ? ^^^^
|
E + 2: 'eggs',
|
||||||
|
E }
|
||||||
""",
|
""",
|
||||||
id="Compare dicts with differing values",
|
id="Compare dicts with differing values",
|
||||||
),
|
),
|
||||||
|
@ -169,10 +187,11 @@ TESTCASES = [
|
||||||
E Right contains 1 more item:
|
E Right contains 1 more item:
|
||||||
E {3: 'bacon'}
|
E {3: 'bacon'}
|
||||||
E Full diff:
|
E Full diff:
|
||||||
E - {1: 'spam', 3: 'bacon'}
|
E {
|
||||||
E ? ^ ^^^^^
|
E 1: 'spam',
|
||||||
E + {1: 'spam', 2: 'eggs'}
|
E - 3: 'bacon',
|
||||||
E ? ^ ^^^^
|
E + 2: 'eggs',
|
||||||
|
E }
|
||||||
""",
|
""",
|
||||||
id="Compare dicts with differing items",
|
id="Compare dicts with differing items",
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue