diff options
author | Lewis Gaul <lewis.gaul@gmail.com> | 2021-04-13 23:59:24 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-13 23:59:24 (GMT) |
commit | 11159d2c9d6616497ef4cc62953a5c3cc8454afb (patch) | |
tree | 80c6de1f50ce31cbe76e4a6ab2398a95f8fb5c2f /Lib/pprint.py | |
parent | 695d47b51e3e197de5448a1eb2f618bef6d59ac8 (diff) | |
download | cpython-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.py | 52 |
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 |