bpo-43080: pprint for dataclass instances (GH-24389)

* Added pprint support for dataclass instances which don't have a custom __repr__.
This commit is contained in:
Lewis Gaul 2021-04-14 00:59:24 +01:00 committed by GitHub
parent 695d47b51e
commit 11159d2c9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 133 additions and 14 deletions

View file

@ -35,6 +35,7 @@ saferepr()
"""
import collections as _collections
import dataclasses as _dataclasses
import re
import sys as _sys
import types as _types
@ -178,8 +179,26 @@ class PrettyPrinter:
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)
def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
cls_name = object.__class__.__name__
indent += len(cls_name) + 1
items = [(f.name, getattr(object, f.name)) for f in _dataclasses.fields(object) if f.repr]
stream.write(cls_name + '(')
self._format_namespace_items(items, stream, indent, allowance, context, level)
stream.write(')')
_dispatch = {}
def _pprint_dict(self, object, stream, indent, allowance, context, level):
@ -346,21 +365,9 @@ class PrettyPrinter:
else:
cls_name = object.__class__.__name__
indent += len(cls_name) + 1
delimnl = ',\n' + ' ' * indent
items = object.__dict__.items()
last_index = len(items) - 1
stream.write(cls_name + '(')
for i, (key, ent) in enumerate(items):
stream.write(key)
stream.write('=')
last = i == last_index
self._format(ent, stream, indent + len(key) + 1,
allowance if last else 1,
context, level)
if not last:
stream.write(delimnl)
self._format_namespace_items(items, stream, indent, allowance, context, level)
stream.write(')')
_dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
@ -382,6 +389,25 @@ class PrettyPrinter:
if not last:
write(delimnl)
def _format_namespace_items(self, items, stream, indent, allowance, context, level):
write = stream.write
delimnl = ',\n' + ' ' * indent
last_index = len(items) - 1
for i, (key, ent) in enumerate(items):
last = i == last_index
write(key)
write('=')
if id(ent) in context:
# Special-case representation of recursion to match standard
# recursive dataclass repr.
write("...")
else:
self._format(ent, stream, indent + len(key) + 1,
allowance if last else 1,
context, level)
if not last:
write(delimnl)
def _format_items(self, items, stream, indent, allowance, context, level):
write = stream.write
indent += self._indent_per_level