Remove newlines from left/right operands with '-vv' (#9743)
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 #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>
This commit is contained in:
parent
eb22339dc3
commit
b75cbee290
1
AUTHORS
1
AUTHORS
|
@ -289,6 +289,7 @@ Ruaridh Williamson
|
|||
Russel Winder
|
||||
Ryan Wooden
|
||||
Saiprasad Kale
|
||||
Samuel Colvin
|
||||
Samuel Dion-Girardeau
|
||||
Samuel Searles-Bryant
|
||||
Samuele Pedroni
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Display assertion message without escaped newline characters with ``-vv``.
|
|
@ -107,6 +107,23 @@ def saferepr(obj: object, maxsize: Optional[int] = DEFAULT_REPR_MAX_SIZE) -> str
|
|||
return SafeRepr(maxsize).repr(obj)
|
||||
|
||||
|
||||
def saferepr_unlimited(obj: object) -> str:
|
||||
"""Return an unlimited-size safe repr-string for the given object.
|
||||
|
||||
As with saferepr, failing __repr__ functions of user instances
|
||||
will be represented with a short exception info.
|
||||
|
||||
This function is a wrapper around simple repr.
|
||||
|
||||
Note: a cleaner solution would be to alter ``saferepr``this way
|
||||
when maxsize=None, but that might affect some other code.
|
||||
"""
|
||||
try:
|
||||
return repr(obj)
|
||||
except Exception as exc:
|
||||
return _format_repr_exception(exc, obj)
|
||||
|
||||
|
||||
class AlwaysDispatchingPrettyPrinter(pprint.PrettyPrinter):
|
||||
"""PrettyPrinter that always dispatches (regardless of width)."""
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ from typing import Sequence
|
|||
import _pytest._code
|
||||
from _pytest import outcomes
|
||||
from _pytest._io.saferepr import _pformat_dispatch
|
||||
from _pytest._io.saferepr import safeformat
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest._io.saferepr import saferepr_unlimited
|
||||
from _pytest.config import Config
|
||||
|
||||
# The _reprcompare attribute on the util module is used by the new assertion
|
||||
|
@ -160,8 +160,8 @@ def assertrepr_compare(config, op: str, left: Any, right: Any) -> Optional[List[
|
|||
"""Return specialised explanations for some operators/operands."""
|
||||
verbose = config.getoption("verbose")
|
||||
if verbose > 1:
|
||||
left_repr = safeformat(left)
|
||||
right_repr = safeformat(right)
|
||||
left_repr = saferepr_unlimited(left)
|
||||
right_repr = saferepr_unlimited(right)
|
||||
else:
|
||||
# XXX: "15 chars indentation" is wrong
|
||||
# ("E AssertionError: assert "); should use term width.
|
||||
|
|
|
@ -2,6 +2,7 @@ import pytest
|
|||
from _pytest._io.saferepr import _pformat_dispatch
|
||||
from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest._io.saferepr import saferepr_unlimited
|
||||
|
||||
|
||||
def test_simple_repr():
|
||||
|
@ -179,3 +180,23 @@ def test_broken_getattribute():
|
|||
assert saferepr(SomeClass()).startswith(
|
||||
"<[RuntimeError() raised in repr()] SomeClass object at 0x"
|
||||
)
|
||||
|
||||
|
||||
def test_saferepr_unlimited():
|
||||
dict5 = {f"v{i}": i for i in range(5)}
|
||||
assert saferepr_unlimited(dict5) == "{'v0': 0, 'v1': 1, 'v2': 2, 'v3': 3, 'v4': 4}"
|
||||
|
||||
dict_long = {f"v{i}": i for i in range(1_000)}
|
||||
r = saferepr_unlimited(dict_long)
|
||||
assert "..." not in r
|
||||
assert "\n" not in r
|
||||
|
||||
|
||||
def test_saferepr_unlimited_exc():
|
||||
class A:
|
||||
def __repr__(self):
|
||||
raise ValueError(42)
|
||||
|
||||
assert saferepr_unlimited(A()).startswith(
|
||||
"<[ValueError(42) raised in repr()] A object at 0x"
|
||||
)
|
||||
|
|
|
@ -1695,3 +1695,18 @@ def test_assertion_location_with_coverage(pytester: Pytester) -> None:
|
|||
"*= 1 failed in*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_reprcompare_verbose_long() -> None:
|
||||
a = {f"v{i}": i for i in range(11)}
|
||||
b = a.copy()
|
||||
b["v2"] += 10
|
||||
lines = callop("==", a, b, verbose=2)
|
||||
assert lines is not None
|
||||
assert lines[0] == (
|
||||
"{'v0': 0, 'v1': 1, 'v2': 2, 'v3': 3, 'v4': 4, 'v5': 5, "
|
||||
"'v6': 6, 'v7': 7, 'v8': 8, 'v9': 9, 'v10': 10}"
|
||||
" == "
|
||||
"{'v0': 0, 'v1': 1, 'v2': 12, 'v3': 3, 'v4': 4, 'v5': 5, "
|
||||
"'v6': 6, 'v7': 7, 'v8': 8, 'v9': 9, 'v10': 10}"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue