Skip to content

Commit f5fcbfc

Browse files
committed
Small bug fix for indent=1, added to unit test
1 parent b9baf94 commit f5fcbfc

File tree

3 files changed

+420
-14
lines changed

3 files changed

+420
-14
lines changed

Doc/library/pprint.rst

Lines changed: 99 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Functions
3636
---------
3737

3838
.. function:: pp(object, stream=None, indent=1, width=80, depth=None, *, \
39-
compact=False, sort_dicts=False, underscore_numbers=False)
39+
compact=False, sort_dicts=False, underscore_numbers=False, block_style=False)
4040

4141
Prints the formatted representation of *object*, followed by a newline.
4242
This function may be used in the interactive interpreter
@@ -85,6 +85,12 @@ Functions
8585
integers will be formatted with the ``_`` character for a thousands separator,
8686
otherwise underscores are not displayed (the default).
8787

88+
:param bool block_style:
89+
If ``True``,
90+
opening parentheses and brackets will be followed by a newline and the
91+
following content will be indented by one level, similar to block style
92+
JSON formatting. This option is not compatible with *compact*.
93+
8894
>>> import pprint
8995
>>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
9096
>>> stuff.insert(0, stuff)
@@ -100,18 +106,18 @@ Functions
100106

101107

102108
.. function:: pprint(object, stream=None, indent=1, width=80, depth=None, *, \
103-
compact=False, sort_dicts=True, underscore_numbers=False)
109+
compact=False, sort_dicts=True, underscore_numbers=False, block_style=False)
104110

105111
Alias for :func:`~pprint.pp` with *sort_dicts* set to ``True`` by default,
106112
which would automatically sort the dictionaries' keys,
107113
you might want to use :func:`~pprint.pp` instead where it is ``False`` by default.
108114

109115

110116
.. function:: pformat(object, indent=1, width=80, depth=None, *, \
111-
compact=False, sort_dicts=True, underscore_numbers=False)
117+
compact=False, sort_dicts=True, underscore_numbers=False, block_style=False)
112118

113119
Return the formatted representation of *object* as a string. *indent*,
114-
*width*, *depth*, *compact*, *sort_dicts* and *underscore_numbers* are
120+
*width*, *depth*, *compact*, *sort_dicts*, *underscore_numbers* and *block_style* are
115121
passed to the :class:`PrettyPrinter` constructor as formatting parameters
116122
and their meanings are as described in the documentation above.
117123

@@ -155,7 +161,7 @@ PrettyPrinter Objects
155161
.. index:: single: ...; placeholder
156162

157163
.. class:: PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, \
158-
compact=False, sort_dicts=True, underscore_numbers=False)
164+
compact=False, sort_dicts=True, underscore_numbers=False, block_style=False)
159165

160166
Construct a :class:`PrettyPrinter` instance.
161167

@@ -179,6 +185,22 @@ PrettyPrinter Objects
179185
'knights', 'ni'],
180186
'spam', 'eggs', 'lumberjack', 'knights',
181187
'ni']
188+
>>> pp = pprint.PrettyPrinter(width=41, block_style=True, indent=3)
189+
>>> pp.pprint(stuff)
190+
[
191+
[
192+
'spam',
193+
'eggs',
194+
'lumberjack',
195+
'knights',
196+
'ni'
197+
],
198+
'spam',
199+
'eggs',
200+
'lumberjack',
201+
'knights',
202+
'ni'
203+
]
182204
>>> tup = ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead',
183205
... ('parrot', ('fresh fruit',))))))))
184206
>>> pp = pprint.PrettyPrinter(depth=6)
@@ -198,6 +220,9 @@ PrettyPrinter Objects
198220
.. versionchanged:: 3.11
199221
No longer attempts to write to :data:`!sys.stdout` if it is ``None``.
200222

223+
.. versionchanged:: 3.13
224+
Added the *block_style* parameter.
225+
201226

202227
:class:`PrettyPrinter` instances have the following methods:
203228

@@ -420,3 +445,72 @@ cannot be split, the specified width will be exceeded::
420445
'requires_python': None,
421446
'summary': 'A sample Python project',
422447
'version': '1.2.0'}
448+
449+
Lastly, we can achieve block style formatting with the *block_style* parameter. Best results
450+
are achieved with a higher *indent* value::
451+
452+
>>> pprint.pp(project_info, indent=4, block_style=True)
453+
{
454+
'author': 'The Python Packaging Authority',
455+
'author_email': '[email protected]',
456+
'bugtrack_url': None,
457+
'classifiers': [
458+
'Development Status :: 3 - Alpha',
459+
'Intended Audience :: Developers',
460+
'License :: OSI Approved :: MIT License',
461+
'Programming Language :: Python :: 2',
462+
'Programming Language :: Python :: 2.6',
463+
'Programming Language :: Python :: 2.7',
464+
'Programming Language :: Python :: 3',
465+
'Programming Language :: Python :: 3.2',
466+
'Programming Language :: Python :: 3.3',
467+
'Programming Language :: Python :: 3.4',
468+
'Topic :: Software Development :: Build Tools'
469+
],
470+
'description': 'A sample Python project\n'
471+
'=======================\n'
472+
'\n'
473+
'This is the description file for the project.\n'
474+
'\n'
475+
'The file should use UTF-8 encoding and be written using ReStructured '
476+
'Text. It\n'
477+
'will be used to generate the project webpage on PyPI, and should be '
478+
'written for\n'
479+
'that purpose.\n'
480+
'\n'
481+
'Typical contents for this file would include an overview of the project, '
482+
'basic\n'
483+
'usage examples, etc. Generally, including the project changelog in here '
484+
'is not\n'
485+
'a good idea, although a simple "What\'s New" section for the most recent '
486+
'version\n'
487+
'may be appropriate.',
488+
'description_content_type': None,
489+
'docs_url': None,
490+
'download_url': 'UNKNOWN',
491+
'downloads': {'last_day': -1, 'last_month': -1, 'last_week': -1},
492+
'dynamic': None,
493+
'home_page': 'https://github.com/pypa/sampleproject',
494+
'keywords': 'sample setuptools development',
495+
'license': 'MIT',
496+
'license_expression': None,
497+
'license_files': None,
498+
'maintainer': None,
499+
'maintainer_email': None,
500+
'name': 'sampleproject',
501+
'package_url': 'https://pypi.org/project/sampleproject/',
502+
'platform': 'UNKNOWN',
503+
'project_url': 'https://pypi.org/project/sampleproject/',
504+
'project_urls': {
505+
'Download': 'UNKNOWN',
506+
'Homepage': 'https://github.com/pypa/sampleproject'
507+
},
508+
'provides_extra': None,
509+
'release_url': 'https://pypi.org/project/sampleproject/1.2.0/',
510+
'requires_dist': None,
511+
'requires_python': None,
512+
'summary': 'A sample Python project',
513+
'version': '1.2.0',
514+
'yanked': False,
515+
'yanked_reason': None
516+
}

Lib/pprint.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def _format_block_start(self, start_str, indent):
218218
return start_str +'\n' + ' ' * indent
219219
else:
220220
return start_str
221-
221+
222222
def _format_block_end(self, end_str, indent):
223223
if self._block_style:
224224
return '\n' + ' ' * indent + end_str
@@ -243,9 +243,10 @@ def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
243243
def _pprint_dict(self, object, stream, indent, allowance, context, level):
244244
write = stream.write
245245
write(self._format_block_start('{', indent))
246-
if self._indent_per_level > 1:
247-
indent_adjust = 0 if self._block_style else -1
248-
write((self._indent_per_level + indent_adjust) * ' ')
246+
if self._indent_per_level > 1 and not self._block_style:
247+
write((self._indent_per_level - 1) * ' ')
248+
if self._indent_per_level > 0 and self._block_style:
249+
write(self._indent_per_level * ' ')
249250
length = len(object)
250251
if length:
251252
if self._sort_dicts:
@@ -387,7 +388,8 @@ def _pprint_bytes(self, object, stream, indent, allowance, context, level):
387388
def _pprint_bytearray(self, object, stream, indent, allowance, context, level):
388389
write = stream.write
389390
write(self._format_block_start('bytearray(', indent))
390-
write(' ' * self._indent_per_level)
391+
if self._block_style:
392+
write(' ' * self._indent_per_level)
391393
recursive_indent = indent + 10 if not self._block_style else indent + self._indent_per_level
392394
self._pprint_bytes(bytes(object), stream, recursive_indent,
393395
allowance + 1, context, level + 1)
@@ -460,9 +462,10 @@ def _format_namespace_items(self, items, stream, indent, allowance, context, lev
460462
def _format_items(self, items, stream, indent, allowance, context, level):
461463
write = stream.write
462464
indent += self._indent_per_level
463-
if self._indent_per_level > 1:
464-
indent_adjust = 0 if self._block_style else -1
465-
write((self._indent_per_level + indent_adjust) * ' ')
465+
if self._indent_per_level > 1 and not self._block_style:
466+
write((self._indent_per_level - 1) * ' ')
467+
if self._indent_per_level > 0 and self._block_style:
468+
write(self._indent_per_level * ' ')
466469
delimnl = ',\n' + ' ' * indent
467470
delim = ''
468471
width = max_width = self._width - indent + 1
@@ -537,8 +540,10 @@ def _pprint_counter(self, object, stream, indent, allowance, context, level):
537540
return
538541
cls = object.__class__
539542
stream.write(self._format_block_start(cls.__name__ + '({', indent))
540-
if self._indent_per_level > 1:
543+
if self._indent_per_level > 1 and not self._block_style:
541544
stream.write((self._indent_per_level - 1) * ' ')
545+
if self._indent_per_level > 0 and self._block_style:
546+
stream.write(self._indent_per_level * ' ')
542547
items = object.most_common()
543548
recursive_indent = indent + len(cls.__name__) + 1 if not self._block_style else indent
544549
self._format_dict_items(items, stream,

0 commit comments

Comments
 (0)