Skip to content

Commit b9baf94

Browse files
committed
Added an option for block formatting to pprint
1 parent 29caec6 commit b9baf94

File tree

1 file changed

+82
-46
lines changed

1 file changed

+82
-46
lines changed

Lib/pprint.py

Lines changed: 82 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,21 @@
4444

4545

4646
def pprint(object, stream=None, indent=1, width=80, depth=None, *,
47-
compact=False, sort_dicts=True, underscore_numbers=False):
47+
compact=False, sort_dicts=True, underscore_numbers=False, block_style=False):
4848
"""Pretty-print a Python object to a stream [default is sys.stdout]."""
4949
printer = PrettyPrinter(
5050
stream=stream, indent=indent, width=width, depth=depth,
5151
compact=compact, sort_dicts=sort_dicts,
52-
underscore_numbers=underscore_numbers)
52+
underscore_numbers=underscore_numbers, block_style=block_style)
5353
printer.pprint(object)
5454

5555

5656
def pformat(object, indent=1, width=80, depth=None, *,
57-
compact=False, sort_dicts=True, underscore_numbers=False):
57+
compact=False, sort_dicts=True, underscore_numbers=False, block_style=False):
5858
"""Format a Python object into a pretty-printed representation."""
5959
return PrettyPrinter(indent=indent, width=width, depth=depth,
6060
compact=compact, sort_dicts=sort_dicts,
61-
underscore_numbers=underscore_numbers).pformat(object)
61+
underscore_numbers=underscore_numbers, block_style=block_style).pformat(object)
6262

6363

6464
def pp(object, *args, sort_dicts=False, **kwargs):
@@ -111,7 +111,7 @@ def _safe_tuple(t):
111111

112112
class PrettyPrinter:
113113
def __init__(self, indent=1, width=80, depth=None, stream=None, *,
114-
compact=False, sort_dicts=True, underscore_numbers=False):
114+
compact=False, sort_dicts=True, underscore_numbers=False, block_style=False):
115115
"""Handle pretty printing operations onto a stream using a set of
116116
configured parameters.
117117
@@ -137,6 +137,11 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *,
137137
underscore_numbers
138138
If true, digit groups are separated with underscores.
139139
140+
block_style
141+
If true, the output will be formatted in a block style similar to
142+
pretty-printed json.dumps() when `indent` is supplied. Incompatible
143+
with compact mode.
144+
140145
"""
141146
indent = int(indent)
142147
width = int(width)
@@ -146,6 +151,8 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *,
146151
raise ValueError('depth must be > 0')
147152
if not width:
148153
raise ValueError('width must be != 0')
154+
if compact and block_style:
155+
raise ValueError('compact and block_style are incompatible')
149156
self._depth = depth
150157
self._indent_per_level = indent
151158
self._width = width
@@ -156,6 +163,7 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *,
156163
self._compact = bool(compact)
157164
self._sort_dicts = sort_dicts
158165
self._underscore_numbers = underscore_numbers
166+
self._block_style = bool(block_style)
159167

160168
def pprint(self, object):
161169
if self._stream is not None:
@@ -205,24 +213,39 @@ def _format(self, object, stream, indent, allowance, context, level):
205213
return
206214
stream.write(rep)
207215

216+
def _format_block_start(self, start_str, indent):
217+
if self._block_style:
218+
return start_str +'\n' + ' ' * indent
219+
else:
220+
return start_str
221+
222+
def _format_block_end(self, end_str, indent):
223+
if self._block_style:
224+
return '\n' + ' ' * indent + end_str
225+
else:
226+
return end_str
227+
208228
def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
209229
# Lazy import to improve module import time
210230
from dataclasses import fields as dataclass_fields
211231

212232
cls_name = object.__class__.__name__
213-
indent += len(cls_name) + 1
233+
indent += len(cls_name) + 1 if not self._block_style else self._indent_per_level
214234
items = [(f.name, getattr(object, f.name)) for f in dataclass_fields(object) if f.repr]
215-
stream.write(cls_name + '(')
235+
stream.write(self._format_block_start(cls_name + '(', indent))
216236
self._format_namespace_items(items, stream, indent, allowance, context, level)
217-
stream.write(')')
237+
if self._block_style:
238+
stream.write('\n')
239+
stream.write(self._format_block_end(')', indent - self._indent_per_level))
218240

219241
_dispatch = {}
220242

221243
def _pprint_dict(self, object, stream, indent, allowance, context, level):
222244
write = stream.write
223-
write('{')
245+
write(self._format_block_start('{', indent))
224246
if self._indent_per_level > 1:
225-
write((self._indent_per_level - 1) * ' ')
247+
indent_adjust = 0 if self._block_style else -1
248+
write((self._indent_per_level + indent_adjust) * ' ')
226249
length = len(object)
227250
if length:
228251
if self._sort_dicts:
@@ -231,7 +254,7 @@ def _pprint_dict(self, object, stream, indent, allowance, context, level):
231254
items = object.items()
232255
self._format_dict_items(items, stream, indent, allowance + 1,
233256
context, level)
234-
write('}')
257+
write(self._format_block_end('}', indent))
235258

