mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Issue #23741: Slightly refactor the pprint module to make it a little more
extesible. No public API is added.
This commit is contained in:
parent
72bd327db0
commit
8e2aa88a40
1 changed files with 121 additions and 107 deletions
228
Lib/pprint.py
228
Lib/pprint.py
|
@ -152,130 +152,141 @@ class PrettyPrinter:
|
||||||
return readable and not recursive
|
return readable and not recursive
|
||||||
|
|
||||||
def _format(self, object, stream, indent, allowance, context, level):
|
def _format(self, object, stream, indent, allowance, context, level):
|
||||||
level = level + 1
|
|
||||||
objid = id(object)
|
objid = id(object)
|
||||||
if objid in context:
|
if objid in context:
|
||||||
stream.write(_recursion(object))
|
stream.write(_recursion(object))
|
||||||
self._recursive = True
|
self._recursive = True
|
||||||
self._readable = False
|
self._readable = False
|
||||||
return
|
return
|
||||||
rep = self._repr(object, context, level - 1)
|
rep = self._repr(object, context, level)
|
||||||
typ = type(object)
|
|
||||||
max_width = self._width - indent - allowance
|
max_width = self._width - indent - allowance
|
||||||
sepLines = len(rep) > max_width
|
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 isinstance(object, dict):
|
||||||
|
context[objid] = 1
|
||||||
|
self._pprint_dict(object, stream, indent, allowance,
|
||||||
|
context, level + 1)
|
||||||
|
del context[objid]
|
||||||
|
return
|
||||||
|
stream.write(rep)
|
||||||
|
|
||||||
|
_dispatch = {}
|
||||||
|
|
||||||
|
def _pprint_dict(self, object, stream, indent, allowance, context, level):
|
||||||
write = stream.write
|
write = stream.write
|
||||||
|
write('{')
|
||||||
|
if self._indent_per_level > 1:
|
||||||
|
write((self._indent_per_level - 1) * ' ')
|
||||||
|
length = len(object)
|
||||||
|
if length:
|
||||||
|
if isinstance(object, _OrderedDict):
|
||||||
|
items = list(object.items())
|
||||||
|
else:
|
||||||
|
items = sorted(object.items(), key=_safe_tuple)
|
||||||
|
self._format_dict_items(items, stream, indent, allowance + 1,
|
||||||
|
context, level)
|
||||||
|
write('}')
|
||||||
|
|
||||||
if sepLines:
|
_dispatch[dict.__repr__] = _pprint_dict
|
||||||
r = getattr(typ, "__repr__", None)
|
_dispatch[_OrderedDict.__repr__] = _pprint_dict
|
||||||
if issubclass(typ, dict):
|
|
||||||
write('{')
|
|
||||||
if self._indent_per_level > 1:
|
|
||||||
write((self._indent_per_level - 1) * ' ')
|
|
||||||
length = len(object)
|
|
||||||
if length:
|
|
||||||
context[objid] = 1
|
|
||||||
if issubclass(typ, _OrderedDict):
|
|
||||||
items = list(object.items())
|
|
||||||
else:
|
|
||||||
items = sorted(object.items(), key=_safe_tuple)
|
|
||||||
self._format_dict_items(items, stream,
|
|
||||||
indent + self._indent_per_level,
|
|
||||||
allowance + 1,
|
|
||||||
context, level)
|
|
||||||
del context[objid]
|
|
||||||
write('}')
|
|
||||||
return
|
|
||||||
|
|
||||||
if ((issubclass(typ, list) and r is list.__repr__) or
|
def _pprint_list(self, object, stream, indent, allowance, context, level):
|
||||||
(issubclass(typ, tuple) and r is tuple.__repr__) or
|
stream.write('[')
|
||||||
(issubclass(typ, set) and r is set.__repr__) or
|
self._format_items(object, stream, indent, allowance + 1,
|
||||||
(issubclass(typ, frozenset) and r is frozenset.__repr__)
|
context, level)
|
||||||
):
|
stream.write(']')
|
||||||
length = len(object)
|
|
||||||
if issubclass(typ, list):
|
|
||||||
write('[')
|
|
||||||
endchar = ']'
|
|
||||||
elif issubclass(typ, tuple):
|
|
||||||
write('(')
|
|
||||||
if length == 1:
|
|
||||||
endchar = ',)'
|
|
||||||
else:
|
|
||||||
endchar = ')'
|
|
||||||
else:
|
|
||||||
if not length:
|
|
||||||
write(rep)
|
|
||||||
return
|
|
||||||
if typ is set:
|
|
||||||
write('{')
|
|
||||||
endchar = '}'
|
|
||||||
else:
|
|
||||||
write(typ.__name__)
|
|
||||||
write('({')
|
|
||||||
endchar = '})'
|
|
||||||
indent += len(typ.__name__) + 1
|
|
||||||
object = sorted(object, key=_safe_key)
|
|
||||||
if self._indent_per_level > 1:
|
|
||||||
write((self._indent_per_level - 1) * ' ')
|
|
||||||
if length:
|
|
||||||
context[objid] = 1
|
|
||||||
self._format_items(object, stream,
|
|
||||||
indent + self._indent_per_level,
|
|
||||||
allowance + len(endchar),
|
|
||||||
context, level)
|
|
||||||
del context[objid]
|
|
||||||
write(endchar)
|
|
||||||
return
|
|
||||||
|
|
||||||
if issubclass(typ, str) and len(object) > 0 and r is str.__repr__:
|
_dispatch[list.__repr__] = _pprint_list
|
||||||
chunks = []
|
|
||||||
lines = object.splitlines(True)
|
def _pprint_tuple(self, object, stream, indent, allowance, context, level):
|
||||||
if level == 1:
|
stream.write('(')
|
||||||
indent += 1
|
endchar = ',)' if len(object) == 1 else ')'
|
||||||
allowance += 1
|
self._format_items(object, stream, indent, allowance + len(endchar),
|
||||||
max_width1 = max_width = self._width - indent
|
context, level)
|
||||||
for i, line in enumerate(lines):
|
stream.write(endchar)
|
||||||
rep = repr(line)
|
|
||||||
if i == len(lines) - 1:
|
_dispatch[tuple.__repr__] = _pprint_tuple
|
||||||
max_width1 -= allowance
|
|
||||||
if len(rep) <= max_width1:
|
def _pprint_set(self, object, stream, indent, allowance, context, level):
|
||||||
chunks.append(rep)
|
if not len(object):
|
||||||
else:
|
stream.write(repr(object))
|
||||||
# A list of alternating (non-space, space) strings
|
return
|
||||||
parts = re.findall(r'\S*\s*', line)
|
typ = object.__class__
|
||||||
assert parts
|
if typ is set:
|
||||||
assert not parts[-1]
|
stream.write('{')
|
||||||
parts.pop() # drop empty last part
|
endchar = '}'
|
||||||
max_width2 = max_width
|
else:
|
||||||
current = ''
|
stream.write(typ.__name__ + '({')
|
||||||
for j, part in enumerate(parts):
|
endchar = '})'
|
||||||
candidate = current + part
|
indent += len(typ.__name__) + 1
|
||||||
if j == len(parts) - 1 and i == len(lines) - 1:
|
object = sorted(object, key=_safe_key)
|
||||||
max_width2 -= allowance
|
self._format_items(object, stream, indent, allowance + len(endchar),
|
||||||
if len(repr(candidate)) > max_width2:
|
context, level)
|
||||||
if current:
|
stream.write(endchar)
|
||||||
chunks.append(repr(current))
|
|
||||||
current = part
|
_dispatch[set.__repr__] = _pprint_set
|
||||||
else:
|
_dispatch[frozenset.__repr__] = _pprint_set
|
||||||
current = candidate
|
|
||||||
|
def _pprint_str(self, object, stream, indent, allowance, context, level):
|
||||||
|
write = stream.write
|
||||||
|
if not len(object):
|
||||||
|
write(repr(object))
|
||||||
|
return
|
||||||
|
chunks = []
|
||||||
|
lines = object.splitlines(True)
|
||||||
|
if level == 1:
|
||||||
|
indent += 1
|
||||||
|
allowance += 1
|
||||||
|
max_width1 = max_width = self._width - indent
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
rep = repr(line)
|
||||||
|
if i == len(lines) - 1:
|
||||||
|
max_width1 -= allowance
|
||||||
|
if len(rep) <= max_width1:
|
||||||
|
chunks.append(rep)
|
||||||
|
else:
|
||||||
|
# A list of alternating (non-space, space) strings
|
||||||
|
parts = re.findall(r'\S*\s*', line)
|
||||||
|
assert parts
|
||||||
|
assert not parts[-1]
|
||||||
|
parts.pop() # drop empty last part
|
||||||
|
max_width2 = max_width
|
||||||
|
current = ''
|
||||||
|
for j, part in enumerate(parts):
|
||||||
|
candidate = current + part
|
||||||
|
if j == len(parts) - 1 and i == len(lines) - 1:
|
||||||
|
max_width2 -= allowance
|
||||||
|
if len(repr(candidate)) > max_width2:
|
||||||
if current:
|
if current:
|
||||||
chunks.append(repr(current))
|
chunks.append(repr(current))
|
||||||
if len(chunks) == 1:
|
current = part
|
||||||
write(rep)
|
else:
|
||||||
return
|
current = candidate
|
||||||
if level == 1:
|
if current:
|
||||||
write('(')
|
chunks.append(repr(current))
|
||||||
for i, rep in enumerate(chunks):
|
if len(chunks) == 1:
|
||||||
if i > 0:
|
write(rep)
|
||||||
write('\n' + ' '*indent)
|
return
|
||||||
write(rep)
|
if level == 1:
|
||||||
if level == 1:
|
write('(')
|
||||||
write(')')
|
for i, rep in enumerate(chunks):
|
||||||
return
|
if i > 0:
|
||||||
write(rep)
|
write('\n' + ' '*indent)
|
||||||
|
write(rep)
|
||||||
|
if level == 1:
|
||||||
|
write(')')
|
||||||
|
|
||||||
|
_dispatch[str.__repr__] = _pprint_str
|
||||||
|
|
||||||
def _format_dict_items(self, items, stream, indent, allowance, context,
|
def _format_dict_items(self, items, stream, indent, allowance, context,
|
||||||
level):
|
level):
|
||||||
write = stream.write
|
write = stream.write
|
||||||
|
indent += self._indent_per_level
|
||||||
delimnl = ',\n' + ' ' * indent
|
delimnl = ',\n' + ' ' * indent
|
||||||
last_index = len(items) - 1
|
last_index = len(items) - 1
|
||||||
for i, (key, ent) in enumerate(items):
|
for i, (key, ent) in enumerate(items):
|
||||||
|
@ -291,6 +302,9 @@ class PrettyPrinter:
|
||||||
|
|
||||||
def _format_items(self, items, stream, indent, allowance, context, level):
|
def _format_items(self, items, stream, indent, allowance, context, level):
|
||||||
write = stream.write
|
write = stream.write
|
||||||
|
indent += self._indent_per_level
|
||||||
|
if self._indent_per_level > 1:
|
||||||
|
write((self._indent_per_level - 1) * ' ')
|
||||||
delimnl = ',\n' + ' ' * indent
|
delimnl = ',\n' + ' ' * indent
|
||||||
delim = ''
|
delim = ''
|
||||||
width = max_width = self._width - indent + 1
|
width = max_width = self._width - indent + 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue