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