236259
_dispatch[dict.__repr__] = _pprint_dict
237260

@@ -241,27 +264,28 @@ def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level
241264
return
242265
cls = object.__class__
243266
stream.write(cls.__name__ + '(')
267+
recursive_indent = indent + len(cls.__name__) + 1 if not self._block_style else indent
244268
self._format(list(object.items()), stream,
245-
indent + len(cls.__name__) + 1, allowance + 1,
269+
recursive_indent, allowance + 1,
246270
context, level)
247271
stream.write(')')
248272

249273
_dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict
250274

251275
def _pprint_list(self, object, stream, indent, allowance, context, level):
252-
stream.write('[')
276+
stream.write(self._format_block_start('[', indent))
253277
self._format_items(object, stream, indent, allowance + 1,
254278
context, level)
255-
stream.write(']')
279+
stream.write(self._format_block_end(']', indent))
256280

257281
_dispatch[list.__repr__] = _pprint_list
258282

259283
def _pprint_tuple(self, object, stream, indent, allowance, context, level):
260-
stream.write('(')
284+
stream.write(self._format_block_start('(', indent))
261285
endchar = ',)' if len(object) == 1 else ')'
262286
self._format_items(object, stream, indent, allowance + len(endchar),
263287
context, level)
264-
stream.write(endchar)
288+
stream.write(self._format_block_end(endchar, indent))
265289

266290
_dispatch[tuple.__repr__] = _pprint_tuple
267291

@@ -271,16 +295,16 @@ def _pprint_set(self, object, stream, indent, allowance, context, level):
271295
return
272296
typ = object.__class__
273297
if typ is set:
274-
stream.write('{')
298+
stream.write(self._format_block_start('{', indent))
275299
endchar = '}'
276300
else:
277-
stream.write(typ.__name__ + '({')
301+
stream.write(self._format_block_start(typ.__name__ + '({', indent))
278302
endchar = '})'
279-
indent += len(typ.__name__) + 1
303+
indent += len(typ.__name__) + 1 if not self._block_style else 0
280304
object = sorted(object, key=_safe_key)
281305
self._format_items(object, stream, indent, allowance + len(endchar),
282306
context, level)
283-
stream.write(endchar)
307+
stream.write(self._format_block_end(endchar, indent))
284308

285309
_dispatch[set.__repr__] = _pprint_set
286310
_dispatch[frozenset.__repr__] = _pprint_set
@@ -346,32 +370,35 @@ def _pprint_bytes(self, object, stream, indent, allowance, context, level):
346370
return
347371
parens = level == 1
348372
if parens:
349-
indent += 1
373+
indent += 1 if not self._block_style else self._indent_per_level
350374
allowance += 1
351-
write('(')
375+
write(self._format_block_start('(', indent))
352376
delim = ''
353377
for rep in _wrap_bytes_repr(object, self._width - indent, allowance):
354378
write(delim)
355379
write(rep)
356380
if not delim:
357381
delim = '\n' + ' '*indent
358382
if parens:
359-
write(')')
383+
write(self._format_block_end(')', indent - self._indent_per_level))
360384

361385
_dispatch[bytes.__repr__] = _pprint_bytes
362386

