Skip to content

Remove newlines from left/right operands with '-vv'#9743

Merged
nicoddemus merged 4 commits into
pytest-dev:mainfrom
samuelcolvin:repr-9742
Mar 19, 2022
Merged

Remove newlines from left/right operands with '-vv'#9743
nicoddemus merged 4 commits into
pytest-dev:mainfrom
samuelcolvin:repr-9742

Conversation

@samuelcolvin
Copy link
Copy Markdown
Member

@samuelcolvin samuelcolvin commented Mar 8, 2022

fix #9742

I've done this in the least intrusive way possible, a cleaner solution would be to alter saferepr to behave like the new saferepr_unlimited method when maxsize=None, but that might effect some other code (though I think use of saferepr() with maxsize=None is very rare).

@samuelcolvin samuelcolvin changed the title improve -vv repr improve -vv AssertionError message Mar 8, 2022
@Zac-HD
Copy link
Copy Markdown
Member

Zac-HD commented Mar 15, 2022

Thanks @samuelcolvin - this looks good to me, though I'll leave merging to another maintainer to be sure 🙂

@nicoddemus
Copy link
Copy Markdown
Member

Here's the output of main:

 λ pytest .tmp\test_foo.py -vv --no-header
======================== test session starts ========================
collected 1 item

.tmp\test_foo.py::test_foobar FAILED                           [100%]

============================= FAILURES ==============================
____________________________ test_foobar ____________________________

    def test_foobar():
        a = {string.ascii_letters[i]: i for i in range(26)}
        b = a.copy()
        a.pop('g')
>       assert a == b
E       AssertionError: assert {'a': 0,\n 'b': 1,\n 'c': 2,\n 'd': 3,\n 'e': 4,\n 'f': 5,\n 'h': 7,\n 'i': 8,\n 'j': 9,\n 'k': 10,\n 'l': 11,\n 'm': 12,\n 'n': 13,\n 'o': 14,\n 'p': 15,\n 'q': 16,\n 'r': 17,\n 's': 18,\n 't': 19,\n 'u': 20,\n 'v': 21,\n 'w': 22,\n 'x': 23,\n 'y': 24,\n 'z': 25} == {'a': 0,\n 'b': 1,\n 'c': 2,\n 'd': 3,\n 'e': 4,\n 'f': 5,\n 'g': 6,\n 'h': 7,\n 'i': 8,\n 'j': 9,\n 'k': 10,\n 'l': 11,\n 'm': 12,\n 'n': 13,\n 'o': 14,\n 'p': 15,\n 'q': 16,\n 'r': 17,\n 's': 18,\n 't': 19,\n 'u': 20,\n 'v': 21,\n 'w': 22,\n 'x': 23,\n 'y': 24,\n 'z': 25}
E         Common items:
E         {'a': 0,
E          'b': 1,
E          'c': 2,
E          'd': 3,
E          'e': 4,
E          'f': 5,
E          'h': 7,
E          'i': 8,
E          'j': 9,
E          'k': 10,
E          'l': 11,
E          'm': 12,
E          'n': 13,
E          'o': 14,
E          'p': 15,
E          'q': 16,
E          'r': 17,
E          's': 18,
E          't': 19,
E          'u': 20,
E          'v': 21,
E          'w': 22,
E          'x': 23,
E          'y': 24,
E          'z': 25}
E         Right contains 1 more item:
E         {'g': 6}
E         Full diff:
E           {
E            'a': 0,
E            'b': 1,
E            'c': 2,
E            'd': 3,
E            'e': 4,
E            'f': 5,
E         -  'g': 6,
E            'h': 7,
E            'i': 8,
E            'j': 9,
E            'k': 10,
E            'l': 11,
E            'm': 12,
E            'n': 13,
E            'o': 14,
E            'p': 15,
E            'q': 16,
E            'r': 17,
E            's': 18,
E            't': 19,
E            'u': 20,
E            'v': 21,
E            'w': 22,
E            'x': 23,
E            'y': 24,
E            'z': 25,
E           }

