91 lines
2.9 KiB
Python
91 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable
|
|
from collections.abc import Iterator
|
|
from collections.abc import Sequence
|
|
|
|
from _pytest._io.pprint import PrettyPrinter
|
|
from _pytest._io.saferepr import saferepr
|
|
from _pytest.assertion._typing import _HighlightFunc
|
|
from _pytest.compat import running_on_ci
|
|
|
|
|
|
def _compare_eq_iterable(
|
|
left: Iterable[object],
|
|
right: Iterable[object],
|
|
highlighter: _HighlightFunc,
|
|
verbose: int = 0,
|
|
) -> Iterator[str]:
|
|
if verbose <= 0 and not running_on_ci():
|
|
yield "Use -v to get more diff"
|
|
return
|
|
# dynamic import to speedup pytest
|
|
import difflib
|
|
|
|
left_formatting = PrettyPrinter().pformat(left).splitlines()
|
|
right_formatting = PrettyPrinter().pformat(right).splitlines()
|
|
|
|
yield ""
|
|
yield "Full diff:"
|
|
# "right" is the expected base against which we compare "left",
|
|
# see https://github.com/pytest-dev/pytest/issues/3333
|
|
yield from highlighter(
|
|
"\n".join(
|
|
line.rstrip() for line in difflib.ndiff(right_formatting, left_formatting)
|
|
),
|
|
lexer="diff",
|
|
).splitlines()
|
|
|
|
|
|
def _compare_eq_sequence(
|
|
left: Sequence[object],
|
|
right: Sequence[object],
|
|
highlighter: _HighlightFunc,
|
|
verbose: int = 0,
|
|
) -> Iterator[str]:
|
|
comparing_bytes = isinstance(left, bytes) and isinstance(right, bytes)
|
|
len_left = len(left)
|
|
len_right = len(right)
|
|
for i in range(min(len_left, len_right)):
|
|
if left[i] != right[i]:
|
|
if comparing_bytes:
|
|
# when comparing bytes, we want to see their ascii representation
|
|
# instead of their numeric values (#5260)
|
|
# using a slice gives us the ascii representation:
|
|
# >>> s = b'foo'
|
|
# >>> s[0]
|
|
# 102
|
|
# >>> s[0:1]
|
|
# b'f'
|
|
left_value: object = left[i : i + 1]
|
|
right_value: object = right[i : i + 1]
|
|
else:
|
|
left_value = left[i]
|
|
right_value = right[i]
|
|
|
|
yield (
|
|
f"At index {i} diff:"
|
|
f" {highlighter(repr(left_value))} != {highlighter(repr(right_value))}"
|
|
)
|
|
break
|
|
|
|
if comparing_bytes:
|
|
# when comparing bytes, it doesn't help to show the "sides contain one or more
|
|
# items" longer explanation, so skip it
|
|
return
|
|
|
|
len_diff = len_left - len_right
|
|
if len_diff:
|
|
if len_diff > 0:
|
|
dir_with_more = "Left"
|
|
extra = saferepr(left[len_right])
|
|
else:
|
|
len_diff = 0 - len_diff
|
|
dir_with_more = "Right"
|
|
extra = saferepr(right[len_left])
|
|
|
|
if len_diff == 1:
|
|
yield f"{dir_with_more} contains one more item: {highlighter(extra)}"
|
|
else:
|
|
yield f"{dir_with_more} contains {len_diff} more items, first extra item: {highlighter(extra)}"
|