Merge the AlwaysDispathPrettyPrinter into the now vendored PrettyPrinter

We don't need to keep the separation anymore, and this will make it
easier to extend
This commit is contained in:
Benjamin Schubert 2023-11-18 09:07:00 +00:00
parent 2953120003
commit 19934b2b0c
5 changed files with 34 additions and 84 deletions

View File

@ -121,31 +121,28 @@ class PrettyPrinter:
self._recursive = True self._recursive = True
self._readable = False self._readable = False
return return
rep = self._repr(object, context, level)
max_width = self._width - indent - allowance p = self._dispatch.get(type(object).__repr__, None)
if len(rep) > max_width: if p is not None:
p = self._dispatch.get(type(object).__repr__, None) context[objid] = 1
if p is not None: p(self, object, stream, indent, allowance, context, level + 1)
context[objid] = 1 del context[objid]
p(self, object, stream, indent, allowance, context, level + 1) elif (
del context[objid] _dataclasses.is_dataclass(object)
return and not isinstance(object, type)
elif ( and object.__dataclass_params__.repr
_dataclasses.is_dataclass(object) and
and not isinstance(object, type) # Check dataclass has generated repr method.
and object.__dataclass_params__.repr hasattr(object.__repr__, "__wrapped__")
and and "__create_fn__" in object.__repr__.__wrapped__.__qualname__
# Check dataclass has generated repr method. ):
hasattr(object.__repr__, "__wrapped__") context[objid] = 1
and "__create_fn__" in object.__repr__.__wrapped__.__qualname__ self._pprint_dataclass(
): object, stream, indent, allowance, context, level + 1
context[objid] = 1 )
self._pprint_dataclass( del context[objid]
object, stream, indent, allowance, context, level + 1 else:
) stream.write(self._repr(object, context, level))
del context[objid]
return
stream.write(rep)
def _pprint_dataclass(self, object, stream, indent, allowance, context, level): def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
cls_name = object.__class__.__name__ cls_name = object.__class__.__name__

View File

@ -1,12 +1,7 @@
import pprint import pprint
import reprlib import reprlib
from typing import Any
from typing import Dict
from typing import IO
from typing import Optional from typing import Optional
from .pprint import PrettyPrinter
def _try_repr_or_str(obj: object) -> str: def _try_repr_or_str(obj: object) -> str:
try: try:
@ -134,47 +129,3 @@ def saferepr_unlimited(obj: object, use_ascii: bool = True) -> str:
return repr(obj) return repr(obj)
except Exception as exc: except Exception as exc:
return _format_repr_exception(exc, obj) return _format_repr_exception(exc, obj)
class AlwaysDispatchingPrettyPrinter(PrettyPrinter):
"""PrettyPrinter that always dispatches (regardless of width)."""
def _format(
self,
object: object,
stream: IO[str],
indent: int,
allowance: int,
context: Dict[int, Any],
level: int,
) -> None:
p = self._dispatch.get(type(object).__repr__, None)
objid = id(object)
if objid in context or p is None:
super()._format(
object,
stream,
indent,
allowance,
context,
level,
)
return
context[objid] = 1
p(self, object, stream, indent, allowance, context, level + 1)
del context[objid]
def _pformat_dispatch(
object: object,
indent: int = 1,
width: int = 80,
depth: Optional[int] = None,
*,
compact: bool = False,
) -> str:
return AlwaysDispatchingPrettyPrinter(
indent=indent, width=width, depth=depth, compact=compact
).pformat(object)

View File

@ -16,7 +16,7 @@ from unicodedata import normalize
import _pytest._code import _pytest._code
from _pytest import outcomes from _pytest import outcomes
from _pytest._io.saferepr import _pformat_dispatch from _pytest._io.pprint import PrettyPrinter
from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr
from _pytest._io.saferepr import saferepr_unlimited from _pytest._io.saferepr import saferepr_unlimited
from _pytest.config import Config from _pytest.config import Config
@ -348,8 +348,9 @@ def _compare_eq_iterable(
lines_left = len(left_formatting) lines_left = len(left_formatting)
lines_right = len(right_formatting) lines_right = len(right_formatting)
if lines_left != lines_right: if lines_left != lines_right:
left_formatting = _pformat_dispatch(left).splitlines() printer = PrettyPrinter()
right_formatting = _pformat_dispatch(right).splitlines() left_formatting = printer.pformat(left).splitlines()
right_formatting = printer.pformat(right).splitlines()
if lines_left > 1 or lines_right > 1: if lines_left > 1 or lines_right > 1:
_surrounding_parens_on_own_lines(left_formatting) _surrounding_parens_on_own_lines(left_formatting)

View File

@ -0,0 +1,8 @@
from _pytest._io.pprint import PrettyPrinter
def test_pformat_dispatch():
printer = PrettyPrinter(width=5)
assert printer.pformat("a") == "'a'"
assert printer.pformat("a" * 10) == "'aaaaaaaaaa'"
assert printer.pformat("foo bar") == "('foo '\n 'bar')"

View File

@ -1,5 +1,4 @@
import pytest import pytest
from _pytest._io.saferepr import _pformat_dispatch
from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE
from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr
from _pytest._io.saferepr import saferepr_unlimited from _pytest._io.saferepr import saferepr_unlimited
@ -159,12 +158,6 @@ def test_unicode():
assert saferepr(val) == reprval assert saferepr(val) == reprval
def test_pformat_dispatch():
assert _pformat_dispatch("a") == "'a'"
assert _pformat_dispatch("a" * 10, width=5) == "'aaaaaaaaaa'"
assert _pformat_dispatch("foo bar", width=5) == "('foo '\n 'bar')"
def test_broken_getattribute(): def test_broken_getattribute():
"""saferepr() can create proper representations of classes with """saferepr() can create proper representations of classes with
broken __getattribute__ (#7145) broken __getattribute__ (#7145)