Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full diff issue #11688

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions AUTHORS
Expand Up @@ -180,6 +180,7 @@ Jake VanderPlas
Jakob van Santen
Jakub Mitoraj
James Bourbeau
Jamie Chen
Jan Balster
Janne Vanhala
Jason R. Coombs
Expand All @@ -206,6 +207,7 @@ Justice Ndou
Justyna Janczyszyn
Kale Kundert
Kamran Ahmad
Kaylin Yeoh
Kenny Y
Karl O. Pinc
Karthikeyan Singaravelan
Expand Down
4 changes: 4 additions & 0 deletions changelog/10863.bugfix.rst
@@ -0,0 +1,4 @@
Found source causes multiline string diff error
Added private functions to check specific cases
Fixed output issue with implicit concatonated strings
Added tests in test assertion file in function test_multiline_diff
51 changes: 49 additions & 2 deletions src/_pytest/assertion/util.py
Expand Up @@ -12,6 +12,7 @@
from typing import Optional
from typing import Protocol
from typing import Sequence
from typing import Tuple
from unicodedata import normalize

import _pytest._code
Expand Down Expand Up @@ -331,8 +332,17 @@
# dynamic import to speedup pytest
import difflib

left_formatting = PrettyPrinter().pformat(left).splitlines()
right_formatting = PrettyPrinter().pformat(right).splitlines()
if _is_empty_vs_non_empty(left, right):
left_formatting, right_formatting = _format_for_empty_and_non_empty(left, right)
lines_left = len(left_formatting)
lines_right = len(right_formatting)

if lines_left > 1 or lines_right > 1:
_surrounding_parens_on_own_lines(left_formatting)
_surrounding_parens_on_own_lines(right_formatting)
else:
left_formatting = PrettyPrinter().pformat(left).splitlines()
right_formatting = PrettyPrinter().pformat(right).splitlines()

explanation = ["", "Full diff:"]
# "right" is the expected base against which we compare "left",
Expand All @@ -349,6 +359,43 @@
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 _is_empty_vs_non_empty(left: Iterable[Any], right: Iterable[Any]) -> bool:
is_left_empty = not any(left) if isinstance(left, Iterable) else not left
is_right_empty = not any(right) if isinstance(right, Iterable) else not right
return (is_left_empty and not is_right_empty) or (
not is_left_empty and is_right_empty
)


def _format_for_empty_and_non_empty(
left: Iterable[Any], right: Iterable[Any]
) -> Tuple[List[str], List[str]]:
if isinstance(left, (list, tuple)) and isinstance(right, (list, tuple)):
if not left:
right_width = max(len(s) + 4 for s in right)
right_formatting = pprint.pformat(right, width=right_width).splitlines()
left_formatting = pprint.pformat(left).splitlines()

Check warning on line 389 in src/_pytest/assertion/util.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/assertion/util.py#L388-L389

Added lines #L388 - L389 were not covered by tests
else:
left_width = max(len(s) + 4 for s in left)
left_formatting = pprint.pformat(left, width=left_width).splitlines()
right_formatting = pprint.pformat(right).splitlines()
return left_formatting, right_formatting
else:
return pprint.pformat(left).splitlines(), pprint.pformat(right).splitlines()

Check warning on line 396 in src/_pytest/assertion/util.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/assertion/util.py#L396

Added line #L396 was not covered by tests


def _compare_eq_sequence(
left: Sequence[Any], right: Sequence[Any], verbose: int = 0
) -> List[str]:
Expand Down
83 changes: 83 additions & 0 deletions testing/test_assertion.py
Expand Up @@ -397,6 +397,89 @@ def test_text_diff(self) -> None:
"+ spam",
]

def test_multiline_diff(self) -> None:
m1 = [
"This is some dummy test which shows the strange way in which Pycharm"
" displays the full diff."
]
m2 = [
"This is some dummy test which shows the strange way in which Pycharm"
" displays the full diff.This is some dummy test which shows the strange way in which Pycharm"
" displays the full diff."
]
m3 = [
"This is some dummy test which shows the strange way in which Pycharm"
" displays the full diff.",
"This is some dummy test which shows the strange way in which Pycharm"
" displays the full diff.",
]

assert callequal(m1, []) == [
"['This is som...e full diff.'] == []",
"",
"Left contains one more item: 'This is some dummy test which shows the "
"strange way in which Pycharm displays the full diff.'",
"Use -v to get more diff",
]
assert callequal(m1, [], verbose=True) == [
"['This is som...e full diff.'] == []",
"",
"Left contains one more item: 'This is some dummy test which shows the "
"strange way in which Pycharm displays the full diff.'",
"",
"Full diff:",
"- []",
"+ ['This is some dummy test which shows the strange way in which Pycharm "
"displays the full diff.']",
]

assert callequal(m2, []) == [
"['This is som...e full diff.'] == []",
"",
"Left contains one more item: 'This is some dummy test which shows the "
"strange way in which Pycharm displays the full diff.This is some dummy test "
"which shows the strange way in which Pycharm displays the full diff.'",
"Use -v to get more diff",
]

assert callequal(m2, [], verbose=True) == [
"['This is som...e full diff.'] == []",
"",
"Left contains one more item: 'This is some dummy test which shows the "
"strange way in which Pycharm displays the full diff.This is some dummy test "
"which shows the strange way in which Pycharm displays the full diff.'",
"" "",
"Full diff:",
"- []",
"+ ['This is some dummy test which shows the strange way in which Pycharm "
"displays the full diff.This is some dummy test which shows the strange "
"way in which Pycharm displays the full diff.']",
]

assert callequal(m3, []) == [
"['This is som...e full diff.'] == []",
"",
"Left contains 2 more items, first extra item: 'This is some dummy test which shows the strange way in "
"which Pycharm displays the full diff.'",
"" "Use -v to get more diff",
]

assert callequal(m3, [], verbose=True) == [
"['This is som...e full diff.'] == []",
"",
"Left contains 2 more items, first extra item: 'This is some dummy test which shows the strange way in "
"which Pycharm displays the full diff.'",
"",
"Full diff:",
" [",
"- ,",
"+ 'This is some dummy test which shows the strange way in which Pycharm "
"displays the full diff.',",
"+ 'This is some dummy test which shows the strange way in which Pycharm "
"displays the full diff.',",
" ]",
]

def test_text_skipping(self) -> None:
lines = callequal("a" * 50 + "spam", "a" * 50 + "eggs")
assert lines is not None
Expand Down