.tmp\test_foo.py:8: AssertionError
====================== short test summary info ======================
FAILED .tmp\test_foo.py::test_foobar - AssertionError: assert {'a':...
========================= 1 failed in 0.11s =========================

And here's the output of this PR:

λ pytest .tmp\test_foo.py -vv --no-header
======================== test session starts ========================
collected 1 item

.tmp\test_foo.py::test_foobar FAILED                           [100%]

============================= FAILURES ==============================
____________________________ test_foobar ____________________________

    def test_foobar():
        a = {string.ascii_letters[i]: i for i in range(26)}
        b = a.copy()
        a.pop('g')
>       assert a == b
E       AssertionError: assert {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25} == {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25}
E         Common items:
E         {'a': 0,
E          'b': 1,
E          'c': 2,
E          'd': 3,
E          'e': 4,
E          'f': 5,
E          'h': 7,
E          'i': 8,
E          'j': 9,
E          'k': 10,
E          'l': 11,
E          'm': 12,
E          'n': 13,
E          'o': 14,
E          'p': 15,
E          'q': 16,
E          'r': 17,
E          's': 18,
E          't': 19,
E          'u': 20,
E          'v': 21,
E          'w': 22,
E          'x': 23,
E          'y': 24,
E          'z': 25}
E         Right contains 1 more item:
E         {'g': 6}
E         Full diff:
E           {
E            'a': 0,
E            'b': 1,
E            'c': 2,
E            'd': 3,
E            'e': 4,
E            'f': 5,
E         -  'g': 6,
E            'h': 7,
E            'i': 8,
E            'j': 9,
E            'k': 10,
E            'l': 11,
E            'm': 12,
E            'n': 13,
E            'o': 14,
E            'p': 15,
E            'q': 16,
E            'r': 17,
E            's': 18,
E            't': 19,
E            'u': 20,
E            'v': 21,
E            'w': 22,
E            'x': 23,
E            'y': 24,
E            'z': 25,
E           }

.tmp\test_foo.py:8: AssertionError
====================== short test summary info ======================
FAILED .tmp\test_foo.py::test_foobar - AssertionError: assert {'a':...
========================= 1 failed in 0.09s =========================

So clearly an improvement! 👍

Copy link
Copy Markdown
Member

@nicoddemus nicoddemus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @samuelcolvin, appreciate a lot the PR! Very clean work. 👍

if verbose > 1:
left_repr = safeformat(left)
right_repr = safeformat(right)
left_repr = saferepr_unlimited(left)
Copy link
Copy Markdown
Member

@nicoddemus nicoddemus Mar 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed using safeformat for the left and right operands when verbose > 1 is not what is expected, because safeformat introduces newlines, and the result of assertrepr_compare is expected to be a list of lines; the string produced by safeformat (containing \n) is put as a single string in the result, which causes them to be escaped by the terminal later (I assume).

So the fix is entirely correct: use repr to produce the representation without \n, which is used to build the summary variable which is expected to be a single line.

@nicoddemus nicoddemus changed the title improve -vv AssertionError message Remove newlines from left/right operands with '-vv' Mar 19, 2022
@nicoddemus nicoddemus enabled auto-merge (squash) March 19, 2022 11:44
@nicoddemus nicoddemus merged commit b75cbee into pytest-dev:main Mar 19, 2022
@samuelcolvin samuelcolvin deleted the repr-9742 branch March 19, 2022 19:36
imgbot Bot pushed a commit to kkipngenokoech/pytest that referenced this pull request Apr 18, 2026
The left/right operands produced when `verbose > 1` should not contain newlines, because they are used to 
build the `summary` string. The `assertrepr_compare` function returns a list of lines, and the summary is one of those lines and should not contain newlines itself. 

Fix pytest-dev#9742

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
imgbot Bot pushed a commit to kkipngenokoech/pytest that referenced this pull request Apr 18, 2026
The left/right operands produced when `verbose > 1` should not contain newlines, because they are used to 
build the `summary` string. The `assertrepr_compare` function returns a list of lines, and the summary is one of those lines and should not contain newlines itself. 

Fix pytest-dev#9742

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AssertionError message contains unnecessary newline characters in verbose mode

3 participants