---------
.. function:: pp(object, stream=None, indent=1, width=80, depth=None, *, \
- compact=False, sort_dicts=False, underscore_numbers=False)
+ compact=False, expand=False, sort_dicts=False, \
+ underscore_numbers=False)
Prints the formatted representation of *object*, followed by a newline.
This function may be used in the interactive interpreter
each item of a sequence will be formatted on a separate line,
otherwise as many items as will fit within the *width*
will be formatted on each output line.
+ Incompatible with *expand*.
+
+ :param bool expand:
+ If ``True``,
+ opening parentheses and brackets will be followed by a newline and the
+ following content will be indented by one level, similar to
+ pretty-printed JSON. Incompatible with *compact*.
:param bool sort_dicts:
If ``True``, dictionaries will be formatted with
.. function:: pprint(object, stream=None, indent=1, width=80, depth=None, *, \
- compact=False, sort_dicts=True, underscore_numbers=False)
+ compact=False, expand=False, sort_dicts=True, \
+ underscore_numbers=False)
Alias for :func:`~pprint.pp` with *sort_dicts* set to ``True`` by default,
which would automatically sort the dictionaries' keys,
.. function:: pformat(object, indent=1, width=80, depth=None, *, \
- compact=False, sort_dicts=True, underscore_numbers=False)
+ compact=False, expand=False, sort_dicts=True, \
+ underscore_numbers=False)
Return the formatted representation of *object* as a string. *indent*,
- *width*, *depth*, *compact*, *sort_dicts* and *underscore_numbers* are
+ *width*, *depth*, *compact*, *expand*, *sort_dicts* and *underscore_numbers* are
passed to the :class:`PrettyPrinter` constructor as formatting parameters
and their meanings are as described in the documentation above.
.. index:: single: ...; placeholder
.. class:: PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, \
- compact=False, sort_dicts=True, underscore_numbers=False)
+ compact=False, expand=False, sort_dicts=True, \
+ underscore_numbers=False)
Construct a :class:`PrettyPrinter` instance.
'knights', 'ni'],
'spam', 'eggs', 'lumberjack', 'knights',
'ni']
+ >>> pp = pprint.PrettyPrinter(width=41, expand=True, indent=3)
+ >>> pp.pprint(stuff)
+ [
+ [
+ 'spam',
+ 'eggs',
+ 'lumberjack',
+ 'knights',
+ 'ni',
+ ],
+ 'spam',
+ 'eggs',
+ 'lumberjack',
+ 'knights',
+ 'ni',
+ ]
>>> tup = ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead',
... ('parrot', ('fresh fruit',))))))))
>>> pp = pprint.PrettyPrinter(depth=6)
.. versionchanged:: 3.11
No longer attempts to write to :data:`!sys.stdout` if it is ``None``.
+ .. versionchanged:: next
+ Added the *expand* parameter.
+
:class:`PrettyPrinter` instances have the following methods:
'requires_python': None,
'summary': 'A sample Python project',
'version': '1.2.0'}
+
+Lastly, we can format like pretty-printed JSON with the *expand* parameter.
+Best results are achieved with a higher *indent* value::
+
+ >>> pprint.pp(project_info, indent=4, expand=True)
+ {
+ 'author': 'The Python Packaging Authority',
+ 'author_email': 'pypa-dev@googlegroups.com',
+ 'bugtrack_url': None,
+ 'classifiers': [
+ 'Development Status :: 3 - Alpha',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: MIT License',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.2',
+ 'Programming Language :: Python :: 3.3',
+ 'Programming Language :: Python :: 3.4',
+ 'Topic :: Software Development :: Build Tools',
+ ],
+ 'description': 'A sample Python project\n'
+ '=======================\n'
+ '\n'
+ 'This is the description file for the project.\n'
+ '\n'
+ 'The file should use UTF-8 encoding and be written using ReStructured '
+ 'Text. It\n'
+ 'will be used to generate the project webpage on PyPI, and should be '
+ 'written for\n'
+ 'that purpose.\n'
+ '\n'
+ 'Typical contents for this file would include an overview of the project, '
+ 'basic\n'
+ 'usage examples, etc. Generally, including the project changelog in here '
+ 'is not\n'
+ 'a good idea, although a simple "What\'s New" section for the most recent '
+ 'version\n'
+ 'may be appropriate.',
+ 'description_content_type': None,
+ 'docs_url': None,
+ 'download_url': 'UNKNOWN',
+ 'downloads': {'last_day': -1, 'last_month': -1, 'last_week': -1},
+ 'dynamic': None,
+ 'home_page': 'https://github.com/pypa/sampleproject',
+ 'keywords': 'sample setuptools development',
+ 'license': 'MIT',
+ 'license_expression': None,
+ 'license_files': None,
+ 'maintainer': None,
+ 'maintainer_email': None,
+ 'name': 'sampleproject',
+ 'package_url': 'https://pypi.org/project/sampleproject/',
+ 'platform': 'UNKNOWN',
+ 'project_url': 'https://pypi.org/project/sampleproject/',
+ 'project_urls': {
+ 'Download': 'UNKNOWN',
+ 'Homepage': 'https://github.com/pypa/sampleproject',
+ },
+ 'provides_extra': None,
+ 'release_url': 'https://pypi.org/project/sampleproject/1.2.0/',
+ 'requires_dist': None,
+ 'requires_python': None,
+ 'summary': 'A sample Python project',
+ 'version': '1.2.0',
+ 'yanked': False,
+ 'yanked_reason': None,
+ }
def pprint(object, stream=None, indent=1, width=80, depth=None, *,
- compact=False, sort_dicts=True, underscore_numbers=False):
+ compact=False, expand=False, sort_dicts=True,
+ underscore_numbers=False):
"""Pretty-print a Python object to a stream [default is sys.stdout]."""
printer = PrettyPrinter(
stream=stream, indent=indent, width=width, depth=depth,
- compact=compact, sort_dicts=sort_dicts,
+ compact=compact, expand=expand, sort_dicts=sort_dicts,
underscore_numbers=underscore_numbers)
printer.pprint(object)
def pformat(object, indent=1, width=80, depth=None, *,
- compact=False, sort_dicts=True, underscore_numbers=False):
+ compact=False, expand=False, sort_dicts=True,
+ underscore_numbers=False):
"""Format a Python object into a pretty-printed representation."""
return PrettyPrinter(indent=indent, width=width, depth=depth,
- compact=compact, sort_dicts=sort_dicts,
+ compact=compact, expand=expand, sort_dicts=sort_dicts,
underscore_numbers=underscore_numbers).pformat(object)
class PrettyPrinter:
def __init__(self, indent=1, width=80, depth=None, stream=None, *,
- compact=False, sort_dicts=True, underscore_numbers=False):
+ compact=False, expand=False, sort_dicts=True,
+ underscore_numbers=False):
"""Handle pretty printing operations onto a stream using a set of
configured parameters.
compact
If true, several items will be combined in one line.
+ Incompatible with expand mode.
+
+ expand
+ If true, the output will be formatted similar to
+ pretty-printed json.dumps() when ``indent`` is supplied.
+ Incompatible with compact mode.
sort_dicts
If true, dict keys are sorted.
raise ValueError('depth must be > 0')
if not width:
raise ValueError('width must be != 0')
+ if compact and expand:
+ raise ValueError('compact and expand are incompatible')
self._depth = depth
self._indent_per_level = indent
self._width = width
else:
self._stream = _sys.stdout
self._compact = bool(compact)
+ self._expand = bool(expand)
self._sort_dicts = sort_dicts
self._underscore_numbers = underscore_numbers
return
stream.write(rep)
+ def _format_block_start(self, start_str, indent):
+ if self._expand:
+ return f"{start_str}\n{' ' * indent}"
+ return start_str
+
+ def _format_block_end(self, end_str, indent):
+ if self._expand:
+ return f"\n{' ' * indent}{end_str}"
+ return end_str
+
+ def _child_indent(self, indent, prefix_len):
+ if self._expand:
+ return indent
+ return indent + prefix_len
+
+ def _write_indent_padding(self, write):
+ if self._expand:
+ if self._indent_per_level > 0:
+ write(self._indent_per_level * " ")
+ elif self._indent_per_level > 1:
+ write((self._indent_per_level - 1) * " ")
+
def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
# Lazy import to improve module import time
from dataclasses import fields as dataclass_fields
cls_name = object.__class__.__name__
- indent += len(cls_name) + 1
+ if self._expand:
+ indent += self._indent_per_level
+ else:
+ indent += len(cls_name) + 1
items = [(f.name, getattr(object, f.name)) for f in dataclass_fields(object) if f.repr]
- stream.write(cls_name + '(')
+ stream.write(self._format_block_start(cls_name + '(', indent))
self._format_namespace_items(items, stream, indent, allowance, context, level)
- stream.write(')')
+ stream.write(self._format_block_end(')', indent - self._indent_per_level))
_dispatch = {}
def _pprint_dict(self, object, stream, indent, allowance, context, level):
write = stream.write
- write('{')
- if self._indent_per_level > 1:
- write((self._indent_per_level - 1) * ' ')
+ write(self._format_block_start('{', indent))
+ self._write_indent_padding(write)
length = len(object)
if length:
if self._sort_dicts:
items = object.items()
self._format_dict_items(items, stream, indent, allowance + 1,
context, level)
- write('}')
+ write(self._format_block_end('}', indent))
_dispatch[dict.__repr__] = _pprint_dict
def _pprint_frozendict(self, object, stream, indent, allowance, context, level):
write = stream.write
cls = object.__class__
- write(cls.__name__ + '(')
- length = len(object)
- if length:
- self._pprint_dict(object, stream,
- indent + len(cls.__name__) + 1,
- allowance + 1,
- context, level)
- write(')')
+ if not len(object):
+ write(repr(object))
+ return
+
+ write(self._format_block_start(cls.__name__ + "({", indent))
+ self._write_indent_padding(write)
+
+ if self._sort_dicts:
+ items = sorted(object.items(), key=_safe_tuple)
+ else:
+ items = object.items()
+ self._format_dict_items(
+ items,
+ stream,
+ self._child_indent(indent, len(cls.__name__) + 1),
+ allowance + 2,
+ context,
+ level,
+ )
+ write(self._format_block_end("})", indent))
_dispatch[frozendict.__repr__] = _pprint_frozendict
return
cls = object.__class__
stream.write(cls.__name__ + '(')
- self._format(list(object.items()), stream,
- indent + len(cls.__name__) + 1, allowance + 1,
- context, level)
+ self._format(
+ list(object.items()),
+ stream,
+ self._child_indent(indent, len(cls.__name__) + 1),
+ allowance + 1,
+ context,
+ level,
+ )
stream.write(')')
_dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict
key = _safe_tuple
else:
key = _safe_key
+
write = stream.write
- write(object.__class__.__name__ + '([')
- if self._indent_per_level > 1:
- write((self._indent_per_level - 1) * ' ')
- length = len(object)
- if length:
+ write(
+ self._format_block_start(object.__class__.__name__ + "([", indent)
+ )
+
+ if len(object):
if self._sort_dicts:
entries = sorted(object, key=key)
else:
entries = object
- self._format_items(entries, stream, indent, allowance + 1,
- context, level)
- write('])')
+ self._format_items(
+ entries, stream, indent, allowance + 2, context, level
+ )
+ write(self._format_block_end("])", indent))
def _pprint_mapping_abc_view(self, object, stream, indent, allowance, context, level):
"""Pretty print mapping views from collections.abc."""
_collections.abc.MappingView)}
def _pprint_list(self, object, stream, indent, allowance, context, level):
- stream.write('[')
+ stream.write(self._format_block_start('[', indent))
self._format_items(object, stream, indent, allowance + 1,
context, level)
- stream.write(']')
+ stream.write(self._format_block_end(']', indent))
_dispatch[list.__repr__] = _pprint_list
def _pprint_tuple(self, object, stream, indent, allowance, context, level):
- stream.write('(')
- endchar = ',)' if len(object) == 1 else ')'
+ stream.write(self._format_block_start('(', indent))
+ if len(object) == 1 and not self._expand:
+ endchar = ',)'
+ else:
+ endchar = ')'
self._format_items(object, stream, indent, allowance + len(endchar),
context, level)
- stream.write(endchar)
+ stream.write(self._format_block_end(endchar, indent))
_dispatch[tuple.__repr__] = _pprint_tuple
return
typ = object.__class__
if typ is set:
- stream.write('{')
+ stream.write(self._format_block_start('{', indent))
endchar = '}'
else:
- stream.write(typ.__name__ + '({')
+ stream.write(self._format_block_start(typ.__name__ + '({', indent))
endchar = '})'
- indent += len(typ.__name__) + 1
+ if not self._expand:
+ indent += len(typ.__name__) + 1
object = sorted(object, key=_safe_key)
self._format_items(object, stream, indent, allowance + len(endchar),
context, level)
- stream.write(endchar)
+ stream.write(self._format_block_end(endchar, indent))
_dispatch[set.__repr__] = _pprint_set
_dispatch[frozenset.__repr__] = _pprint_set
chunks = []
lines = object.splitlines(True)
if level == 1:
- indent += 1
+ if self._expand:
+ indent += self._indent_per_level
+ else:
+ indent += 1
allowance += 1
max_width1 = max_width = self._width - indent
for i, line in enumerate(lines):
write(rep)
return
if level == 1:
- write('(')
+ write(self._format_block_start("(", indent))
for i, rep in enumerate(chunks):
if i > 0:
write('\n' + ' '*indent)
write(rep)
if level == 1:
- write(')')
+ write(self._format_block_end(")", indent - self._indent_per_level))
_dispatch[str.__repr__] = _pprint_str
return
parens = level == 1
if parens:
- indent += 1
+ if self._expand:
+ indent += self._indent_per_level
+ else:
+ indent += 1
allowance += 1
- write('(')
+ write(self._format_block_start('(', indent))
delim = ''
for rep in _wrap_bytes_repr(object, self._width - indent, allowance):
write(delim)
if not delim:
delim = '\n' + ' '*indent
if parens:
- write(')')
+ write(self._format_block_end(')', indent - self._indent_per_level))
_dispatch[bytes.__repr__] = _pprint_bytes
def _pprint_bytearray(self, object, stream, indent, allowance, context, level):
write = stream.write
- write('bytearray(')
- self._pprint_bytes(bytes(object), stream, indent + 10,
+ write(self._format_block_start('bytearray(', indent))
+ if self._expand:
+ write(' ' * self._indent_per_level)
+ recursive_indent = indent + self._indent_per_level
+ else:
+ recursive_indent = indent + 10
+ self._pprint_bytes(bytes(object), stream, recursive_indent,
allowance + 1, context, level + 1)
- write(')')
+ write(self._format_block_end(')', indent))
_dispatch[bytearray.__repr__] = _pprint_bytearray
def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level):
stream.write('mappingproxy(')
- self._format(object.copy(), stream, indent + 13, allowance + 1,
- context, level)
+ self._format(
+ object.copy(),
+ stream,
+ self._child_indent(indent, 13),
+ allowance + 1,
+ context,
+ level,
+ )
stream.write(')')
_dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy
cls_name = 'namespace'
else:
cls_name = object.__class__.__name__
- indent += len(cls_name) + 1
+ if self._expand:
+ indent += self._indent_per_level
+ else:
+ indent += len(cls_name) + 1
items = object.__dict__.items()
- stream.write(cls_name + '(')
- self._format_namespace_items(items, stream, indent, allowance, context, level)
- stream.write(')')
+ stream.write(self._format_block_start(cls_name + '(', indent))
+ self._format_namespace_items(items, stream, indent, allowance, context,
+ level)
+ stream.write(self._format_block_end(')', indent - self._indent_per_level))
_dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
rep = self._repr(key, context, level)
write(rep)
write(': ')
- self._format(ent, stream, indent + len(rep) + 2,
- allowance if last else 1,
- context, level)
+ self._format(
+ ent,
+ stream,
+ self._child_indent(indent, len(rep) + 2),
+ allowance if last else 1,
+ context,
+ level,
+ )
if not last:
write(delimnl)
+ elif self._expand:
+ write(',')
def _format_namespace_items(self, items, stream, indent, allowance, context, level):
write = stream.write
# recursive dataclass repr.
write("...")
else:
- self._format(ent, stream, indent + len(key) + 1,
- allowance if last else 1,
- context, level)
+ self._format(
+ ent,
+ stream,
+ self._child_indent(indent, len(key) + 1),
+ allowance if last else 1,
+ context,
+ level,
+ )
if not last:
write(delimnl)
+ elif self._expand:
+ write(',')
def _format_items(self, items, stream, indent, allowance, context, level):
write = stream.write
indent += self._indent_per_level
- if self._indent_per_level > 1:
- write((self._indent_per_level - 1) * ' ')
+ self._write_indent_padding(write)
delimnl = ',\n' + ' ' * indent
delim = ''
width = max_width = self._width - indent + 1
self._format(ent, stream, indent,
allowance if last else 1,
context, level)
+ if last and self._expand:
+ write(',')
def _repr(self, object, context, level):
repr, readable, recursive = self.format(object, context.copy(),
return
rdf = self._repr(object.default_factory, context, level)
cls = object.__class__
- indent += len(cls.__name__) + 1
- stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent))
- self._pprint_dict(object, stream, indent, allowance + 1, context, level)
+ if self._expand:
+ stream.write('%s(%s, ' % (cls.__name__, rdf))
+ else:
+ indent += len(cls.__name__) + 1
+ stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent))
+ self._pprint_dict(object, stream, indent, allowance + 1, context,
+ level)
stream.write(')')
_dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict
stream.write(repr(object))
return
cls = object.__class__
- stream.write(cls.__name__ + '({')
- if self._indent_per_level > 1:
- stream.write((self._indent_per_level - 1) * ' ')
+ stream.write(self._format_block_start(cls.__name__ + '({', indent))
+ self._write_indent_padding(stream.write)
items = object.most_common()
- self._format_dict_items(items, stream,
- indent + len(cls.__name__) + 1, allowance + 2,
- context, level)
- stream.write('})')
+ self._format_dict_items(
+ items,
+ stream,
+ self._child_indent(indent, len(cls.__name__) + 1),
+ allowance + 2,
+ context,
+ level,
+ )
+ stream.write(self._format_block_end('})', indent))
_dispatch[_collections.Counter.__repr__] = _pprint_counter
stream.write(repr(object))
return
cls = object.__class__
- stream.write(cls.__name__ + '(')
- indent += len(cls.__name__) + 1
+ stream.write(self._format_block_start(cls.__name__ + '(',
+ indent + self._indent_per_level))
+ if self._expand:
+ indent += self._indent_per_level
+ else:
+ indent += len(cls.__name__) + 1
for i, m in enumerate(object.maps):
if i == len(object.maps) - 1:
self._format(m, stream, indent, allowance + 1, context, level)
- stream.write(')')
+ if self._expand:
+ stream.write(',')
+ stream.write(self._format_block_end(')', indent - self._indent_per_level))
else:
self._format(m, stream, indent, 1, context, level)
stream.write(',\n' + ' ' * indent)
stream.write(repr(object))
return
cls = object.__class__
- stream.write(cls.__name__ + '(')
- indent += len(cls.__name__) + 1
- stream.write('[')
+ stream.write(self._format_block_start(cls.__name__ + '([', indent))
+ if not self._expand:
+ indent += len(cls.__name__) + 1
if object.maxlen is None:
self._format_items(object, stream, indent, allowance + 2,
context, level)
- stream.write('])')
+ stream.write(self._format_block_end('])', indent))
else:
self._format_items(object, stream, indent, 2,
context, level)
rml = self._repr(object.maxlen, context, level)
- stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml))
+ if self._expand:
+ stream.write('%s], maxlen=%s)' % ('\n' + ' ' * indent, rml))
+ else:
+ stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml))
_dispatch[_collections.deque.__repr__] = _pprint_deque
self.assertRaises(ValueError, pprint.PrettyPrinter, depth=0)
self.assertRaises(ValueError, pprint.PrettyPrinter, depth=-1)
self.assertRaises(ValueError, pprint.PrettyPrinter, width=0)
+ self.assertRaises(ValueError, pprint.PrettyPrinter, compact=True, expand=True)
def test_basic(self):
# Verify .isrecursive() and .isreadable() w/o recursion
'e': 4,
'n': 2,
'l': 1})""")
+ self.assertEqual(pprint.pformat(d, indent=2, width=1),
+"""\
+Counter({ 's': 6,
+ 'e': 4,
+ 'n': 2,
+ 'l': 1})""")
def test_chainmap(self):
d = collections.ChainMap()
'jumped over a '
'lazy dog'}""")
+ def test_expand_dataclass(self):
+ @dataclasses.dataclass
+ class DummyDataclass:
+ foo: str
+ bar: float
+ baz: bool
+ qux: dict = dataclasses.field(default_factory=dict)
+ quux: list = dataclasses.field(default_factory=list)
+ corge: int = 1
+ garply: tuple = (1, 2, 3, 4)
+ dummy_dataclass = DummyDataclass(
+ foo="foo",
+ bar=1.2,
+ baz=False,
+ qux={"foo": "bar", "baz": 123},
+ quux=["foo", "bar", "baz"],
+ corge=7,
+ garply=(1, 2, 3, 4),
+ )
+ self.assertEqual(pprint.pformat(dummy_dataclass, width=40, indent=4,
+ expand=True),
+"""\
+DummyDataclass(
+ foo='foo',
+ bar=1.2,
+ baz=False,
+ qux={'baz': 123, 'foo': 'bar'},
+ quux=['foo', 'bar', 'baz'],
+ corge=7,
+ garply=(1, 2, 3, 4),
+)""")
+
+ def test_expand_dict(self):
+ dummy_dict = {
+ "foo": "bar",
+ "baz": 123,
+ "qux": {"foo": "bar", "baz": 123},
+ "quux": ["foo", "bar", "baz"],
+ "corge": 7,
+ }
+ self.assertEqual(pprint.pformat(dummy_dict, width=40, indent=4,
+ expand=True, sort_dicts=False),
+"""\
+{
+ 'foo': 'bar',
+ 'baz': 123,
+ 'qux': {'foo': 'bar', 'baz': 123},
+ 'quux': ['foo', 'bar', 'baz'],
+ 'corge': 7,
+}""")
+
+ def test_expand_ordered_dict(self):
+ dummy_ordered_dict = collections.OrderedDict(
+ [
+ ("foo", 1),
+ ("bar", 12),
+ ("baz", 123),
+ ]
+ )
+ self.assertEqual(pprint.pformat(dummy_ordered_dict, width=20, indent=4,
+ expand=True),
+"""\
+OrderedDict([
+ ('foo', 1),
+ ('bar', 12),
+ ('baz', 123),
+])""")
+
+ def test_expand_list(self):
+ dummy_list = [
+ "foo",
+ "bar",
+ "baz",
+ "qux",
+ ]
+ self.assertEqual(pprint.pformat(dummy_list, width=20, indent=4,
+ expand=True),
+"""\
+[
+ 'foo',
+ 'bar',
+ 'baz',
+ 'qux',
+]""")
+
+ def test_expand_tuple(self):
+ dummy_tuple = (
+ "foo",
+ "bar",
+ "baz",
+ 4,
+ 5,
+ 6,
+ )
+ self.assertEqual(pprint.pformat(dummy_tuple, width=20, indent=4,
+ expand=True),
+"""\
+(
+ 'foo',
+ 'bar',
+ 'baz',
+ 4,
+ 5,
+ 6,
+)""")
+
+ def test_expand_single_element_tuple(self):
+ self.assertEqual(
+ pprint.pformat((1,), width=1, indent=4, expand=True),
+ """\
+(
+ 1,
+)""")
+
+ def test_expand_set(self):
+ dummy_set = {
+ "foo",
+ "bar",
+ "baz",
+ "qux",
+ (1, 2, 3),
+ }
+ self.assertEqual(pprint.pformat(dummy_set, width=20, indent=4,
+ expand=True),
+"""\
+{
+ 'bar',
+ 'baz',
+ 'foo',
+ 'qux',
+ (1, 2, 3),
+}""")
+
+ def test_expand_frozenset(self):
+ dummy_set = {
+ (1, 2, 3),
+ }
+ dummy_frozenset = frozenset(
+ {
+ "foo",
+ "bar",
+ "baz",
+ (1, 2, 3),
+ frozenset(dummy_set),
+ }
+ )
+ self.assertEqual(pprint.pformat(dummy_frozenset, width=40, indent=4,
+ expand=True),
+"""\
+frozenset({
+ frozenset({(1, 2, 3)}),
+ 'bar',
+ 'baz',
+ 'foo',
+ (1, 2, 3),
+})""")
+
+ def test_expand_frozendict(self):
+ dummy_frozendict = frozendict(
+ {"foo": "bar", "baz": 123, "qux": [1, 2]}
+ )
+ self.assertEqual(
+ pprint.pformat(dummy_frozendict, width=20, indent=4, expand=True),
+ """\
+frozendict({
+ 'baz': 123,
+ 'foo': 'bar',
+ 'qux': [1, 2],
+})""",
+ )
+
+ def test_expand_bytes(self):
+ dummy_bytes = b"Hello world! foo bar baz 123 456 789"
+ self.assertEqual(pprint.pformat(dummy_bytes, width=20, indent=4,
+ expand=True),
+"""\
+(
+ b'Hello world!'
+ b' foo bar baz'
+ b' 123 456 789'
+)""")
+
+ def test_expand_bytearray(self):
+ dummy_bytes = b"Hello world! foo bar baz 123 456 789"
+ dummy_byte_array = bytearray(dummy_bytes)
+ self.assertEqual(pprint.pformat(dummy_byte_array, width=40, indent=4,
+ expand=True),
+"""\
+bytearray(
+ b'Hello world! foo bar baz 123 456'
+ b' 789'
+)""")
+
+ def test_expand_mappingproxy(self):
+ dummy_dict = {
+ "foo": "bar",
+ "baz": 123,
+ "qux": {"foo": "bar", "baz": 123},
+ "quux": ["foo", "bar", "baz"],
+ "corge": 7,
+ }
+ dummy_mappingproxy = types.MappingProxyType(dummy_dict)
+ self.assertEqual(pprint.pformat(dummy_mappingproxy, width=40, indent=4,
+ expand=True),
+"""\
+mappingproxy({
+ 'baz': 123,
+ 'corge': 7,
+ 'foo': 'bar',
+ 'quux': ['foo', 'bar', 'baz'],
+ 'qux': {'baz': 123, 'foo': 'bar'},
+})""")
+
+ def test_expand_namespace(self):
+ dummy_namespace = types.SimpleNamespace(
+ foo="bar",
+ bar=42,
+ baz=types.SimpleNamespace(
+ x=321,
+ y="string",
+ d={"foo": True, "bar": "baz"},
+ ),
+ )
+
+ self.assertEqual(pprint.pformat(dummy_namespace, width=40, indent=4,
+ expand=True),
+"""\
+namespace(
+ foo='bar',
+ bar=42,
+ baz=namespace(
+ x=321,
+ y='string',
+ d={'bar': 'baz', 'foo': True},
+ ),
+)""")
+
+ def test_expand_defaultdict(self):
+ dummy_defaultdict = collections.defaultdict(list)
+ dummy_defaultdict["foo"].append("bar")
+ dummy_defaultdict["foo"].append("baz")
+ dummy_defaultdict["foo"].append("qux")
+ dummy_defaultdict["bar"] = {"foo": "bar", "baz": None}
+ self.assertEqual(pprint.pformat(dummy_defaultdict, width=40, indent=4,
+ expand=True),
+"""\
+defaultdict(<class 'list'>, {
+ 'bar': {'baz': None, 'foo': 'bar'},
+ 'foo': ['bar', 'baz', 'qux'],
+})""")
+
+ def test_expand_counter(self):
+ dummy_counter = collections.Counter("abcdeabcdabcaba")
+ expected = """\
+Counter({
+ 'a': 5,
+ 'b': 4,
+ 'c': 3,
+ 'd': 2,
+ 'e': 1,
+})"""
+ self.assertEqual(pprint.pformat(dummy_counter, width=40, indent=4,
+ expand=True), expected)
+
+ expected2 = """\
+Counter({
+ 'a': 5,
+ 'b': 4,
+ 'c': 3,
+ 'd': 2,
+ 'e': 1,
+})"""
+ self.assertEqual(pprint.pformat(dummy_counter, width=20, indent=2,
+ expand=True), expected2)
+
+ def test_expand_chainmap(self):
+ dummy_dict = {
+ "foo": "bar",
+ "baz": 123,
+ "qux": {"foo": "bar", "baz": 123},
+ "quux": ["foo", "bar", "baz"],
+ "corge": 7,
+ }
+ dummy_chainmap = collections.ChainMap(
+ {"foo": "bar"},
+ {"baz": "qux"},
+ {"corge": dummy_dict},
+ )
+ dummy_chainmap.maps.append({"garply": "waldo"})
+ self.assertEqual(pprint.pformat(dummy_chainmap, width=40, indent=4,
+ expand=True),
+"""\
+ChainMap(
+ {'foo': 'bar'},
+ {'baz': 'qux'},
+ {
+ 'corge': {
+ 'baz': 123,
+ 'corge': 7,
+ 'foo': 'bar',
+ 'quux': ['foo', 'bar', 'baz'],
+ 'qux': {
+ 'baz': 123,
+ 'foo': 'bar',
+ },
+ },
+ },
+ {'garply': 'waldo'},
+)""")
+
+ def test_expand_deque(self):
+ dummy_dict = {
+ "foo": "bar",
+ "baz": 123,
+ "qux": {"foo": "bar", "baz": 123},
+ "quux": ["foo", "bar", "baz"],
+ "corge": 7,
+ }
+ dummy_list = [
+ "foo",
+ "bar",
+ "baz",
+ ]
+ dummy_set = {
+ (1, 2, 3),
+ }
+ dummy_deque = collections.deque(maxlen=10)
+ dummy_deque.append("foo")
+ dummy_deque.append(123)
+ dummy_deque.append(dummy_dict)
+ dummy_deque.extend(dummy_list)
+ dummy_deque.appendleft(dummy_set)
+ self.assertEqual(pprint.pformat(dummy_deque, width=40, indent=4,
+ expand=True),
+"""\
+deque([
+ {(1, 2, 3)},
+ 'foo',
+ 123,
+ {
+ 'baz': 123,
+ 'corge': 7,
+ 'foo': 'bar',
+ 'quux': ['foo', 'bar', 'baz'],
+ 'qux': {'baz': 123, 'foo': 'bar'},
+ },
+ 'foo',
+ 'bar',
+ 'baz',
+], maxlen=10)""")
+
+ def test_expand_userdict(self):
+ class DummyUserDict(collections.UserDict):
+ """A custom UserDict with some extra attributes"""
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.access_count = 0
+ dummy_userdict = DummyUserDict({ "foo": "bar", "baz": 123,
+ "qux": {"foo": "bar", "baz": 123},
+ "quux": ["foo", "bar", "baz"],
+ "corge": 7 })
+ dummy_userdict.access_count = 5
+
+ self.assertEqual(pprint.pformat(dummy_userdict, width=40, indent=4,
+ expand=True),
+"""\
+{
+ 'baz': 123,
+ 'corge': 7,
+ 'foo': 'bar',
+ 'quux': ['foo', 'bar', 'baz'],
+ 'qux': {'baz': 123, 'foo': 'bar'},
+}""")
+
+ def test_expand_userlist(self):
+ class DummyUserList(collections.UserList):
+ """A custom UserList with some extra attributes"""
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.description = "foo"
+ dummy_userlist = DummyUserList(["first", 2, {"key": "value"},
+ [4, 5, 6]])
+
+ self.assertEqual(pprint.pformat(dummy_userlist, width=40, indent=4,
+ expand=True),
+"""\
+[
+ 'first',
+ 2,
+ {'key': 'value'},
+ [4, 5, 6],
+]""")
+
+ def test_expand_dict_keys(self):
+ d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5}
+ self.assertEqual(
+ pprint.pformat(d.keys(), width=20, indent=4, expand=True),
+ """\
+dict_keys([
+ 'bar',
+ 'baz',
+ 'foo',
+ 'quux',
+ 'qux',
+])""",
+ )
+
+ def test_expand_dict_values(self):
+ d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5}
+ self.assertEqual(
+ pprint.pformat(d.values(), width=20, indent=4, expand=True),
+ """\
+dict_values([
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+])""",
+ )
+
+ def test_expand_dict_items(self):
+ d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5}
+ self.assertEqual(
+ pprint.pformat(d.items(), width=20, indent=4, expand=True),
+ """\
+dict_items([
+ ('bar', 2),
+ ('baz', 3),
+ ('foo', 1),
+ ('quux', 5),
+ ('qux', 4),
+])""",
+ )
+
+ def test_expand_str(self):
+ s = "The quick brown fox jumped over the lazy dog " * 3
+ self.assertEqual(
+ pprint.pformat(s, width=40, indent=4, expand=True),
+ """\
+(
+ 'The quick brown fox jumped over '
+ 'the lazy dog The quick brown fox '
+ 'jumped over the lazy dog The '
+ 'quick brown fox jumped over the '
+ 'lazy dog '
+)""",
+ )
+
class DottedPrettyPrinter(pprint.PrettyPrinter):