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

View File

@ -1,12 +1,7 @@
import pprint
import reprlib
from typing import Any
from typing import Dict
from typing import IO
from typing import Optional
from .pprint import PrettyPrinter
def _try_repr_or_str(obj: object) -> str:
try:
@ -134,47 +129,3 @@ def saferepr_unlimited(obj: object, use_ascii: bool = True) -> str:
return repr(obj)
except Exception as exc:
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
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_unlimited
from _pytest.config import Config
@ -348,8 +348,9 @@ def _compare_eq_iterable(
lines_left = len(left_formatting)
lines_right = len(right_formatting)
if lines_left != lines_right:
left_formatting = _pformat_dispatch(left).splitlines()
right_formatting = _pformat_dispatch(right).splitlines()
printer = PrettyPrinter()
left_formatting = printer.pformat(left).splitlines()
right_formatting = printer.pformat(right).splitlines()
if lines_left > 1 or lines_right > 1:
_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
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
@ -159,12 +158,6 @@ def test_unicode():
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():
"""saferepr() can create proper representations of classes with
broken __getattribute__ (#7145)