diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index 7704421a22e..6e4207cbb0b 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -46,13 +46,13 @@ def repr_instance(self, x, level): return _ellipsize(s, self.maxsize) -def safeformat(obj): +def safeformat(obj, **kwargs): """return a pretty printed string for the given object. Failing __repr__ functions of user instances will be represented with a short exception info. """ try: - return pprint.pformat(obj) + return pprint.pformat(obj, **kwargs) except Exception as exc: return _format_repr_exception(exc, obj) diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index 3b42b356d5b..5c4405f1ff3 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -141,6 +141,17 @@ def callbinrepr(op, left, right): util._reprcompare = callbinrepr + from _pytest._io.saferepr import safeformat + from _pytest._io.saferepr import saferepr + + def call_assertion_display_hook(obj): + verbose = item.config.getoption("verbose") + if verbose > 1: + return safeformat(obj, compact=True).replace("\n", "\n~") + return saferepr(obj).replace("\n", "\\n") + + util._reprdisplay = call_assertion_display_hook + if item.ihook.pytest_assertion_pass.get_hookimpls(): def call_assertion_pass_hook(lineno, orig, expl): @@ -153,6 +164,7 @@ def call_assertion_pass_hook(lineno, orig, expl): def pytest_runtest_teardown(item): util._reprcompare = None + util._reprdisplay = None util._assertion_pass = None diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index c225eff5fb5..92194f677cc 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -398,6 +398,13 @@ def _call_reprcompare(ops, results, expls, each_obj): return expl +def _call_reprdisplay(obj): + if util._reprdisplay is not None: + return util._reprdisplay(obj) + # XXX: happens/used with testing/test_assertion.py::TestImportHookInstallation::test_rewrite_assertions_pytester_plugin # noqa: E501 + return _saferepr(obj) + + def _call_assertion_pass(lineno, orig, expl): # type: (int, str, str) -> None if util._assertion_pass is not None: @@ -662,8 +669,7 @@ def assign(self, expr): return ast.Name(name, ast.Load()) def display(self, expr): - """Call saferepr on the expression.""" - return self.helper("_saferepr", expr) + return self.helper("_call_reprdisplay", expr) def helper(self, name, *args): """Call a helper in this module."""