summaryrefslogtreecommitdiffstats
path: root/Lib/pprint.py
diff options
context:
space:
mode:
authorLewis Gaul <lewis.gaul@gmail.com>2021-04-13 23:59:24 (GMT)
committerGitHub <noreply@github.com>2021-04-13 23:59:24 (GMT)
commit11159d2c9d6616497ef4cc62953a5c3cc8454afb (patch)
tree80c6de1f50ce31cbe76e4a6ab2398a95f8fb5c2f /Lib/pprint.py
parent695d47b51e3e197de5448a1eb2f618bef6d59ac8 (diff)
downloadcpython-11159d2c9d6616497ef4cc62953a5c3cc8454afb.zip
cpython-11159d2c9d6616497ef4cc62953a5c3cc8454afb.tar.gz
cpython-11159d2c9d6616497ef4cc62953a5c3cc8454afb.tar.bz2
bpo-43080: pprint for dataclass instances (GH-24389)
* Added pprint support for dataclass instances which don't have a custom __repr__.
Diffstat (limited to 'Lib/pprint.py')
-rw-r--r--Lib/pprint.py52
1 files changed, 39 insertions, 13 deletions
diff --git a/Lib/pprint.py b/Lib/pprint.py
index b45cfdd..13819f3 100644
--- a/Lib/pprint.py
+++ b/Lib/pprint.py
@@ -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