363387
def _pprint_bytearray(self, object, stream, indent, allowance, context, level):
364388
write = stream.write
365-
write('bytearray(')
366-
self._pprint_bytes(bytes(object), stream, indent + 10,
389+
write(self._format_block_start('bytearray(', indent))
390+
write(' ' * self._indent_per_level)
391+
recursive_indent = indent + 10 if not self._block_style else indent + self._indent_per_level
392+
self._pprint_bytes(bytes(object), stream, recursive_indent,
367393
allowance + 1, context, level + 1)
368-
write(')')
394+
write(self._format_block_end(')', indent))
369395

370396
_dispatch[bytearray.__repr__] = _pprint_bytearray
371397

372398
def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level):
373399
stream.write('mappingproxy(')
374-
self._format(object.copy(), stream, indent + 13, allowance + 1,
400+
recursive_indent = indent + 13 if not self._block_style else indent
401+
self._format(object.copy(), stream, recursive_indent, allowance + 1,
375402
context, level)
376403
stream.write(')')
377404

@@ -384,11 +411,11 @@ def _pprint_simplenamespace(self, object, stream, indent, allowance, context, le
384411
cls_name = 'namespace'
385412
else:
386413
cls_name = object.__class__.__name__
387-
indent += len(cls_name) + 1
414+
indent += len(cls_name) + 1 if not self._block_style else self._indent_per_level
388415
items = object.__dict__.items()
389-
stream.write(cls_name + '(')
416+
stream.write(self._format_block_start(cls_name + '(', indent))
390417
self._format_namespace_items(items, stream, indent, allowance, context, level)
391-
stream.write(')')
418+
stream.write(self._format_block_end(')', indent - self._indent_per_level))
392419

393420
_dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
394421

@@ -403,7 +430,8 @@ def _format_dict_items(self, items, stream, indent, allowance, context,
403430
rep = self._repr(key, context, level)
404431
write(rep)
405432
write(': ')
406-
self._format(ent, stream, indent + len(rep) + 2,
433+
recursive_indent = indent + len(rep) + 2 if not self._block_style else indent
434+
self._format(ent, stream, recursive_indent,
407435
allowance if last else 1,
408436
context, level)
409437
if not last:
@@ -422,7 +450,8 @@ def _format_namespace_items(self, items, stream, indent, allowance, context, lev
422450
# recursive dataclass repr.
423451
write("...")
424452
else:
425-
self._format(ent, stream, indent + len(key) + 1,
453+
recursive_indent = indent + len(key) + 1 if not self._block_style else indent
454+
self._format(ent, stream, recursive_indent,
426455
allowance if last else 1,
427456
context, level)
428457
if not last:
@@ -432,7 +461,8 @@ def _format_items(self, items, stream, indent, allowance, context, level):
432461
write = stream.write
433462
indent += self._indent_per_level
434463
if self._indent_per_level > 1:
435-
write((self._indent_per_level - 1) * ' ')
464+
indent_adjust = 0 if self._block_style else -1
465+
write((self._indent_per_level + indent_adjust) * ' ')
436466
delimnl = ',\n' + ' ' * indent
437467
delim = ''
438468
width = max_width = self._width - indent + 1
@@ -491,8 +521,11 @@ def _pprint_default_dict(self, object, stream, indent, allowance, context, level
491521
return
492522
rdf = self._repr(object.default_factory, context, level)
493523
cls = object.__class__
494-
indent += len(cls.__name__) + 1
495-
stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent))
524+
indent += len(cls.__name__) + 1 if not self._block_style else 0
525+
if self._block_style:
526+
stream.write('%s(%s, ' % (cls.__name__, rdf))
527+
else:
528+
stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent))
496529
self._pprint_dict(object, stream, indent, allowance + 1, context, level)
497530
stream.write(')')
498531

@@ -503,14 +536,15 @@ def _pprint_counter(self, object, stream, indent, allowance, context, level):
503536
stream.write(repr(object))
504537
return
505538
cls = object.__class__
506-
stream.write(cls.__name__ + '({')
539+
stream.write(self._format_block_start(cls.__name__ + '({', indent))
507540
if self._indent_per_level > 1:
508541
stream.write((self._indent_per_level - 1) * ' ')
509542
items = object.most_common()
543+
recursive_indent = indent + len(cls.__name__) + 1 if not self._block_style else indent
510544
self._format_dict_items(items, stream,
511-
indent + len(cls.__name__) + 1, allowance + 2,
545+
recursive_indent, allowance + 2,
512546
context, level)
513-
stream.write('})')
547+
stream.write(self._format_block_end('})', indent))
514548

515549
_dispatch[_collections.Counter.__repr__] = _pprint_counter
516550

@@ -519,12 +553,12 @@ def _pprint_chain_map(self, object, stream, indent, allowance, context, level):
519553
stream.write(repr(object))
520554
return
521555
cls = object.__class__
522-
stream.write(cls.__name__ + '(')
523-
indent += len(cls.__name__) + 1
556+
stream.write(self._format_block_start(cls.__name__ + '(', indent + self._indent_per_level))
557+
indent += len(cls.__name__) + 1 if not self._block_style else self._indent_per_level
524558
for i, m in enumerate(object.maps):
525559
if i == len(object.maps) - 1:
526560
self._format(m, stream, indent, allowance + 1, context, level)
527-
stream.write(')')
561+
stream.write(self._format_block_end(')', indent - self._indent_per_level))
528562
else:
529563
self._format(m, stream, indent, 1, context, level)
530564
stream.write(',\n' + ' ' * indent)
@@ -536,18 +570,20 @@ def _pprint_deque(self, object, stream, indent, allowance, context, level):
536570
stream.write(repr(object))
537571
return
538572
cls = object.__class__
539-
stream.write(cls.__name__ + '(')
540-
indent += len(cls.__name__) + 1
541-
stream.write('[')
573+
stream.write(self._format_block_start(cls.__name__ + '([', indent))
574+
indent += len(cls.__name__) + 1 if not self._block_style else 0
542575
if object.maxlen is None:
543576
self._format_items(object, stream, indent, allowance + 2,
544577
context, level)
545-
stream.write('])')
578+
stream.write(self._format_block_end('])', indent))
546579
else:
547580
self._format_items(object, stream, indent, 2,
548581
context, level)
549582
rml = self._repr(object.maxlen, context, level)
550-
stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml))
583+
if self._block_style:
584+
stream.write('%s], maxlen=%s)' % ('\n' + ' ' * indent, rml))
585+
else:
586+
stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml))
551587

552588
_dispatch[_collections.deque.__repr__] = _pprint_deque
553589

0 commit comments

Comments
 (0)