]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-149189: Modern defaults for `pprint` (#149190)
authorHugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Tue, 5 May 2026 12:04:05 +0000 (15:04 +0300)
committerGitHub <noreply@github.com>
Tue, 5 May 2026 12:04:05 +0000 (15:04 +0300)
14 files changed:
Doc/library/difflib.rst
Doc/library/pprint.rst
Doc/library/ssl.rst
Doc/library/unittest.mock.rst
Doc/tutorial/stdlib2.rst
Doc/whatsnew/3.15.rst
Lib/difflib.py
Lib/pprint.py
Lib/test/test_descrtut.py
Lib/test/test_pickle.py
Lib/test/test_pprint.py
Lib/test/test_stable_abi_ctypes.py
Lib/test/test_unittest/testmock/testhelpers.py
Misc/NEWS.d/next/Library/2026-04-30-18-56-23.gh-issue-149189.mszW10.rst [new file with mode: 0644]

index 8b812c173b595368a8d87392fb90c003958247c8..e5afa17441354181510358cc878230eab9f1f67e 100644 (file)
@@ -728,16 +728,18 @@ Finally, we compare the two:
 
    >>> from pprint import pprint
    >>> pprint(result)
-   ['    1. Beautiful is better than ugly.\n',
-    '-   2. Explicit is better than implicit.\n',
-    '-   3. Simple is better than complex.\n',
-    '+   3.   Simple is better than complex.\n',
-    '?     ++\n',
-    '-   4. Complex is better than complicated.\n',
-    '?            ^                     ---- ^\n',
-    '+   4. Complicated is better than complex.\n',
-    '?           ++++ ^                      ^\n',
-    '+   5. Flat is better than nested.\n']
+   [
+       '    1. Beautiful is better than ugly.\n',
+       '-   2. Explicit is better than implicit.\n',
+       '-   3. Simple is better than complex.\n',
+       '+   3.   Simple is better than complex.\n',
+       '?     ++\n',
+       '-   4. Complex is better than complicated.\n',
+       '?            ^                     ---- ^\n',
+       '+   4. Complicated is better than complex.\n',
+       '?           ++++ ^                      ^\n',
+       '+   5. Flat is better than nested.\n',
+   ]
 
 As a single multi-line string it looks like this:
 
index 4f043fbb3a46dff47bca303e2ff0861fd916026d..0bdbe8c2e2bc974dec7feaeac61676f95229d92b 100644 (file)
@@ -17,7 +17,7 @@ objects which are not representable as Python literals.
 
 The formatted representation keeps objects on a single line if it can, and
 breaks them onto multiple lines if they don't fit within the allowed width,
-adjustable by the *width* parameter defaulting to 80 characters.
+adjustable by the *width* parameter defaulting to 88 characters.
 
 .. versionchanged:: 3.9
    Added support for pretty-printing :class:`types.SimpleNamespace`.
@@ -30,9 +30,8 @@ adjustable by the *width* parameter defaulting to 80 characters.
 Functions
 ---------
 
-.. function:: pp(object, stream=None, indent=1, width=80, depth=None, *, \
-                 compact=False, expand=False, sort_dicts=False, \
-                 underscore_numbers=False)
+.. function:: pp(object, stream=None, indent=4, width=88, depth=None, *, \
+                 compact=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
@@ -67,16 +66,11 @@ Functions
    :param bool compact:
       Control the way long :term:`sequences <sequence>` are formatted.
       If ``False`` (the default),
-      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*.
+      pretty-printed JSON.
+      If ``True``, as many items as will fit within the *width*
+      will be formatted on each output line.
 
    :param bool sort_dicts:
       If ``True``, dictionaries will be formatted with
@@ -91,32 +85,25 @@ Functions
    >>> import pprint
    >>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
    >>> stuff.insert(0, stuff)
-   >>> pprint.pp(stuff)
-   [<Recursion on list with id=...>,
-    'spam',
-    'eggs',
-    'lumberjack',
-    'knights',
-    'ni']
+   >>> pprint.pp(stuff, width=100)
+   [<Recursion on list with id=...>, 'spam', 'eggs', 'lumberjack', 'knights', 'ni']
 
    .. versionadded:: 3.8
 
 
-.. function:: pprint(object, stream=None, indent=1, width=80, depth=None, *, \
-                     compact=False, expand=False, sort_dicts=True, \
-                     underscore_numbers=False)
+.. function:: pprint(object, stream=None, indent=4, width=88, depth=None, *, \
+                     compact=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,
    you might want to use :func:`~pprint.pp` instead where it is ``False`` by default.
 
 
-.. function:: pformat(object, indent=1, width=80, depth=None, *, \
-                      compact=False, expand=False, sort_dicts=True, \
-                      underscore_numbers=False)
+.. function:: pformat(object, indent=4, width=88, depth=None, *, \
+                      compact=False, sort_dicts=True, underscore_numbers=False)
 
    Return the formatted representation of *object* as a string.  *indent*,
-   *width*, *depth*, *compact*, *expand*, *sort_dicts* and *underscore_numbers* are
+   *width*, *depth*, *compact*, *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.
 
@@ -154,13 +141,13 @@ Functions
 
 .. _prettyprinter-objects:
 
-PrettyPrinter Objects
+PrettyPrinter objects
 ---------------------
 
 .. index:: single: ...; placeholder
 
-.. class:: PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, \
-                         compact=False, expand=False, sort_dicts=True, \
+.. class:: PrettyPrinter(indent=4, width=88, depth=None, stream=None, *, \
+                         compact=False, sort_dicts=True, \
                          underscore_numbers=False)
 
    Construct a :class:`PrettyPrinter` instance.
@@ -171,21 +158,23 @@ PrettyPrinter Objects
    >>> import pprint
    >>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
    >>> stuff.insert(0, stuff[:])
-   >>> pp = pprint.PrettyPrinter(indent=4)
+   >>> pp = pprint.PrettyPrinter()
    >>> pp.pprint(stuff)
-   [   ['spam', 'eggs', 'lumberjack', 'knights', 'ni'],
+   [
+       ['spam', 'eggs', 'lumberjack', 'knights', 'ni'],
        'spam',
        'eggs',
        'lumberjack',
        'knights',
-       'ni']
-   >>> pp = pprint.PrettyPrinter(width=41, compact=True)
+       'ni',
+   ]
+   >>> pp = pprint.PrettyPrinter(indent=1, width=41, compact=True)
    >>> pp.pprint(stuff)
    [['spam', 'eggs', 'lumberjack',
      'knights', 'ni'],
     'spam', 'eggs', 'lumberjack', 'knights',
     'ni']
-   >>> pp = pprint.PrettyPrinter(width=41, expand=True, indent=3)
+   >>> pp = pprint.PrettyPrinter(width=41, indent=3)
    >>> pp.pprint(stuff)
    [
       [
@@ -220,8 +209,12 @@ PrettyPrinter Objects
    .. versionchanged:: 3.11
       No longer attempts to write to :data:`!sys.stdout` if it is ``None``.
 
-   .. versionchanged:: 3.15
-      Added the *expand* parameter.
+   .. versionchanged:: next
+      Changed default *indent* from 1 to 4
+      and default *width* from 80 to 88.
+      The default ``compact=False`` layout is now similar to
+      pretty-printed JSON, with opening parentheses and brackets
+      followed by a newline and the contents indented by one level.
 
 
 :class:`PrettyPrinter` instances have the following methods:
@@ -298,219 +291,144 @@ let's fetch information about a project from `PyPI <https://pypi.org>`_::
 In its basic form, :func:`~pprint.pp` shows the whole object::
 
    >>> pprint.pp(project_info)
-   {'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},
-    'home_page': 'https://github.com/pypa/sampleproject',
-    'keywords': 'sample setuptools development',
-    'license': 'MIT',
-    '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'},
-    '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'}
+   {
+       '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},
+       'home_page': 'https://github.com/pypa/sampleproject',
+       'keywords': 'sample setuptools development',
+       'license': 'MIT',
+       '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'},
+       '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',
+   }
 
 The result can be limited to a certain *depth* (ellipsis is used for deeper
 contents)::
 
    >>> pprint.pp(project_info, depth=1)
-   {'author': 'The Python Packaging Authority',
-    'author_email': 'pypa-dev@googlegroups.com',
-    'bugtrack_url': None,
-    'classifiers': [...],
-    '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': {...},
-    'home_page': 'https://github.com/pypa/sampleproject',
-    'keywords': 'sample setuptools development',
-    'license': 'MIT',
-    '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': {...},
-    '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'}
+   {
+       'author': 'The Python Packaging Authority',
+       'author_email': 'pypa-dev@googlegroups.com',
+       'bugtrack_url': None,
+       'classifiers': [...],
+       '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': {...},
+       'home_page': 'https://github.com/pypa/sampleproject',
+       'keywords': 'sample setuptools development',
+       'license': 'MIT',
+       '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': {...},
+       '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',
+   }
 
 Additionally, maximum character *width* can be suggested. If a long object
 cannot be split, the specified width will be exceeded::
 
    >>> pprint.pp(project_info, depth=1, width=60)
-   {'author': 'The Python Packaging Authority',
-    'author_email': 'pypa-dev@googlegroups.com',
-    'bugtrack_url': None,
-    'classifiers': [...],
-    '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': {...},
-    'home_page': 'https://github.com/pypa/sampleproject',
-    'keywords': 'sample setuptools development',
-    'license': 'MIT',
-    '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': {...},
-    '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'}
-
-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,
+       'author': 'The Python Packaging Authority',
+       'author_email': 'pypa-dev@googlegroups.com',
+       'bugtrack_url': None,
+       'classifiers': [...],
+       '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': {...},
+       'home_page': 'https://github.com/pypa/sampleproject',
+       'keywords': 'sample setuptools development',
+       'license': 'MIT',
+       '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': {...},
+       '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',
    }
index f2c35d1897a77f8d8114b40554949f5401922aec..d9c736d27dcaecc92718a8dcc8b8b7f702b923ad 100644 (file)
@@ -2473,67 +2473,79 @@ Visual inspection shows that the certificate does identify the desired service
 (that is, the HTTPS host ``www.python.org``)::
 
    >>> pprint.pprint(cert)
-   {'OCSP': ('http://ocsp.digicert.com',),
-    'caIssuers': ('http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt',),
-    'crlDistributionPoints': ('http://crl3.digicert.com/sha2-ev-server-g1.crl',
-                              'http://crl4.digicert.com/sha2-ev-server-g1.crl'),
-    'issuer': ((('countryName', 'US'),),
-               (('organizationName', 'DigiCert Inc'),),
-               (('organizationalUnitName', 'www.digicert.com'),),
-               (('commonName', 'DigiCert SHA2 Extended Validation Server CA'),)),
-    'notAfter': 'Sep  9 12:00:00 2016 GMT',
-    'notBefore': 'Sep  5 00:00:00 2014 GMT',
-    'serialNumber': '01BB6F00122B177F36CAB49CEA8B6B26',
-    'subject': ((('businessCategory', 'Private Organization'),),
-                (('1.3.6.1.4.1.311.60.2.1.3', 'US'),),
-                (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),),
-                (('serialNumber', '3359300'),),
-                (('streetAddress', '16 Allen Rd'),),
-                (('postalCode', '03894-4801'),),
-                (('countryName', 'US'),),
-                (('stateOrProvinceName', 'NH'),),
-                (('localityName', 'Wolfeboro'),),
-                (('organizationName', 'Python Software Foundation'),),
-                (('commonName', 'www.python.org'),)),
-    'subjectAltName': (('DNS', 'www.python.org'),
-                       ('DNS', 'python.org'),
-                       ('DNS', 'pypi.org'),
-                       ('DNS', 'docs.python.org'),
-                       ('DNS', 'testpypi.org'),
-                       ('DNS', 'bugs.python.org'),
-                       ('DNS', 'wiki.python.org'),
-                       ('DNS', 'hg.python.org'),
-                       ('DNS', 'mail.python.org'),
-                       ('DNS', 'packaging.python.org'),
-                       ('DNS', 'pythonhosted.org'),
-                       ('DNS', 'www.pythonhosted.org'),
-                       ('DNS', 'test.pythonhosted.org'),
-                       ('DNS', 'us.pycon.org'),
-                       ('DNS', 'id.python.org')),
-    'version': 3}
+   {
+       'OCSP': ('http://ocsp.digicert.com',),
+       'caIssuers': ('http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt',),
+       'crlDistributionPoints': (
+           'http://crl3.digicert.com/sha2-ev-server-g1.crl',
+           'http://crl4.digicert.com/sha2-ev-server-g1.crl',
+       ),
+       'issuer': (
+           (('countryName', 'US'),),
+           (('organizationName', 'DigiCert Inc'),),
+           (('organizationalUnitName', 'www.digicert.com'),),
+           (('commonName', 'DigiCert SHA2 Extended Validation Server CA'),),
+       ),
+       'notAfter': 'Sep  9 12:00:00 2016 GMT',
+       'notBefore': 'Sep  5 00:00:00 2014 GMT',
+       'serialNumber': '01BB6F00122B177F36CAB49CEA8B6B26',
+       'subject': (
+           (('businessCategory', 'Private Organization'),),
+           (('1.3.6.1.4.1.311.60.2.1.3', 'US'),),
+           (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),),
+           (('serialNumber', '3359300'),),
+           (('streetAddress', '16 Allen Rd'),),
+           (('postalCode', '03894-4801'),),
+           (('countryName', 'US'),),
+           (('stateOrProvinceName', 'NH'),),
+           (('localityName', 'Wolfeboro'),),
+           (('organizationName', 'Python Software Foundation'),),
+           (('commonName', 'www.python.org'),),
+       ),
+       'subjectAltName': (
+           ('DNS', 'www.python.org'),
+           ('DNS', 'python.org'),
+           ('DNS', 'pypi.org'),
+           ('DNS', 'docs.python.org'),
+           ('DNS', 'testpypi.org'),
+           ('DNS', 'bugs.python.org'),
+           ('DNS', 'wiki.python.org'),
+           ('DNS', 'hg.python.org'),
+           ('DNS', 'mail.python.org'),
+           ('DNS', 'packaging.python.org'),
+           ('DNS', 'pythonhosted.org'),
+           ('DNS', 'www.pythonhosted.org'),
+           ('DNS', 'test.pythonhosted.org'),
+           ('DNS', 'us.pycon.org'),
+           ('DNS', 'id.python.org'),
+       ),
+       'version': 3,
+   }
 
 Now the SSL channel is established and the certificate verified, you can
 proceed to talk with the server::
 
    >>> conn.sendall(b"HEAD / HTTP/1.0\r\nHost: linuxfr.org\r\n\r\n")
    >>> pprint.pprint(conn.recv(1024).split(b"\r\n"))
-   [b'HTTP/1.1 200 OK',
-    b'Date: Sat, 18 Oct 2014 18:27:20 GMT',
-    b'Server: nginx',
-    b'Content-Type: text/html; charset=utf-8',
-    b'X-Frame-Options: SAMEORIGIN',
-    b'Content-Length: 45679',
-    b'Accept-Ranges: bytes',
-    b'Via: 1.1 varnish',
-    b'Age: 2188',
-    b'X-Served-By: cache-lcy1134-LCY',
-    b'X-Cache: HIT',
-    b'X-Cache-Hits: 11',
-    b'Vary: Cookie',
-    b'Strict-Transport-Security: max-age=63072000; includeSubDomains',
-    b'Connection: close',
-    b'',
-    b'']
+   [
+       b'HTTP/1.1 200 OK',
+       b'Date: Sat, 18 Oct 2014 18:27:20 GMT',
+       b'Server: nginx',
+       b'Content-Type: text/html; charset=utf-8',
+       b'X-Frame-Options: SAMEORIGIN',
+       b'Content-Length: 45679',
+       b'Accept-Ranges: bytes',
+       b'Via: 1.1 varnish',
+       b'Age: 2188',
+       b'X-Served-By: cache-lcy1134-LCY',
+       b'X-Cache: HIT',
+       b'X-Cache-Hits: 11',
+       b'Vary: Cookie',
+       b'Strict-Transport-Security: max-age=63072000; includeSubDomains',
+       b'Connection: close',
+       b'',
+       b'',
+   ]
 
 See the discussion of :ref:`ssl-security` below.
 
index 2ff1015af7a86e0060465f1c9efccbef77d2a607..5b9f9eec93aa28dbd6ed4a7b0fc3787744e891d0 100644 (file)
@@ -2347,10 +2347,12 @@ chained call:
     <MagicMock name='mock().method().other()()' id='...'>
     >>> kall = call(1).method(arg='foo').other('bar')(2.0)
     >>> kall.call_list()
-    [call(1),
-     call().method(arg='foo'),
-     call().method().other('bar'),
-     call().method().other()(2.0)]
+    [
+        call(1),
+        call().method(arg='foo'),
+        call().method().other('bar'),
+        call().method().other()(2.0),
+    ]
     >>> m.mock_calls == kall.call_list()
     True
 
index 6c68ba0108137941dcfa80d2dbfd33caff5ea1bc..2c3ec71cd3de397294f527d8bddbe03c91a76608 100644 (file)
@@ -30,11 +30,22 @@ and indentation to more clearly reveal data structure::
    ...     'yellow'], 'blue']]]
    ...
    >>> pprint.pprint(t, width=30)
-   [[[['black', 'cyan'],
-      'white',
-      ['green', 'red']],
-     [['magenta', 'yellow'],
-      'blue']]]
+   [
+       [
+           [
+               ['black', 'cyan'],
+               'white',
+               ['green', 'red'],
+           ],
+           [
+               [
+                   'magenta',
+                   'yellow',
+               ],
+               'blue',
+           ],
+       ],
+   ]
 
 The :mod:`textwrap` module formats paragraphs of text to fit a given screen
 width::
index c34a1bf3c47126934c2267616607ed8b1aa1191b..3cf69718e63b28e2f100879f043de858021445e3 100644 (file)
@@ -1210,12 +1210,11 @@ pickletools
 pprint
 ------
 
-* Add an *expand* keyword argument for :func:`pprint.pprint`,
-  :func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be
-  formatted similar to pretty-printed :func:`json.dumps` when
-  *indent* is supplied.
+* :mod:`pprint` now uses modern defaults: ``indent=4, width=88``,
+  and the default ``compact=False`` output is now formatted similar to
+  pretty-printed :func:`json.dumps`.
   (Contributed by Stefan Todoran, Semyon Moroz and Hugo van Kemenade in
-  :gh:`112632`.)
+  :gh:`112632` and :gh:`149189`.)
 
 * Add t-string support to :mod:`pprint`.
   (Contributed by Loïc Simon and Hugo van Kemenade in :gh:`134551`.)
index 8f3cdaed9564d87e382e12e71d0d785ffff479c6..eb249e3e288923032fd2712e855d1e0456a4d369 100644 (file)
@@ -559,15 +559,17 @@ class SequenceMatcher:
         >>> b[23:28] = []      # Make a deletion
         >>> b[30] += 'y'       # Make another replacement
         >>> pprint(list(SequenceMatcher(None,a,b).get_grouped_opcodes()))
-        [[('equal', 5, 8, 5, 8), ('insert', 8, 8, 8, 9), ('equal', 8, 11, 9, 12)],
-         [('equal', 16, 19, 17, 20),
-          ('replace', 19, 20, 20, 21),
-          ('equal', 20, 22, 21, 23),
-          ('delete', 22, 27, 23, 23),
-          ('equal', 27, 30, 23, 26)],
-         [('equal', 31, 34, 27, 30),
-          ('replace', 34, 35, 30, 31),
-          ('equal', 35, 38, 31, 34)]]
+        [
+            [('equal', 5, 8, 5, 8), ('insert', 8, 8, 8, 9), ('equal', 8, 11, 9, 12)],
+            [
+                ('equal', 16, 19, 17, 20),
+                ('replace', 19, 20, 20, 21),
+                ('equal', 20, 22, 21, 23),
+                ('delete', 22, 27, 23, 23),
+                ('equal', 27, 30, 23, 26),
+            ],
+            [('equal', 31, 34, 27, 30), ('replace', 34, 35, 30, 31), ('equal', 35, 38, 31, 34)],
+        ]
         """
 
         codes = self.get_opcodes()
@@ -784,16 +786,18 @@ class Differ:
 
     >>> from pprint import pprint as _pprint
     >>> _pprint(result)
-    ['    1. Beautiful is better than ugly.\n',
-     '-   2. Explicit is better than implicit.\n',
-     '-   3. Simple is better than complex.\n',
-     '+   3.   Simple is better than complex.\n',
-     '?     ++\n',
-     '-   4. Complex is better than complicated.\n',
-     '?            ^                     ---- ^\n',
-     '+   4. Complicated is better than complex.\n',
-     '?           ++++ ^                      ^\n',
-     '+   5. Flat is better than nested.\n']
+    [
+        '    1. Beautiful is better than ugly.\n',
+        '-   2. Explicit is better than implicit.\n',
+        '-   3. Simple is better than complex.\n',
+        '+   3.   Simple is better than complex.\n',
+        '?     ++\n',
+        '-   4. Complex is better than complicated.\n',
+        '?            ^                     ---- ^\n',
+        '+   4. Complicated is better than complex.\n',
+        '?           ++++ ^                      ^\n',
+        '+   5. Flat is better than nested.\n',
+    ]
 
     As a single multi-line string it looks like this:
 
index 7355021998081dcda7bec837fbe6d39a50099631..1fd7e3ec95a073463c4a03d939441bbc97733c43 100644 (file)
@@ -43,23 +43,38 @@ __all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
            "PrettyPrinter", "pp"]
 
 
-def pprint(object, stream=None, indent=1, width=80, depth=None, *,
-           compact=False, expand=False, sort_dicts=True,
-           underscore_numbers=False):
+def pprint(
+    object,
+    stream=None,
+    indent=4,
+    width=88,
+    depth=None,
+    *,
+    compact=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, expand=expand, sort_dicts=sort_dicts,
+        compact=compact, sort_dicts=sort_dicts,
         underscore_numbers=underscore_numbers)
     printer.pprint(object)
 
 
-def pformat(object, indent=1, width=80, depth=None, *,
-            compact=False, expand=False, sort_dicts=True,
-            underscore_numbers=False):
+def pformat(
+    object,
+    indent=4,
+    width=88,
+    depth=None,
+    *,
+    compact=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, expand=expand, sort_dicts=sort_dicts,
+                         compact=compact, sort_dicts=sort_dicts,
                          underscore_numbers=underscore_numbers).pformat(object)
 
 
@@ -112,9 +127,17 @@ def _safe_tuple(t):
 
 
 class PrettyPrinter:
-    def __init__(self, indent=1, width=80, depth=None, stream=None, *,
-                 compact=False, expand=False, sort_dicts=True,
-                 underscore_numbers=False):
+    def __init__(
+        self,
+        indent=4,
+        width=88,
+        depth=None,
+        stream=None,
+        *,
+        compact=False,
+        sort_dicts=True,
+        underscore_numbers=False,
+    ):
         """Handle pretty printing operations onto a stream using a set of
         configured parameters.
 
@@ -133,12 +156,6 @@ class PrettyPrinter:
 
         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.
@@ -155,8 +172,6 @@ class PrettyPrinter:
             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
@@ -165,7 +180,6 @@ class PrettyPrinter:
         else:
             self._stream = _sys.stdout
         self._compact = bool(compact)
-        self._expand = bool(expand)
         self._sort_dicts = sort_dicts
         self._underscore_numbers = underscore_numbers
 
@@ -218,36 +232,36 @@ class PrettyPrinter:
         stream.write(rep)
 
     def _format_block_start(self, start_str, indent):
-        if self._expand:
-            return f"{start_str}\n{' ' * indent}"
-        return start_str
+        if self._compact:
+            return start_str
+        return f"{start_str}\n{' ' * indent}"
 
     def _format_block_end(self, end_str, indent):
-        if self._expand:
-            return f"\n{' ' * indent}{end_str}"
-        return end_str
+        if self._compact:
+            return end_str
+        return f"\n{' ' * indent}{end_str}"
 
     def _child_indent(self, indent, prefix_len):
-        if self._expand:
-            return indent
-        return indent + prefix_len
+        if self._compact:
+            return indent + prefix_len
+        return indent
 
     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) * " ")
+        if self._compact:
+            if self._indent_per_level > 1:
+                write((self._indent_per_level - 1) * " ")
+        elif self._indent_per_level > 0:
+            write(self._indent_per_level * " ")
 
     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__
-        if self._expand:
-            indent += self._indent_per_level
-        else:
+        if self._compact:
             indent += len(cls_name) + 1
+        else:
+            indent += self._indent_per_level
         items = [(f.name, getattr(object, f.name)) for f in dataclass_fields(object) if f.repr]
         stream.write(self._format_block_start(cls_name + '(', indent))
         self._format_namespace_items(items, stream, indent, allowance, context, level)
@@ -370,7 +384,7 @@ class PrettyPrinter:
 
     def _pprint_tuple(self, object, stream, indent, allowance, context, level):
         stream.write(self._format_block_start('(', indent))
-        if len(object) == 1 and not self._expand:
+        if len(object) == 1 and self._compact:
             endchar = ',)'
         else:
             endchar = ')'
@@ -391,7 +405,7 @@ class PrettyPrinter:
         else:
             stream.write(self._format_block_start(typ.__name__ + '({', indent))
             endchar = '})'
-            if not self._expand:
+            if self._compact:
                 indent += len(typ.__name__) + 1
         object = sorted(object, key=_safe_key)
         self._format_items(object, stream, indent, allowance + len(endchar),
@@ -409,10 +423,10 @@ class PrettyPrinter:
         chunks = []
         lines = object.splitlines(True)
         if level == 1:
-            if self._expand:
-                indent += self._indent_per_level
-            else:
+            if self._compact:
                 indent += 1
+            else:
+                indent += self._indent_per_level
             allowance += 1
         max_width1 = max_width = self._width - indent
         for i, line in enumerate(lines):
@@ -465,10 +479,10 @@ class PrettyPrinter:
             return
         parens = level == 1
         if parens:
-            if self._expand:
-                indent += self._indent_per_level
-            else:
+            if self._compact:
                 indent += 1
+            else:
+                indent += self._indent_per_level
             allowance += 1
             write(self._format_block_start('(', indent))
         delim = ''
@@ -485,11 +499,11 @@ class PrettyPrinter:
     def _pprint_bytearray(self, object, stream, indent, allowance, context, level):
         write = stream.write
         write(self._format_block_start('bytearray(', indent))
-        if self._expand:
+        if self._compact:
+            recursive_indent = indent + 10
+        else:
             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(self._format_block_end(')', indent))
@@ -517,10 +531,10 @@ class PrettyPrinter:
             cls_name = 'namespace'
         else:
             cls_name = object.__class__.__name__
-        if self._expand:
-            indent += self._indent_per_level
-        else:
+        if self._compact:
             indent += len(cls_name) + 1
+        else:
+            indent += self._indent_per_level
         items = object.__dict__.items()
         stream.write(self._format_block_start(cls_name + '(', indent))
         self._format_namespace_items(items, stream, indent, allowance, context,
@@ -550,7 +564,7 @@ class PrettyPrinter:
             )
             if not last:
                 write(delimnl)
-            elif self._expand:
+            elif not self._compact:
                 write(',')
 
     def _format_namespace_items(self, items, stream, indent, allowance, context, level):
@@ -576,7 +590,7 @@ class PrettyPrinter:
                 )
             if not last:
                 write(delimnl)
-            elif self._expand:
+            elif not self._compact:
                 write(',')
 
     def _format_items(self, items, stream, indent, allowance, context, level):
@@ -618,7 +632,7 @@ class PrettyPrinter:
             self._format(ent, stream, indent,
                          allowance if last else 1,
                          context, level)
-            if last and self._expand:
+            if last and not self._compact:
                 write(',')
 
     def _repr(self, object, context, level):
@@ -643,11 +657,11 @@ class PrettyPrinter:
             return
         rdf = self._repr(object.default_factory, context, level)
         cls = object.__class__
-        if self._expand:
-            stream.write('%s(%s, ' % (cls.__name__, rdf))
-        else:
+        if self._compact:
             indent += len(cls.__name__) + 1
             stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent))
+        else:
+            stream.write('%s(%s, ' % (cls.__name__, rdf))
         self._pprint_dict(object, stream, indent, allowance + 1, context,
                           level)
         stream.write(')')
@@ -681,14 +695,14 @@ class PrettyPrinter:
         cls = object.__class__
         stream.write(self._format_block_start(cls.__name__ + '(',
                                               indent + self._indent_per_level))
-        if self._expand:
-            indent += self._indent_per_level
-        else:
+        if self._compact:
             indent += len(cls.__name__) + 1
+        else:
+            indent += self._indent_per_level
         for i, m in enumerate(object.maps):
             if i == len(object.maps) - 1:
                 self._format(m, stream, indent, allowance + 1, context, level)
-                if self._expand:
+                if not self._compact:
                     stream.write(',')
                 stream.write(self._format_block_end(')', indent - self._indent_per_level))
             else:
@@ -703,7 +717,7 @@ class PrettyPrinter:
             return
         cls = object.__class__
         stream.write(self._format_block_start(cls.__name__ + '([', indent))
-        if not self._expand:
+        if self._compact:
             indent += len(cls.__name__) + 1
         if object.maxlen is None:
             self._format_items(object, stream, indent, allowance + 2,
@@ -713,10 +727,10 @@ class PrettyPrinter:
             self._format_items(object, stream, indent, 2,
                                context, level)
             rml = self._repr(object.maxlen, context, level)
-            if self._expand:
-                stream.write('%s], maxlen=%s)' % ('\n' + ' ' * indent, rml))
-            else:
+            if self._compact:
                 stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml))
+            else:
+                stream.write('%s], maxlen=%s)' % ('\n' + ' ' * indent, rml))
 
     _dispatch[_collections.deque.__repr__] = _pprint_deque
 
@@ -737,10 +751,10 @@ class PrettyPrinter:
 
     def _pprint_template(self, object, stream, indent, allowance, context, level):
         cls_name = object.__class__.__name__
-        if self._expand:
-            indent += self._indent_per_level
-        else:
+        if self._compact:
             indent += len(cls_name) + 1
+        else:
+            indent += self._indent_per_level
 
         items = (
             ("strings", object.strings),
@@ -756,7 +770,20 @@ class PrettyPrinter:
 
     def _pprint_interpolation(self, object, stream, indent, allowance, context, level):
         cls_name = object.__class__.__name__
-        if self._expand:
+        if self._compact:
+            indent += len(cls_name)
+            items = (
+                object.value,
+                object.expression,
+                object.conversion,
+                object.format_spec,
+            )
+            stream.write(cls_name + "(")
+            self._format_items(
+                items, stream, indent, allowance, context, level
+            )
+            stream.write(")")
+        else:
             indent += self._indent_per_level
             items = (
                 ("value", object.value),
@@ -771,19 +798,6 @@ class PrettyPrinter:
             stream.write(
                 self._format_block_end(")", indent - self._indent_per_level)
             )
-        else:
-            indent += len(cls_name)
-            items = (
-                object.value,
-                object.expression,
-                object.conversion,
-                object.format_spec,
-            )
-            stream.write(cls_name + "(")
-            self._format_items(
-                items, stream, indent, allowance, context, level
-            )
-            stream.write(")")
 
     t = t"{0}"
     _dispatch[type(t).__repr__] = _pprint_template
index 828440a993a975d155c941332b63c9738411e494..425fb85e93558d2593f860c5ff30ab84423bf0b0 100644 (file)
@@ -168,54 +168,56 @@ You can get the information from the list type:
 
     >>> import pprint
     >>> pprint.pprint(dir(list))    # like list.__dict__.keys(), but sorted
-    ['__add__',
-     '__class__',
-     '__class_getitem__',
-     '__contains__',
-     '__delattr__',
-     '__delitem__',
-     '__dir__',
-     '__doc__',
-     '__eq__',
-     '__format__',
-     '__ge__',
-     '__getattribute__',
-     '__getitem__',
-     '__getstate__',
-     '__gt__',
-     '__hash__',
-     '__iadd__',
-     '__imul__',
-     '__init__',
-     '__init_subclass__',
-     '__iter__',
-     '__le__',
-     '__len__',
-     '__lt__',
-     '__mul__',
-     '__ne__',
-     '__new__',
-     '__reduce__',
-     '__reduce_ex__',
-     '__repr__',
-     '__reversed__',
-     '__rmul__',
-     '__setattr__',
-     '__setitem__',
-     '__sizeof__',
-     '__str__',
-     '__subclasshook__',
-     'append',
-     'clear',
-     'copy',
-     'count',
-     'extend',
-     'index',
-     'insert',
-     'pop',
-     'remove',
-     'reverse',
-     'sort']
+    [
+        '__add__',
+        '__class__',
+        '__class_getitem__',
+        '__contains__',
+        '__delattr__',
+        '__delitem__',
+        '__dir__',
+        '__doc__',
+        '__eq__',
+        '__format__',
+        '__ge__',
+        '__getattribute__',
+        '__getitem__',
+        '__getstate__',
+        '__gt__',
+        '__hash__',
+        '__iadd__',
+        '__imul__',
+        '__init__',
+        '__init_subclass__',
+        '__iter__',
+        '__le__',
+        '__len__',
+        '__lt__',
+        '__mul__',
+        '__ne__',
+        '__new__',
+        '__reduce__',
+        '__reduce_ex__',
+        '__repr__',
+        '__reversed__',
+        '__rmul__',
+        '__setattr__',
+        '__setitem__',
+        '__sizeof__',
+        '__str__',
+        '__subclasshook__',
+        'append',
+        'clear',
+        'copy',
+        'count',
+        'extend',
+        'index',
+        'insert',
+        'pop',
+        'remove',
+        'reverse',
+        'sort',
+    ]
 
 The new introspection API gives more information than the old one:  in
 addition to the regular methods, it also shows the methods that are
index 48375cf459ea0b15cd33dc613b09392984718fcf..55a3c654aa0a471a0c1c3d4ec331222a5dabcbb8 100644 (file)
@@ -786,11 +786,7 @@ class CommandLineTest(unittest.TestCase):
             'b': ('character string', b'byte string'),
             'c': 'string'
         }
-        expect = '''
-            {'a': [1, 2.0, (3+4j)],
-             'b': ('character string', b'byte string'),
-             'c': 'string'}
-        '''
+        expect = "{'a': [1, 2.0, (3+4j)], 'b': ('character string', b'byte string'), 'c': 'string'}"
         self.set_pickle_data(data)
 
         with self.subTest(data=data):
index 041c2072b9e253a9ace901508e6c8aa6e0ed8bd5..f439782f53e6fb9a8cad4c2a4824f38659fa9031 100644 (file)
@@ -3,6 +3,7 @@
 import collections
 import contextlib
 import dataclasses
+import functools
 import io
 import itertools
 import pprint
@@ -15,6 +16,10 @@ from collections.abc import ItemsView, KeysView, Mapping, MappingView, ValuesVie
 from test.support import cpython_only
 from test.support.import_helper import ensure_lazy_imports
 
+# Pin pre-3.15 width/indent for existing formatting tests.
+# compact=True keeps the legacy non-JSON-style container wrapping.
+_pformat = functools.partial(pprint.pformat, indent=1, width=80, compact=True)
+
 # list, tuple and dict subclasses that do or don't overwrite __repr__
 class list2(list):
     pass
@@ -164,7 +169,6 @@ class QueryTestCase(unittest.TestCase):
         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
@@ -284,10 +288,10 @@ class QueryTestCase(unittest.TestCase):
                        True, False, None, ...,
                       ):
             native = repr(simple)
-            self.assertEqual(pprint.pformat(simple), native)
-            self.assertEqual(pprint.pformat(simple, width=1, indent=0)
+            self.assertEqual(_pformat(simple), native)
+            self.assertEqual(_pformat(simple, width=1, indent=0)
                              .replace('\n', ' '), native)
-            self.assertEqual(pprint.pformat(simple, underscore_numbers=True), native)
+            self.assertEqual(_pformat(simple, underscore_numbers=True), native)
             self.assertEqual(pprint.saferepr(simple), native)
 
     def test_container_repr_override_called(self):
@@ -318,8 +322,8 @@ class QueryTestCase(unittest.TestCase):
                     ):
             native = repr(cont)
             expected = '*' * len(native)
-            self.assertEqual(pprint.pformat(cont), expected)
-            self.assertEqual(pprint.pformat(cont, width=1, indent=0), expected)
+            self.assertEqual(_pformat(cont), expected)
+            self.assertEqual(_pformat(cont, width=1, indent=0), expected)
             self.assertEqual(pprint.saferepr(cont), expected)
 
     def test_basic_line_wrap(self):
@@ -340,7 +344,7 @@ class QueryTestCase(unittest.TestCase):
  'read_io_runtime_us': 0,
  'write_io_runtime_us': 43690}"""
         for type in [dict, dict2]:
-            self.assertEqual(pprint.pformat(type(o)), exp)
+            self.assertEqual(_pformat(type(o)), exp)
 
         exp = """\
 frozendict({'RPM_cal': 0,
@@ -350,7 +354,7 @@ frozendict({'RPM_cal': 0,
             'main_code_runtime_us': 0,
             'read_io_runtime_us': 0,
             'write_io_runtime_us': 43690})"""
-        self.assertEqual(pprint.pformat(frozendict(o)), exp)
+        self.assertEqual(_pformat(frozendict(o)), exp)
         exp = """\
 frozendict2({'RPM_cal': 0,
              'RPM_cal2': 48059,
@@ -359,79 +363,79 @@ frozendict2({'RPM_cal': 0,
              'main_code_runtime_us': 0,
              'read_io_runtime_us': 0,
              'write_io_runtime_us': 43690})"""
-        self.assertEqual(pprint.pformat(frozendict2(o)), exp)
+        self.assertEqual(_pformat(frozendict2(o)), exp)
 
         o = range(100)
         exp = 'dict_keys([%s])' % ',\n '.join(map(str, o))
         keys = dict.fromkeys(o).keys()
-        self.assertEqual(pprint.pformat(keys), exp)
+        self.assertEqual(_pformat(keys, width=1), exp)
         keys = frozendict.fromkeys(o).keys()
-        self.assertEqual(pprint.pformat(keys), exp)
+        self.assertEqual(_pformat(keys, width=1), exp)
 
         o = range(100)
         exp = 'dict_values([%s])' % ',\n '.join(map(str, o))
         values = {v: v for v in o}.values()
-        self.assertEqual(pprint.pformat(values), exp)
+        self.assertEqual(_pformat(values, width=1), exp)
         values = frozendict({v: v for v in o}).values()
-        self.assertEqual(pprint.pformat(values), exp)
+        self.assertEqual(_pformat(values, width=1), exp)
 
         o = range(100)
         exp = 'dict_items([%s])' % ',\n '.join("(%s, %s)" % (i, i) for i in o)
         items = {v: v for v in o}.items()
-        self.assertEqual(pprint.pformat(items), exp)
+        self.assertEqual(_pformat(items, width=11), exp)
         items = frozendict({v: v for v in o}).items()
-        self.assertEqual(pprint.pformat(items), exp)
+        self.assertEqual(_pformat(items, width=11), exp)
 
         o = range(100)
         exp = 'odict_keys([%s])' % ',\n '.join(map(str, o))
         keys = collections.OrderedDict.fromkeys(o).keys()
-        self.assertEqual(pprint.pformat(keys), exp)
+        self.assertEqual(_pformat(keys, width=1), exp)
 
         o = range(100)
         exp = 'odict_values([%s])' % ',\n '.join(map(str, o))
         values = collections.OrderedDict({v: v for v in o}).values()
-        self.assertEqual(pprint.pformat(values), exp)
+        self.assertEqual(_pformat(values, width=1), exp)
 
         o = range(100)
         exp = 'odict_items([%s])' % ',\n '.join("(%s, %s)" % (i, i) for i in o)
         items = collections.OrderedDict({v: v for v in o}).items()
-        self.assertEqual(pprint.pformat(items), exp)
+        self.assertEqual(_pformat(items, width=11), exp)
 
         o = range(100)
         exp = 'KeysView({%s})' % (': None,\n '.join(map(str, o)) + ': None')
         keys_view = KeysView(dict.fromkeys(o))
-        self.assertEqual(pprint.pformat(keys_view), exp)
+        self.assertEqual(_pformat(keys_view), exp)
 
         o = range(100)
         exp = 'ItemsView({%s})' % (': None,\n '.join(map(str, o)) + ': None')
         items_view = ItemsView(dict.fromkeys(o))
-        self.assertEqual(pprint.pformat(items_view), exp)
+        self.assertEqual(_pformat(items_view), exp)
 
         o = range(100)
         exp = 'MappingView({%s})' % (': None,\n '.join(map(str, o)) + ': None')
         mapping_view = MappingView(dict.fromkeys(o))
-        self.assertEqual(pprint.pformat(mapping_view), exp)
+        self.assertEqual(_pformat(mapping_view), exp)
 
         o = range(100)
         exp = 'ValuesView({%s})' % (': None,\n '.join(map(str, o)) + ': None')
         values_view = ValuesView(dict.fromkeys(o))
-        self.assertEqual(pprint.pformat(values_view), exp)
+        self.assertEqual(_pformat(values_view), exp)
 
         o = range(100)
         exp = '[%s]' % ',\n '.join(map(str, o))
         for type in [list, list2]:
-            self.assertEqual(pprint.pformat(type(o)), exp)
+            self.assertEqual(_pformat(type(o), width=1), exp)
 
         o = tuple(range(100))
         exp = '(%s)' % ',\n '.join(map(str, o))
         for type in [tuple, tuple2]:
-            self.assertEqual(pprint.pformat(type(o)), exp)
+            self.assertEqual(_pformat(type(o), width=1), exp)
 
         # indent parameter
         o = range(100)
         exp = '[   %s]' % ',\n    '.join(map(str, o))
         for type in [list, list2]:
-            self.assertEqual(pprint.pformat(type(o), indent=4), exp)
+            self.assertEqual(_pformat(type(o), indent=4, width=1), exp)
 
     def test_nested_indentations(self):
         o1 = list(range(10))
@@ -440,13 +444,13 @@ frozendict2({'RPM_cal': 0,
         expected = """\
 [   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
     {'first': 1, 'second': 2, 'third': 3}]"""
-        self.assertEqual(pprint.pformat(o, indent=4, width=42), expected)
+        self.assertEqual(pprint.pformat(o, indent=4, width=42, compact=True), expected)
         expected = """\
 [   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
     {   'first': 1,
         'second': 2,
         'third': 3}]"""
-        self.assertEqual(pprint.pformat(o, indent=4, width=41), expected)
+        self.assertEqual(pprint.pformat(o, indent=4, width=41, compact=True), expected)
 
     def test_width(self):
         expected = """\
@@ -460,17 +464,15 @@ frozendict2({'RPM_cal': 0,
  [[[[[1, 2, 3],
      '1 2']]]]]"""
         o = eval(expected)
-        self.assertEqual(pprint.pformat(o, width=15), expected)
-        self.assertEqual(pprint.pformat(o, width=16), expected)
-        self.assertEqual(pprint.pformat(o, width=25), expected)
-        self.assertEqual(pprint.pformat(o, width=14), """\
-[[[[[[1,
-      2,
+        self.assertEqual(_pformat(o, width=15), expected)
+        self.assertEqual(_pformat(o, width=16), expected)
+        self.assertEqual(_pformat(o, width=25), expected)
+        self.assertEqual(_pformat(o, width=14), """\
+[[[[[[1, 2,
       3],
      '1 '
      '2']]]],
- {1: [1,
-      2,
+ {1: [1, 2,
       3],
   2: [12,
       34]},
@@ -480,15 +482,14 @@ frozendict2({'RPM_cal': 0,
   'ef',),
  set2({1,
        23}),
- [[[[[1,
-      2,
+ [[[[[1, 2,
       3],
      '1 '
      '2']]]]]""")
 
     def test_integer(self):
-        self.assertEqual(pprint.pformat(1234567), '1234567')
-        self.assertEqual(pprint.pformat(1234567, underscore_numbers=True), '1_234_567')
+        self.assertEqual(_pformat(1234567), '1234567')
+        self.assertEqual(_pformat(1234567, underscore_numbers=True), '1_234_567')
 
         class Temperature(int):
             def __new__(cls, celsius_degrees):
@@ -496,7 +497,7 @@ frozendict2({'RPM_cal': 0,
             def __repr__(self):
                 kelvin_degrees = self + 273.15
                 return f"{kelvin_degrees:.2f}°K"
-        self.assertEqual(pprint.pformat(Temperature(1000)), '1273.15°K')
+        self.assertEqual(_pformat(Temperature(1000)), '1273.15°K')
 
     def test_sorted_dict(self):
         # Starting in Python 2.5, pprint sorts dict displays by key regardless
@@ -504,8 +505,8 @@ frozendict2({'RPM_cal': 0,
         # Before the change, on 32-bit Windows pformat() gave order
         # 'a', 'c', 'b' here, so this test failed.
         d = {'a': 1, 'b': 1, 'c': 1}
-        self.assertEqual(pprint.pformat(d), "{'a': 1, 'b': 1, 'c': 1}")
-        self.assertEqual(pprint.pformat([d, d]),
+        self.assertEqual(_pformat(d), "{'a': 1, 'b': 1, 'c': 1}")
+        self.assertEqual(_pformat([d, d]),
             "[{'a': 1, 'b': 1, 'c': 1}, {'a': 1, 'b': 1, 'c': 1}]")
 
         # The next one is kind of goofy.  The sorted order depends on the
@@ -513,63 +514,42 @@ frozendict2({'RPM_cal': 0,
         # Python 2.5, this was in the test_same_as_repr() test.  It's worth
         # keeping around for now because it's one of few tests of pprint
         # against a crazy mix of types.
-        self.assertEqual(pprint.pformat({"xy\tab\n": (3,), 5: [[]], (): {}}),
+        self.assertEqual(_pformat({"xy\tab\n": (3,), 5: [[]], (): {}}),
             r"{5: [[]], 'xy\tab\n': (3,), (): {}}")
 
     def test_sort_dict(self):
         d = dict.fromkeys('cba')
-        self.assertEqual(pprint.pformat(d, sort_dicts=False), "{'c': None, 'b': None, 'a': None}")
-        self.assertEqual(pprint.pformat([d, d], sort_dicts=False),
+        self.assertEqual(_pformat(d, sort_dicts=False), "{'c': None, 'b': None, 'a': None}")
+        self.assertEqual(_pformat([d, d], sort_dicts=False),
             "[{'c': None, 'b': None, 'a': None}, {'c': None, 'b': None, 'a': None}]")
 
     def test_ordered_dict(self):
         d = collections.OrderedDict()
-        self.assertEqual(pprint.pformat(d, width=1), 'OrderedDict()')
+        self.assertEqual(_pformat(d, width=1), 'OrderedDict()')
         d = collections.OrderedDict([])
-        self.assertEqual(pprint.pformat(d, width=1), 'OrderedDict()')
+        self.assertEqual(_pformat(d, width=1), 'OrderedDict()')
         words = 'the quick brown fox jumped over a lazy dog'.split()
         d = collections.OrderedDict(zip(words, itertools.count()))
-        self.assertEqual(pprint.pformat(d),
-"""\
-OrderedDict([('the', 0),
-             ('quick', 1),
-             ('brown', 2),
-             ('fox', 3),
-             ('jumped', 4),
-             ('over', 5),
-             ('a', 6),
-             ('lazy', 7),
-             ('dog', 8)])""")
-        self.assertEqual(pprint.pformat(d.keys(), sort_dicts=False),
+        self.assertEqual(_pformat(d),
 """\
-odict_keys(['the',
- 'quick',
- 'brown',
- 'fox',
- 'jumped',
- 'over',
- 'a',
- 'lazy',
- 'dog'])""")
-        self.assertEqual(pprint.pformat(d.items(), sort_dicts=False),
+OrderedDict([('the', 0), ('quick', 1), ('brown', 2), ('fox', 3), ('jumped', 4),
+             ('over', 5), ('a', 6), ('lazy', 7), ('dog', 8)])""")
+        self.assertEqual(
+            _pformat(d.keys(), sort_dicts=False),
+            "odict_keys(['the', 'quick', 'brown', 'fox', 'jumped', 'over', 'a', 'lazy', 'dog'])",
+        )
+        self.assertEqual(_pformat(d.items(), sort_dicts=False),
 """\
-odict_items([('the', 0),
- ('quick', 1),
- ('brown', 2),
- ('fox', 3),
- ('jumped', 4),
- ('over', 5),
- ('a', 6),
- ('lazy', 7),
- ('dog', 8)])""")
-        self.assertEqual(pprint.pformat(d.values(), sort_dicts=False),
+odict_items([('the', 0), ('quick', 1), ('brown', 2), ('fox', 3), ('jumped', 4), ('over', 5),
+ ('a', 6), ('lazy', 7), ('dog', 8)])""")
+        self.assertEqual(_pformat(d.values(), sort_dicts=False),
                          "odict_values([0, 1, 2, 3, 4, 5, 6, 7, 8])")
 
     def test_mapping_proxy(self):
         words = 'the quick brown fox jumped over a lazy dog'.split()
         d = dict(zip(words, itertools.count()))
         m = types.MappingProxyType(d)
-        self.assertEqual(pprint.pformat(m), """\
+        self.assertEqual(_pformat(m), """\
 mappingproxy({'a': 6,
               'brown': 2,
               'dog': 8,
@@ -581,49 +561,81 @@ mappingproxy({'a': 6,
               'the': 0})""")
         d = collections.OrderedDict(zip(words, itertools.count()))
         m = types.MappingProxyType(d)
-        self.assertEqual(pprint.pformat(m), """\
-mappingproxy(OrderedDict([('the', 0),
-                          ('quick', 1),
-                          ('brown', 2),
-                          ('fox', 3),
-                          ('jumped', 4),
-                          ('over', 5),
-                          ('a', 6),
-                          ('lazy', 7),
+        self.assertEqual(_pformat(m), """\
+mappingproxy(OrderedDict([('the', 0), ('quick', 1), ('brown', 2), ('fox', 3),
+                          ('jumped', 4), ('over', 5), ('a', 6), ('lazy', 7),
                           ('dog', 8)]))""")
 
     def test_dict_views(self):
         for dict_class in (dict, collections.OrderedDict, collections.Counter):
             empty = dict_class({})
             short = dict_class(dict(zip('edcba', 'edcba')))
-            long = dict_class(dict((chr(x), chr(x)) for x in range(90, 64, -1)))
-            lengths = {"empty": empty, "short": short, "long": long}
+            lengths = {"empty": empty, "short": short}
             prefix = "odict" if dict_class is collections.OrderedDict else "dict"
             for name, d in lengths.items():
                 with self.subTest(length=name, prefix=prefix):
-                    is_short = len(d) < 6
-                    joiner = ", " if is_short else ",\n "
                     k = d.keys()
                     v = d.values()
                     i = d.items()
-                    self.assertEqual(pprint.pformat(k, sort_dicts=True),
+                    self.assertEqual(_pformat(k, sort_dicts=True),
                                      prefix + "_keys([%s])" %
-                                     joiner.join(repr(key) for key in sorted(k)))
-                    self.assertEqual(pprint.pformat(v, sort_dicts=True),
+                                     ", ".join(repr(key) for key in sorted(k)))
+                    self.assertEqual(_pformat(v, sort_dicts=True),
                                      prefix + "_values([%s])" %
-                                     joiner.join(repr(val) for val in sorted(v)))
-                    self.assertEqual(pprint.pformat(i, sort_dicts=True),
+                                     ", ".join(repr(val) for val in sorted(v)))
+                    self.assertEqual(_pformat(i, sort_dicts=True),
                                      prefix + "_items([%s])" %
-                                     joiner.join(repr(item) for item in sorted(i)))
-                    self.assertEqual(pprint.pformat(k, sort_dicts=False),
+                                     ", ".join(repr(item) for item in sorted(i)))
+                    self.assertEqual(_pformat(k, sort_dicts=False),
                                      prefix + "_keys([%s])" %
-                                     joiner.join(repr(key) for key in k))
-                    self.assertEqual(pprint.pformat(v, sort_dicts=False),
+                                     ", ".join(repr(key) for key in k))
+                    self.assertEqual(_pformat(v, sort_dicts=False),
                                      prefix + "_values([%s])" %
-                                     joiner.join(repr(val) for val in v))
-                    self.assertEqual(pprint.pformat(i, sort_dicts=False),
+                                     ", ".join(repr(val) for val in v))
+                    self.assertEqual(_pformat(i, sort_dicts=False),
                                      prefix + "_items([%s])" %
-                                     joiner.join(repr(item) for item in i))
+                                     ", ".join(repr(item) for item in i))
+
+        # Long case: views wrap with compact-mode packing.
+        long = dict((chr(x), chr(x)) for x in range(90, 64, -1))
+        sorted_keys = (
+            "['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\n"
+            " 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']"
+        )
+        unsorted_keys = (
+            "['Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K',\n"
+            " 'J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A']"
+        )
+        sorted_items = (
+            "[('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D'), ('E', 'E'), ('F', 'F'),\n"
+            " ('G', 'G'), ('H', 'H'), ('I', 'I'), ('J', 'J'), ('K', 'K'), ('L', 'L'),\n"
+            " ('M', 'M'), ('N', 'N'), ('O', 'O'), ('P', 'P'), ('Q', 'Q'), ('R', 'R'),\n"
+            " ('S', 'S'), ('T', 'T'), ('U', 'U'), ('V', 'V'), ('W', 'W'), ('X', 'X'),\n"
+            " ('Y', 'Y'), ('Z', 'Z')]"
+        )
+        unsorted_items = (
+            "[('Z', 'Z'), ('Y', 'Y'), ('X', 'X'), ('W', 'W'), ('V', 'V'), ('U', 'U'),\n"
+            " ('T', 'T'), ('S', 'S'), ('R', 'R'), ('Q', 'Q'), ('P', 'P'), ('O', 'O'),\n"
+            " ('N', 'N'), ('M', 'M'), ('L', 'L'), ('K', 'K'), ('J', 'J'), ('I', 'I'),\n"
+            " ('H', 'H'), ('G', 'G'), ('F', 'F'), ('E', 'E'), ('D', 'D'), ('C', 'C'),\n"
+            " ('B', 'B'), ('A', 'A')]"
+        )
+        for dict_class in (dict, collections.OrderedDict, collections.Counter):
+            d = dict_class(long)
+            prefix = "odict" if dict_class is collections.OrderedDict else "dict"
+            with self.subTest(length="long", prefix=prefix):
+                self.assertEqual(_pformat(d.keys(), sort_dicts=True),
+                                 f"{prefix}_keys({sorted_keys})")
+                self.assertEqual(_pformat(d.values(), sort_dicts=True),
+                                 f"{prefix}_values({sorted_keys})")
+                self.assertEqual(_pformat(d.items(), sort_dicts=True),
+                                 f"{prefix}_items({sorted_items})")
+                self.assertEqual(_pformat(d.keys(), sort_dicts=False),
+                                 f"{prefix}_keys({unsorted_keys})")
+                self.assertEqual(_pformat(d.values(), sort_dicts=False),
+                                 f"{prefix}_values({unsorted_keys})")
+                self.assertEqual(_pformat(d.items(), sort_dicts=False),
+                                 f"{prefix}_items({unsorted_items})")
 
     def test_abc_views(self):
         empty = {}
@@ -641,55 +653,55 @@ mappingproxy(OrderedDict([('the', 0),
                 s = sorted(i)
                 joined_items = "({%s})" % joiner.join(["%r: %r" % (k, v) for (k, v) in i])
                 sorted_items = "({%s})" % joiner.join(["%r: %r" % (k, v) for (k, v) in s])
-                self.assertEqual(pprint.pformat(KeysView(d), sort_dicts=True),
+                self.assertEqual(_pformat(KeysView(d), sort_dicts=True),
                                  KeysView.__name__ + sorted_items)
-                self.assertEqual(pprint.pformat(ItemsView(d), sort_dicts=True),
+                self.assertEqual(_pformat(ItemsView(d), sort_dicts=True),
                                  ItemsView.__name__ + sorted_items)
-                self.assertEqual(pprint.pformat(MappingView(d), sort_dicts=True),
+                self.assertEqual(_pformat(MappingView(d), sort_dicts=True),
                                  MappingView.__name__ + sorted_items)
-                self.assertEqual(pprint.pformat(MV(d), sort_dicts=True),
+                self.assertEqual(_pformat(MV(d), sort_dicts=True),
                                  MV.__name__ + sorted_items)
-                self.assertEqual(pprint.pformat(ValuesView(d), sort_dicts=True),
+                self.assertEqual(_pformat(ValuesView(d), sort_dicts=True),
                                  ValuesView.__name__ + sorted_items)
-                self.assertEqual(pprint.pformat(KeysView(d), sort_dicts=False),
+                self.assertEqual(_pformat(KeysView(d), sort_dicts=False),
                                  KeysView.__name__ + joined_items)
-                self.assertEqual(pprint.pformat(ItemsView(d), sort_dicts=False),
+                self.assertEqual(_pformat(ItemsView(d), sort_dicts=False),
                                  ItemsView.__name__ + joined_items)
-                self.assertEqual(pprint.pformat(MappingView(d), sort_dicts=False),
+                self.assertEqual(_pformat(MappingView(d), sort_dicts=False),
                                  MappingView.__name__ + joined_items)
-                self.assertEqual(pprint.pformat(MV(d), sort_dicts=False),
+                self.assertEqual(_pformat(MV(d), sort_dicts=False),
                                  MV.__name__ + joined_items)
-                self.assertEqual(pprint.pformat(ValuesView(d), sort_dicts=False),
+                self.assertEqual(_pformat(ValuesView(d), sort_dicts=False),
                                  ValuesView.__name__ + joined_items)
 
     def test_nested_views(self):
         d = {1: MappingView({1: MappingView({1: MappingView({1: 2})})})}
         self.assertEqual(repr(d),
                          "{1: MappingView({1: MappingView({1: MappingView({1: 2})})})}")
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
                          "{1: MappingView({1: MappingView({1: MappingView({1: 2})})})}")
-        self.assertEqual(pprint.pformat(d, depth=2),
+        self.assertEqual(_pformat(d, depth=2),
                          "{1: MappingView({1: {...}})}")
         d = {}
         d1 = {1: d.values()}
         d2 = {1: d1.values()}
         d3 = {1: d2.values()}
-        self.assertEqual(pprint.pformat(d3),
+        self.assertEqual(_pformat(d3),
                          "{1: dict_values([dict_values([dict_values([])])])}")
-        self.assertEqual(pprint.pformat(d3, depth=2),
+        self.assertEqual(_pformat(d3, depth=2),
                          "{1: dict_values([{...}])}")
 
     def test_unorderable_items_views(self):
         """Check that views with unorderable items have stable sorting."""
         d = dict((((3+1j), 3), ((1+1j), (1+0j)), (1j, 0j), (500, None), (499, None)))
         iv = ItemsView(d)
-        self.assertEqual(pprint.pformat(iv),
-                         pprint.pformat(iv))
-        self.assertTrue(pprint.pformat(iv).endswith(", 499: None, 500: None})"),
-                        pprint.pformat(iv))
-        self.assertEqual(pprint.pformat(d.items()),  # Won't be equal unless _safe_tuple
-                         pprint.pformat(d.items()))  # is used in _safe_repr
-        self.assertTrue(pprint.pformat(d.items()).endswith(", (499, None), (500, None)])"))
+        self.assertEqual(_pformat(iv),
+                         _pformat(iv))
+        self.assertTrue(_pformat(iv).endswith(", 499: None, 500: None})"),
+                        _pformat(iv))
+        self.assertEqual(_pformat(d.items()),  # Won't be equal unless _safe_tuple
+                         _pformat(d.items()))  # is used in _safe_repr
+        self.assertTrue(_pformat(d.items()).endswith(", (499, None), (500, None)])"))
 
     def test_mapping_view_subclass_no_mapping(self):
         class BMV(MappingView):
@@ -698,7 +710,7 @@ mappingproxy(OrderedDict([('the', 0),
                 self.mapping = self._mapping
                 del self._mapping
 
-        self.assertRaises(AttributeError, pprint.pformat, BMV({}))
+        self.assertRaises(AttributeError, _pformat, BMV({}))
 
     def test_mapping_subclass_repr(self):
         """Test that mapping ABC views use their ._mapping's __repr__."""
@@ -722,10 +734,10 @@ mappingproxy(OrderedDict([('the', 0),
         self.assertEqual(repr(m), "MyMapping(['test', 1])")
         short_view_repr = "%s(MyMapping(['test', 1]))"
         self.assertEqual(repr(m.keys()), short_view_repr % "KeysView")
-        self.assertEqual(pprint.pformat(m.items()), short_view_repr % "ItemsView")
-        self.assertEqual(pprint.pformat(m.keys()), short_view_repr % "KeysView")
-        self.assertEqual(pprint.pformat(MappingView(m)), short_view_repr % "MappingView")
-        self.assertEqual(pprint.pformat(m.values()), short_view_repr % "ValuesView")
+        self.assertEqual(_pformat(m.items()), short_view_repr % "ItemsView")
+        self.assertEqual(_pformat(m.keys()), short_view_repr % "KeysView")
+        self.assertEqual(_pformat(MappingView(m)), short_view_repr % "MappingView")
+        self.assertEqual(_pformat(m.values()), short_view_repr % "ValuesView")
 
         alpha = "abcdefghijklmnopqrstuvwxyz"
         m = MyMapping(alpha)
@@ -733,19 +745,19 @@ mappingproxy(OrderedDict([('the', 0),
         long_view_repr = "%%s(MyMapping([%s]))" % alpha_repr
         self.assertEqual(repr(m), "MyMapping([%s])" % alpha_repr)
         self.assertEqual(repr(m.keys()), long_view_repr % "KeysView")
-        self.assertEqual(pprint.pformat(m.items()), long_view_repr % "ItemsView")
-        self.assertEqual(pprint.pformat(m.keys()), long_view_repr % "KeysView")
-        self.assertEqual(pprint.pformat(MappingView(m)), long_view_repr % "MappingView")
-        self.assertEqual(pprint.pformat(m.values()), long_view_repr % "ValuesView")
+        self.assertEqual(_pformat(m.items()), long_view_repr % "ItemsView")
+        self.assertEqual(_pformat(m.keys()), long_view_repr % "KeysView")
+        self.assertEqual(_pformat(MappingView(m)), long_view_repr % "MappingView")
+        self.assertEqual(_pformat(m.values()), long_view_repr % "ValuesView")
 
     def test_empty_simple_namespace(self):
         ns = types.SimpleNamespace()
-        formatted = pprint.pformat(ns)
+        formatted = _pformat(ns)
         self.assertEqual(formatted, "namespace()")
 
     def test_small_simple_namespace(self):
         ns = types.SimpleNamespace(a=1, b=2)
-        formatted = pprint.pformat(ns)
+        formatted = _pformat(ns)
         self.assertEqual(formatted, "namespace(a=1, b=2)")
 
     def test_simple_namespace(self):
@@ -760,7 +772,7 @@ mappingproxy(OrderedDict([('the', 0),
             lazy=7,
             dog=8,
         )
-        formatted = pprint.pformat(ns, width=60, indent=4)
+        formatted = pprint.pformat(ns, width=60, indent=4, compact=True)
         self.assertEqual(formatted, """\
 namespace(the=0,
           quick=1,
@@ -785,7 +797,7 @@ namespace(the=0,
             lazy=7,
             dog=8,
         )
-        formatted = pprint.pformat(ns, width=60)
+        formatted = _pformat(ns, width=60)
         self.assertEqual(formatted, """\
 AdvancedNamespace(the=0,
                   quick=1,
@@ -799,17 +811,17 @@ AdvancedNamespace(the=0,
 
     def test_empty_dataclass(self):
         dc = dataclasses.make_dataclass("MyDataclass", ())()
-        formatted = pprint.pformat(dc)
+        formatted = _pformat(dc)
         self.assertEqual(formatted, "MyDataclass()")
 
     def test_small_dataclass(self):
         dc = dataclass1("text", 123)
-        formatted = pprint.pformat(dc)
+        formatted = _pformat(dc)
         self.assertEqual(formatted, "dataclass1(field1='text', field2=123, field3=False)")
 
     def test_larger_dataclass(self):
         dc = dataclass1("some fairly long text", int(1e10), True)
-        formatted = pprint.pformat([dc, dc], width=60, indent=4)
+        formatted = pprint.pformat([dc, dc], width=60, indent=4, compact=True)
         self.assertEqual(formatted, """\
 [   dataclass1(field1='some fairly long text',
                field2=10000000000,
@@ -820,12 +832,12 @@ AdvancedNamespace(the=0,
 
     def test_dataclass_with_repr(self):
         dc = dataclass2()
-        formatted = pprint.pformat(dc, width=20)
+        formatted = _pformat(dc, width=20)
         self.assertEqual(formatted, "custom repr that doesn't fit within pprint width")
 
     def test_dataclass_no_repr(self):
         dc = dataclass3()
-        formatted = pprint.pformat(dc, width=10)
+        formatted = _pformat(dc, width=10)
         self.assertRegex(
             formatted,
             fr"<{re.escape(__name__)}.dataclass3 object at \w+>",
@@ -834,7 +846,7 @@ AdvancedNamespace(the=0,
     def test_recursive_dataclass(self):
         dc = dataclass4(None)
         dc.a = dc
-        formatted = pprint.pformat(dc, width=10)
+        formatted = _pformat(dc, width=10)
         self.assertEqual(formatted, """\
 dataclass4(a=...,
            b=1)""")
@@ -844,7 +856,7 @@ dataclass4(a=...,
         dc6 = dataclass6(None)
         dc5.a = dc6
         dc6.c = dc5
-        formatted = pprint.pformat(dc5, width=10)
+        formatted = _pformat(dc5, width=10)
         self.assertEqual(formatted, """\
 dataclass5(a=dataclass6(c=...,
                         d=1),
@@ -858,7 +870,7 @@ dataclass5(a=dataclass6(c=...,
 {'names with spaces': 'should be presented using repr()',
  others.should.not.be: like.this}"""
 
-        dotted_printer = DottedPrettyPrinter()
+        dotted_printer = DottedPrettyPrinter(indent=1, compact=True)
         self.assertEqual(dotted_printer.pformat(o), exp)
 
         # length(repr(obj)) < width
@@ -870,47 +882,29 @@ dataclass5(a=dataclass6(c=...,
         self.assertEqual(dotted_printer.pformat(o2), exp2)
 
     def test_set_reprs(self):
-        self.assertEqual(pprint.pformat(set()), 'set()')
-        self.assertEqual(pprint.pformat(set(range(3))), '{0, 1, 2}')
-        self.assertEqual(pprint.pformat(set(range(7)), width=20), '''\
-{0,
- 1,
- 2,
- 3,
- 4,
- 5,
+        self.assertEqual(_pformat(set()), 'set()')
+        self.assertEqual(_pformat(set(range(3))), '{0, 1, 2}')
+        self.assertEqual(_pformat(set(range(7)), width=20), '''\
+{0, 1, 2, 3, 4, 5,
  6}''')
-        self.assertEqual(pprint.pformat(set2(range(7)), width=20), '''\
-set2({0,
-      1,
-      2,
-      3,
-      4,
-      5,
-      6})''')
-        self.assertEqual(pprint.pformat(set3(range(7)), width=20),
+        self.assertEqual(_pformat(set2(range(7)), width=20), '''\
+set2({0, 1, 2, 3, 4,
+      5, 6})''')
+        self.assertEqual(_pformat(set3(range(7)), width=20),
                          'set3({0, 1, 2, 3, 4, 5, 6})')
 
-        self.assertEqual(pprint.pformat(frozenset()), 'frozenset()')
-        self.assertEqual(pprint.pformat(frozenset(range(3))),
+        self.assertEqual(_pformat(frozenset()), 'frozenset()')
+        self.assertEqual(_pformat(frozenset(range(3))),
                          'frozenset({0, 1, 2})')
-        self.assertEqual(pprint.pformat(frozenset(range(7)), width=20), '''\
-frozenset({0,
-           1,
-           2,
-           3,
-           4,
-           5,
+        self.assertEqual(_pformat(frozenset(range(7)), width=20), '''\
+frozenset({0, 1, 2,
+           3, 4, 5,
            6})''')
-        self.assertEqual(pprint.pformat(frozenset2(range(7)), width=20), '''\
-frozenset2({0,
-            1,
-            2,
-            3,
-            4,
-            5,
+        self.assertEqual(_pformat(frozenset2(range(7)), width=20), '''\
+frozenset2({0, 1, 2,
+            3, 4, 5,
             6})''')
-        self.assertEqual(pprint.pformat(frozenset3(range(7)), width=20),
+        self.assertEqual(_pformat(frozenset3(range(7)), width=20),
                          'frozenset3({0, 1, 2, 3, 4, 5, 6})')
 
     def test_set_of_sets_reprs(self):
@@ -942,21 +936,21 @@ frozenset2({0,
         fs0 = frozenset()
         fs1 = frozenset(('abc', 'xyz'))
         data = frozenset((fs0, fs1))
-        self.assertEqual(pprint.pformat(data),
+        self.assertEqual(_pformat(data),
                          'frozenset({%r, %r})' % (fs0, fs1))
-        self.assertEqual(pprint.pformat(data), repr(data))
+        self.assertEqual(_pformat(data), repr(data))
 
         fs2 = frozenset(('one', 'two'))
         data = {fs2: frozenset((fs0, fs1))}
-        self.assertEqual(pprint.pformat(data),
+        self.assertEqual(_pformat(data),
                          "{%r: frozenset({%r, %r})}" % (fs2, fs0, fs1))
-        self.assertEqual(pprint.pformat(data), repr(data))
+        self.assertEqual(_pformat(data), repr(data))
 
         # Single-line, unordered:
         fs1 = frozenset(("xyz", "qwerty"))
         fs2 = frozenset(("abcd", "spam"))
         fs = frozenset((fs1, fs2))
-        self.assertEqual(pprint.pformat(fs), repr(fs))
+        self.assertEqual(_pformat(fs), repr(fs))
 
         # Multiline, unordered:
         def check(res, invariants):
@@ -966,7 +960,7 @@ frozenset2({0,
         fs1 = frozenset(('regular string', 'other string'))
         fs2 = frozenset(('third string', 'one more string'))
         check(
-            pprint.pformat(frozenset((fs1, fs2))),
+            _pformat(frozenset((fs1, fs2))),
             [
                 """
                 frozenset({%r,
@@ -981,7 +975,7 @@ frozenset2({0,
 
         # Everything is multiline, unordered:
         check(
-            pprint.pformat(
+            _pformat(
                 frozenset((
                     frozenset((
                         "xyz very-very long string",
@@ -1028,16 +1022,16 @@ frozenset2({0,
         nested_tuple = (1, (2, (3, (4, (5, 6)))))
         nested_dict = {1: {2: {3: {4: {5: {6: 6}}}}}}
         nested_list = [1, [2, [3, [4, [5, [6, []]]]]]]
-        self.assertEqual(pprint.pformat(nested_tuple), repr(nested_tuple))
-        self.assertEqual(pprint.pformat(nested_dict), repr(nested_dict))
-        self.assertEqual(pprint.pformat(nested_list), repr(nested_list))
+        self.assertEqual(_pformat(nested_tuple), repr(nested_tuple))
+        self.assertEqual(_pformat(nested_dict), repr(nested_dict))
+        self.assertEqual(_pformat(nested_list), repr(nested_list))
 
         lv1_tuple = '(1, (...))'
         lv1_dict = '{1: {...}}'
         lv1_list = '[1, [...]]'
-        self.assertEqual(pprint.pformat(nested_tuple, depth=1), lv1_tuple)
-        self.assertEqual(pprint.pformat(nested_dict, depth=1), lv1_dict)
-        self.assertEqual(pprint.pformat(nested_list, depth=1), lv1_list)
+        self.assertEqual(_pformat(nested_tuple, depth=1), lv1_tuple)
+        self.assertEqual(_pformat(nested_dict, depth=1), lv1_dict)
+        self.assertEqual(_pformat(nested_list, depth=1), lv1_list)
 
     def test_sort_unorderable_values(self):
         # Issue 3976:  sorted pprints fail for unorderable values.
@@ -1047,24 +1041,24 @@ frozenset2({0,
         skeys = sorted(keys, key=id)
         clean = lambda s: s.replace(' ', '').replace('\n','')
 
-        self.assertEqual(clean(pprint.pformat(set(keys))),
+        self.assertEqual(clean(_pformat(set(keys))),
             '{' + ','.join(map(repr, skeys)) + '}')
-        self.assertEqual(clean(pprint.pformat(frozenset(keys))),
+        self.assertEqual(clean(_pformat(frozenset(keys))),
             'frozenset({' + ','.join(map(repr, skeys)) + '})')
-        self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys))),
+        self.assertEqual(clean(_pformat(dict.fromkeys(keys))),
             '{' + ','.join('%r:None' % k for k in skeys) + '}')
-        self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys).keys())),
+        self.assertEqual(clean(_pformat(dict.fromkeys(keys).keys())),
             'dict_keys([' + ','.join('%r' % k for k in skeys) + '])')
-        self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys).items())),
+        self.assertEqual(clean(_pformat(dict.fromkeys(keys).items())),
             'dict_items([' + ','.join('(%r,None)' % k for k in skeys) + '])')
 
         # Issue 10017: TypeError on user-defined types as dict keys.
-        self.assertEqual(pprint.pformat({Unorderable: 0, 1: 0}),
+        self.assertEqual(_pformat({Unorderable: 0, 1: 0}),
                          '{1: 0, ' + repr(Unorderable) +': 0}')
 
         # Issue 14998: TypeError on tuples with NoneTypes as dict keys.
         keys = [(1,), (None,)]
-        self.assertEqual(pprint.pformat(dict.fromkeys(keys, 0)),
+        self.assertEqual(_pformat(dict.fromkeys(keys, 0)),
                          '{%r: 0, %r: 0}' % tuple(sorted(keys, key=id)))
 
     def test_sort_orderable_and_unorderable_values(self):
@@ -1077,24 +1071,24 @@ frozenset2({0,
         self.assertEqual(sorted([b, a]), [a, b])
         self.assertEqual(sorted([a, b]), [a, b])
         # set
-        self.assertEqual(pprint.pformat(set([b, a]), width=1),
+        self.assertEqual(_pformat(set([b, a]), width=1),
                          '{%r,\n %r}' % (a, b))
-        self.assertEqual(pprint.pformat(set([a, b]), width=1),
+        self.assertEqual(_pformat(set([a, b]), width=1),
                          '{%r,\n %r}' % (a, b))
         # dict
-        self.assertEqual(pprint.pformat(dict.fromkeys([b, a]), width=1),
+        self.assertEqual(_pformat(dict.fromkeys([b, a]), width=1),
                          '{%r: None,\n %r: None}' % (a, b))
-        self.assertEqual(pprint.pformat(dict.fromkeys([a, b]), width=1),
+        self.assertEqual(_pformat(dict.fromkeys([a, b]), width=1),
                          '{%r: None,\n %r: None}' % (a, b))
 
     def test_str_wrap(self):
         # pprint tries to wrap strings intelligently
         fox = 'the quick brown fox jumped over a lazy dog'
-        self.assertEqual(pprint.pformat(fox, width=19), """\
+        self.assertEqual(_pformat(fox, width=19), """\
 ('the quick brown '
  'fox jumped over '
  'a lazy dog')""")
-        self.assertEqual(pprint.pformat({'a': 1, 'b': fox, 'c': 2},
+        self.assertEqual(_pformat({'a': 1, 'b': fox, 'c': 2},
                                         width=25), """\
 {'a': 1,
  'b': 'the quick brown '
@@ -1107,28 +1101,28 @@ frozenset2({0,
         # - non-ASCII is allowed
         # - an apostrophe doesn't disrupt the pprint
         special = "Portons dix bons \"whiskys\"\nà l'avocat goujat\t qui fumait au zoo"
-        self.assertEqual(pprint.pformat(special, width=68), repr(special))
-        self.assertEqual(pprint.pformat(special, width=31), """\
+        self.assertEqual(_pformat(special, width=68), repr(special))
+        self.assertEqual(_pformat(special, width=31), """\
 ('Portons dix bons "whiskys"\\n'
  "à l'avocat goujat\\t qui "
  'fumait au zoo')""")
-        self.assertEqual(pprint.pformat(special, width=20), """\
+        self.assertEqual(_pformat(special, width=20), """\
 ('Portons dix bons '
  '"whiskys"\\n'
  "à l'avocat "
  'goujat\\t qui '
  'fumait au zoo')""")
-        self.assertEqual(pprint.pformat([[[[[special]]]]], width=35), """\
+        self.assertEqual(_pformat([[[[[special]]]]], width=35), """\
 [[[[['Portons dix bons "whiskys"\\n'
      "à l'avocat goujat\\t qui "
      'fumait au zoo']]]]]""")
-        self.assertEqual(pprint.pformat([[[[[special]]]]], width=25), """\
+        self.assertEqual(_pformat([[[[[special]]]]], width=25), """\
 [[[[['Portons dix bons '
      '"whiskys"\\n'
      "à l'avocat "
      'goujat\\t qui '
      'fumait au zoo']]]]]""")
-        self.assertEqual(pprint.pformat([[[[[special]]]]], width=23), """\
+        self.assertEqual(_pformat([[[[[special]]]]], width=23), """\
 [[[[['Portons dix '
      'bons "whiskys"\\n'
      "à l'avocat "
@@ -1137,14 +1131,14 @@ frozenset2({0,
      'zoo']]]]]""")
         # An unwrappable string is formatted as its repr
         unwrappable = "x" * 100
-        self.assertEqual(pprint.pformat(unwrappable, width=80), repr(unwrappable))
-        self.assertEqual(pprint.pformat(''), "''")
+        self.assertEqual(_pformat(unwrappable, width=80), repr(unwrappable))
+        self.assertEqual(_pformat(''), "''")
         # Check that the pprint is a usable repr
         special *= 10
         for width in range(3, 40):
-            formatted = pprint.pformat(special, width=width)
+            formatted = _pformat(special, width=width)
             self.assertEqual(eval(formatted), special)
-            formatted = pprint.pformat([special] * 2, width=width)
+            formatted = _pformat([special] * 2, width=width)
             self.assertEqual(eval(formatted), [special] * 2)
 
     def test_compact(self):
@@ -1157,7 +1151,7 @@ frozenset2({0,
   14, 15],
  [], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3],
  [0, 1, 2, 3, 4]]"""
-        self.assertEqual(pprint.pformat(o, width=47, compact=True), expected)
+        self.assertEqual(_pformat(o, width=47, compact=True), expected)
 
     def test_compact_width(self):
         levels = 20
@@ -1166,117 +1160,117 @@ frozenset2({0,
         for i in range(levels - 1):
             o = [o]
         for w in range(levels * 2 + 1, levels + 3 * number - 1):
-            lines = pprint.pformat(o, width=w, compact=True).splitlines()
+            lines = _pformat(o, width=w, compact=True).splitlines()
             maxwidth = max(map(len, lines))
             self.assertLessEqual(maxwidth, w)
             self.assertGreater(maxwidth, w - 3)
 
     def test_bytes_wrap(self):
-        self.assertEqual(pprint.pformat(b'', width=1), "b''")
-        self.assertEqual(pprint.pformat(b'abcd', width=1), "b'abcd'")
+        self.assertEqual(_pformat(b'', width=1), "b''")
+        self.assertEqual(_pformat(b'abcd', width=1), "b'abcd'")
         letters = b'abcdefghijklmnopqrstuvwxyz'
-        self.assertEqual(pprint.pformat(letters, width=29), repr(letters))
-        self.assertEqual(pprint.pformat(letters, width=19), """\
+        self.assertEqual(_pformat(letters, width=29), repr(letters))
+        self.assertEqual(_pformat(letters, width=19), """\
 (b'abcdefghijkl'
  b'mnopqrstuvwxyz')""")
-        self.assertEqual(pprint.pformat(letters, width=18), """\
+        self.assertEqual(_pformat(letters, width=18), """\
 (b'abcdefghijkl'
  b'mnopqrstuvwx'
  b'yz')""")
-        self.assertEqual(pprint.pformat(letters, width=16), """\
+        self.assertEqual(_pformat(letters, width=16), """\
 (b'abcdefghijkl'
  b'mnopqrstuvwx'
  b'yz')""")
         special = bytes(range(16))
-        self.assertEqual(pprint.pformat(special, width=61), repr(special))
-        self.assertEqual(pprint.pformat(special, width=48), """\
+        self.assertEqual(_pformat(special, width=61), repr(special))
+        self.assertEqual(_pformat(special, width=48), """\
 (b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
  b'\\x0c\\r\\x0e\\x0f')""")
-        self.assertEqual(pprint.pformat(special, width=32), """\
+        self.assertEqual(_pformat(special, width=32), """\
 (b'\\x00\\x01\\x02\\x03'
  b'\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
  b'\\x0c\\r\\x0e\\x0f')""")
-        self.assertEqual(pprint.pformat(special, width=1), """\
+        self.assertEqual(_pformat(special, width=1), """\
 (b'\\x00\\x01\\x02\\x03'
  b'\\x04\\x05\\x06\\x07'
  b'\\x08\\t\\n\\x0b'
  b'\\x0c\\r\\x0e\\x0f')""")
-        self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
+        self.assertEqual(_pformat({'a': 1, 'b': letters, 'c': 2},
                                         width=21), """\
 {'a': 1,
  'b': b'abcdefghijkl'
       b'mnopqrstuvwx'
       b'yz',
  'c': 2}""")
-        self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
+        self.assertEqual(_pformat({'a': 1, 'b': letters, 'c': 2},
                                         width=20), """\
 {'a': 1,
  'b': b'abcdefgh'
       b'ijklmnop'
       b'qrstuvwxyz',
  'c': 2}""")
-        self.assertEqual(pprint.pformat([[[[[[letters]]]]]], width=25), """\
+        self.assertEqual(_pformat([[[[[[letters]]]]]], width=25), """\
 [[[[[[b'abcdefghijklmnop'
       b'qrstuvwxyz']]]]]]""")
-        self.assertEqual(pprint.pformat([[[[[[special]]]]]], width=41), """\
+        self.assertEqual(_pformat([[[[[[special]]]]]], width=41), """\
 [[[[[[b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'
       b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f']]]]]]""")
         # Check that the pprint is a usable repr
         for width in range(1, 64):
-            formatted = pprint.pformat(special, width=width)
+            formatted = _pformat(special, width=width)
             self.assertEqual(eval(formatted), special)
-            formatted = pprint.pformat([special] * 2, width=width)
+            formatted = _pformat([special] * 2, width=width)
             self.assertEqual(eval(formatted), [special] * 2)
 
     def test_bytearray_wrap(self):
-        self.assertEqual(pprint.pformat(bytearray(), width=1), "bytearray(b'')")
+        self.assertEqual(_pformat(bytearray(), width=1), "bytearray(b'')")
         letters = bytearray(b'abcdefghijklmnopqrstuvwxyz')
-        self.assertEqual(pprint.pformat(letters, width=40), repr(letters))
-        self.assertEqual(pprint.pformat(letters, width=28), """\
+        self.assertEqual(_pformat(letters, width=40), repr(letters))
+        self.assertEqual(_pformat(letters, width=28), """\
 bytearray(b'abcdefghijkl'
           b'mnopqrstuvwxyz')""")
-        self.assertEqual(pprint.pformat(letters, width=27), """\
+        self.assertEqual(_pformat(letters, width=27), """\
 bytearray(b'abcdefghijkl'
           b'mnopqrstuvwx'
           b'yz')""")
-        self.assertEqual(pprint.pformat(letters, width=25), """\
+        self.assertEqual(_pformat(letters, width=25), """\
 bytearray(b'abcdefghijkl'
           b'mnopqrstuvwx'
           b'yz')""")
         special = bytearray(range(16))
-        self.assertEqual(pprint.pformat(special, width=72), repr(special))
-        self.assertEqual(pprint.pformat(special, width=57), """\
+        self.assertEqual(_pformat(special, width=72), repr(special))
+        self.assertEqual(_pformat(special, width=57), """\
 bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
           b'\\x0c\\r\\x0e\\x0f')""")
-        self.assertEqual(pprint.pformat(special, width=41), """\
+        self.assertEqual(_pformat(special, width=41), """\
 bytearray(b'\\x00\\x01\\x02\\x03'
           b'\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
           b'\\x0c\\r\\x0e\\x0f')""")
-        self.assertEqual(pprint.pformat(special, width=1), """\
+        self.assertEqual(_pformat(special, width=1), """\
 bytearray(b'\\x00\\x01\\x02\\x03'
           b'\\x04\\x05\\x06\\x07'
           b'\\x08\\t\\n\\x0b'
           b'\\x0c\\r\\x0e\\x0f')""")
-        self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
+        self.assertEqual(_pformat({'a': 1, 'b': letters, 'c': 2},
                                         width=31), """\
 {'a': 1,
  'b': bytearray(b'abcdefghijkl'
                 b'mnopqrstuvwx'
                 b'yz'),
  'c': 2}""")
-        self.assertEqual(pprint.pformat([[[[[letters]]]]], width=37), """\
+        self.assertEqual(_pformat([[[[[letters]]]]], width=37), """\
 [[[[[bytearray(b'abcdefghijklmnop'
                b'qrstuvwxyz')]]]]]""")
-        self.assertEqual(pprint.pformat([[[[[special]]]]], width=50), """\
+        self.assertEqual(_pformat([[[[[special]]]]], width=50), """\
 [[[[[bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'
                b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f')]]]]]""")
 
     def test_default_dict(self):
         d = collections.defaultdict(int)
-        self.assertEqual(pprint.pformat(d, width=1), "defaultdict(<class 'int'>, {})")
+        self.assertEqual(_pformat(d, width=1), "defaultdict(<class 'int'>, {})")
         words = 'the quick brown fox jumped over a lazy dog'.split()
         d = collections.defaultdict(int, zip(words, itertools.count()))
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
 """\
 defaultdict(<class 'int'>,
             {'a': 6,
@@ -1291,15 +1285,15 @@ defaultdict(<class 'int'>,
 
     def test_counter(self):
         d = collections.Counter()
-        self.assertEqual(pprint.pformat(d, width=1), "Counter()")
+        self.assertEqual(_pformat(d, width=1), "Counter()")
         d = collections.Counter('senselessness')
-        self.assertEqual(pprint.pformat(d, width=40),
+        self.assertEqual(_pformat(d, width=40),
 """\
 Counter({'s': 6,
          'e': 4,
          'n': 2,
          'l': 1})""")
-        self.assertEqual(pprint.pformat(d, indent=2, width=1),
+        self.assertEqual(_pformat(d, indent=2, width=1),
 """\
 Counter({ 's': 6,
           'e': 4,
@@ -1308,11 +1302,11 @@ Counter({ 's': 6,
 
     def test_chainmap(self):
         d = collections.ChainMap()
-        self.assertEqual(pprint.pformat(d, width=1), "ChainMap({})")
+        self.assertEqual(_pformat(d, width=1), "ChainMap({})")
         words = 'the quick brown fox jumped over a lazy dog'.split()
         items = list(zip(words, itertools.count()))
         d = collections.ChainMap(dict(items))
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
 """\
 ChainMap({'a': 6,
           'brown': 2,
@@ -1324,7 +1318,7 @@ ChainMap({'a': 6,
           'quick': 1,
           'the': 0})""")
         d = collections.ChainMap(dict(items), collections.OrderedDict(items))
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
 """\
 ChainMap({'a': 6,
           'brown': 2,
@@ -1335,16 +1329,10 @@ ChainMap({'a': 6,
           'over': 5,
           'quick': 1,
           'the': 0},
-         OrderedDict([('the', 0),
-                      ('quick', 1),
-                      ('brown', 2),
-                      ('fox', 3),
-                      ('jumped', 4),
-                      ('over', 5),
-                      ('a', 6),
-                      ('lazy', 7),
+         OrderedDict([('the', 0), ('quick', 1), ('brown', 2), ('fox', 3),
+                      ('jumped', 4), ('over', 5), ('a', 6), ('lazy', 7),
                       ('dog', 8)]))""")
-        self.assertEqual(pprint.pformat(d.keys()),
+        self.assertEqual(_pformat(d.keys()),
 """\
 KeysView(ChainMap({'a': 6,
           'brown': 2,
@@ -1355,16 +1343,10 @@ KeysView(ChainMap({'a': 6,
           'over': 5,
           'quick': 1,
           'the': 0},
-         OrderedDict([('the', 0),
-                      ('quick', 1),
-                      ('brown', 2),
-                      ('fox', 3),
-                      ('jumped', 4),
-                      ('over', 5),
-                      ('a', 6),
-                      ('lazy', 7),
+         OrderedDict([('the', 0), ('quick', 1), ('brown', 2), ('fox', 3),
+                      ('jumped', 4), ('over', 5), ('a', 6), ('lazy', 7),
                       ('dog', 8)])))""")
-        self.assertEqual(pprint.pformat(d.items()),
+        self.assertEqual(_pformat(d.items()),
  """\
 ItemsView(ChainMap({'a': 6,
           'brown': 2,
@@ -1375,16 +1357,10 @@ ItemsView(ChainMap({'a': 6,
           'over': 5,
           'quick': 1,
           'the': 0},
-         OrderedDict([('the', 0),
-                      ('quick', 1),
-                      ('brown', 2),
-                      ('fox', 3),
-                      ('jumped', 4),
-                      ('over', 5),
-                      ('a', 6),
-                      ('lazy', 7),
+         OrderedDict([('the', 0), ('quick', 1), ('brown', 2), ('fox', 3),
+                      ('jumped', 4), ('over', 5), ('a', 6), ('lazy', 7),
                       ('dog', 8)])))""")
-        self.assertEqual(pprint.pformat(d.values()),
+        self.assertEqual(_pformat(d.values()),
  """\
 ValuesView(ChainMap({'a': 6,
           'brown': 2,
@@ -1395,52 +1371,34 @@ ValuesView(ChainMap({'a': 6,
           'over': 5,
           'quick': 1,
           'the': 0},
-         OrderedDict([('the', 0),
-                      ('quick', 1),
-                      ('brown', 2),
-                      ('fox', 3),
-                      ('jumped', 4),
-                      ('over', 5),
-                      ('a', 6),
-                      ('lazy', 7),
+         OrderedDict([('the', 0), ('quick', 1), ('brown', 2), ('fox', 3),
+                      ('jumped', 4), ('over', 5), ('a', 6), ('lazy', 7),
                       ('dog', 8)])))""")
 
     def test_deque(self):
         d = collections.deque()
-        self.assertEqual(pprint.pformat(d, width=1), "deque([])")
+        self.assertEqual(_pformat(d, width=1), "deque([])")
         d = collections.deque(maxlen=7)
-        self.assertEqual(pprint.pformat(d, width=1), "deque([], maxlen=7)")
+        self.assertEqual(_pformat(d, width=1), "deque([], maxlen=7)")
         words = 'the quick brown fox jumped over a lazy dog'.split()
         d = collections.deque(zip(words, itertools.count()))
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
 """\
-deque([('the', 0),
-       ('quick', 1),
-       ('brown', 2),
-       ('fox', 3),
-       ('jumped', 4),
-       ('over', 5),
-       ('a', 6),
-       ('lazy', 7),
-       ('dog', 8)])""")
+deque([('the', 0), ('quick', 1), ('brown', 2), ('fox', 3), ('jumped', 4),
+       ('over', 5), ('a', 6), ('lazy', 7), ('dog', 8)])""")
         d = collections.deque(zip(words, itertools.count()), maxlen=7)
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
 """\
-deque([('brown', 2),
-       ('fox', 3),
-       ('jumped', 4),
-       ('over', 5),
-       ('a', 6),
-       ('lazy', 7),
-       ('dog', 8)],
+deque([('brown', 2), ('fox', 3), ('jumped', 4), ('over', 5), ('a', 6),
+       ('lazy', 7), ('dog', 8)],
       maxlen=7)""")
 
     def test_user_dict(self):
         d = collections.UserDict()
-        self.assertEqual(pprint.pformat(d, width=1), "{}")
+        self.assertEqual(_pformat(d, width=1), "{}")
         words = 'the quick brown fox jumped over a lazy dog'.split()
         d = collections.UserDict(zip(words, itertools.count()))
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
 """\
 {'a': 6,
  'brown': 2,
@@ -1451,7 +1409,7 @@ deque([('brown', 2),
  'over': 5,
  'quick': 1,
  'the': 0}""")
-        self.assertEqual(pprint.pformat(d.keys()), """\
+        self.assertEqual(_pformat(d.keys()), """\
 KeysView({'a': 6,
  'brown': 2,
  'dog': 8,
@@ -1461,7 +1419,7 @@ KeysView({'a': 6,
  'over': 5,
  'quick': 1,
  'the': 0})""")
-        self.assertEqual(pprint.pformat(d.items()), """\
+        self.assertEqual(_pformat(d.items()), """\
 ItemsView({'a': 6,
  'brown': 2,
  'dog': 8,
@@ -1471,7 +1429,7 @@ ItemsView({'a': 6,
  'over': 5,
  'quick': 1,
  'the': 0})""")
-        self.assertEqual(pprint.pformat(d.values()), """\
+        self.assertEqual(_pformat(d.values()), """\
 ValuesView({'a': 6,
  'brown': 2,
  'dog': 8,
@@ -1484,31 +1442,24 @@ ValuesView({'a': 6,
 
     def test_user_list(self):
         d = collections.UserList()
-        self.assertEqual(pprint.pformat(d, width=1), "[]")
+        self.assertEqual(_pformat(d, width=1), "[]")
         words = 'the quick brown fox jumped over a lazy dog'.split()
         d = collections.UserList(zip(words, itertools.count()))
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
 """\
-[('the', 0),
- ('quick', 1),
- ('brown', 2),
- ('fox', 3),
- ('jumped', 4),
- ('over', 5),
- ('a', 6),
- ('lazy', 7),
- ('dog', 8)]""")
+[('the', 0), ('quick', 1), ('brown', 2), ('fox', 3), ('jumped', 4), ('over', 5),
+ ('a', 6), ('lazy', 7), ('dog', 8)]""")
 
     def test_user_string(self):
         d = collections.UserString('')
-        self.assertEqual(pprint.pformat(d, width=1), "''")
+        self.assertEqual(_pformat(d, width=1), "''")
         d = collections.UserString('the quick brown fox jumped over a lazy dog')
-        self.assertEqual(pprint.pformat(d, width=20),
+        self.assertEqual(_pformat(d, width=20),
 """\
 ('the quick brown '
  'fox jumped over '
  'a lazy dog')""")
-        self.assertEqual(pprint.pformat({1: d}, width=20),
+        self.assertEqual(_pformat({1: d}, width=20),
 """\
 {1: 'the quick '
     'brown fox '
@@ -1517,22 +1468,22 @@ ValuesView({'a': 6,
 
     def test_template(self):
         d = t""
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
                          "Template(strings=('',), interpolations=())")
-        self.assertEqual(pprint.pformat(d), repr(d))
-        self.assertEqual(pprint.pformat(d, width=1),
+        self.assertEqual(_pformat(d), repr(d))
+        self.assertEqual(_pformat(d, width=1),
 """\
 Template(strings=('',),
          interpolations=())""")
         name = "World"
         d = t"Hello {name}"
-        self.assertEqual(pprint.pformat(d),
+        self.assertEqual(_pformat(d),
 """\
 Template(strings=('Hello ', ''),
          interpolations=(Interpolation('World', 'name', None, ''),))""")
         ver = {3.13: False, 3.14: True}
         d = t"Hello { {"name": "Python", "version": ver}!s:z}!"
-        self.assertEqual(pprint.pformat(d, width=1),
+        self.assertEqual(_pformat(d, width=1),
 """\
 Template(strings=('Hello ',
                   '!'),
@@ -1550,13 +1501,13 @@ Template(strings=('Hello ',
     def test_expand_template(self):
         d = t""
         self.assertEqual(
-            pprint.pformat(d, expand=True),
+            pprint.pformat(d),
             "Template(strings=('',), interpolations=())",
         )
         name = "World"
         d = t"Hello {name}"
         self.assertEqual(
-            pprint.pformat(d, width=40, indent=4, expand=True),
+            pprint.pformat(d, width=40, indent=4),
             """\
 Template(
     strings=('Hello ', ''),
@@ -1573,7 +1524,7 @@ Template(
         ver = {3.13: False, 3.14: True}
         d = t"Hello { {"name": "Python", "version": ver}!s:z}!"
         self.assertEqual(
-            pprint.pformat(d, width=40, indent=4, expand=True),
+            pprint.pformat(d, width=40, indent=4),
             """\
 Template(
     strings=('Hello ', '!'),
@@ -1614,8 +1565,7 @@ Template(
             corge=7,
             garply=(1, 2, 3, 4),
         )
-        self.assertEqual(pprint.pformat(dummy_dataclass, width=40, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_dataclass, width=40, indent=4),
 """\
 DummyDataclass(
     foo='foo',
@@ -1635,8 +1585,7 @@ DummyDataclass(
             "quux": ["foo", "bar", "baz"],
             "corge": 7,
         }
-        self.assertEqual(pprint.pformat(dummy_dict, width=40, indent=4,
-                                        expand=True, sort_dicts=False),
+        self.assertEqual(pprint.pformat(dummy_dict, width=40, indent=4, sort_dicts=False),
 """\
 {
     'foo': 'bar',
@@ -1654,8 +1603,7 @@ DummyDataclass(
                 ("baz", 123),
             ]
         )
-        self.assertEqual(pprint.pformat(dummy_ordered_dict, width=20, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_ordered_dict, width=20, indent=4),
 """\
 OrderedDict([
     ('foo', 1),
@@ -1670,8 +1618,7 @@ OrderedDict([
             "baz",
             "qux",
         ]
-        self.assertEqual(pprint.pformat(dummy_list, width=20, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_list, width=20, indent=4),
 """\
 [
     'foo',
@@ -1689,8 +1636,7 @@ OrderedDict([
             5,
             6,
         )
-        self.assertEqual(pprint.pformat(dummy_tuple, width=20, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_tuple, width=20, indent=4),
 """\
 (
     'foo',
@@ -1703,7 +1649,7 @@ OrderedDict([
 
     def test_expand_single_element_tuple(self):
         self.assertEqual(
-            pprint.pformat((1,), width=1, indent=4, expand=True),
+            pprint.pformat((1,), width=1, indent=4),
             """\
 (
     1,
@@ -1717,8 +1663,7 @@ OrderedDict([
             "qux",
             (1, 2, 3),
         }
-        self.assertEqual(pprint.pformat(dummy_set, width=20, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_set, width=20, indent=4),
 """\
 {
     'bar',
@@ -1741,8 +1686,7 @@ OrderedDict([
                 frozenset(dummy_set),
             }
         )
-        self.assertEqual(pprint.pformat(dummy_frozenset, width=40, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_frozenset, width=40, indent=4),
 """\
 frozenset({
     frozenset({(1, 2, 3)}),
@@ -1757,7 +1701,7 @@ frozenset({
             {"foo": "bar", "baz": 123, "qux": [1, 2]}
         )
         self.assertEqual(
-            pprint.pformat(dummy_frozendict, width=20, indent=4, expand=True),
+            pprint.pformat(dummy_frozendict, width=20, indent=4),
             """\
 frozendict({
     'baz': 123,
@@ -1768,8 +1712,7 @@ frozendict({
 
     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),
+        self.assertEqual(pprint.pformat(dummy_bytes, width=20, indent=4),
 """\
 (
     b'Hello world!'
@@ -1780,8 +1723,7 @@ frozendict({
     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),
+        self.assertEqual(pprint.pformat(dummy_byte_array, width=40, indent=4),
 """\
 bytearray(
     b'Hello world! foo bar baz 123 456'
@@ -1797,8 +1739,7 @@ bytearray(
             "corge": 7,
         }
         dummy_mappingproxy = types.MappingProxyType(dummy_dict)
-        self.assertEqual(pprint.pformat(dummy_mappingproxy, width=40, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_mappingproxy, width=40, indent=4),
 """\
 mappingproxy({
     'baz': 123,
@@ -1819,8 +1760,7 @@ mappingproxy({
             ),
         )
 
-        self.assertEqual(pprint.pformat(dummy_namespace, width=40, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_namespace, width=40, indent=4),
 """\
 namespace(
     foo='bar',
@@ -1838,8 +1778,7 @@ namespace(
         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),
+        self.assertEqual(pprint.pformat(dummy_defaultdict, width=40, indent=4),
 """\
 defaultdict(<class 'list'>, {
     'bar': {'baz': None, 'foo': 'bar'},
@@ -1856,8 +1795,7 @@ Counter({
     'd': 2,
     'e': 1,
 })"""
-        self.assertEqual(pprint.pformat(dummy_counter, width=40, indent=4,
-                                        expand=True), expected)
+        self.assertEqual(pprint.pformat(dummy_counter, width=40, indent=4), expected)
 
         expected2 = """\
 Counter({
@@ -1867,8 +1805,7 @@ Counter({
   'd': 2,
   'e': 1,
 })"""
-        self.assertEqual(pprint.pformat(dummy_counter, width=20, indent=2,
-                                        expand=True), expected2)
+        self.assertEqual(pprint.pformat(dummy_counter, width=20, indent=2), expected2)
 
     def test_expand_chainmap(self):
         dummy_dict = {
@@ -1884,8 +1821,7 @@ Counter({
             {"corge": dummy_dict},
         )
         dummy_chainmap.maps.append({"garply": "waldo"})
-        self.assertEqual(pprint.pformat(dummy_chainmap, width=40, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_chainmap, width=40, indent=4),
 """\
 ChainMap(
     {'foo': 'bar'},
@@ -1927,8 +1863,7 @@ ChainMap(
         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),
+        self.assertEqual(pprint.pformat(dummy_deque, width=40, indent=4),
 """\
 deque([
     {(1, 2, 3)},
@@ -1959,8 +1894,7 @@ deque([
                                         "corge": 7 })
         dummy_userdict.access_count = 5
 
-        self.assertEqual(pprint.pformat(dummy_userdict, width=40, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_userdict, width=40, indent=4),
 """\
 {
     'baz': 123,
@@ -1980,8 +1914,7 @@ deque([
         dummy_userlist = DummyUserList(["first", 2, {"key": "value"},
                                        [4, 5, 6]])
 
-        self.assertEqual(pprint.pformat(dummy_userlist, width=40, indent=4,
-                                        expand=True),
+        self.assertEqual(pprint.pformat(dummy_userlist, width=40, indent=4),
 """\
 [
     'first',
@@ -1993,7 +1926,7 @@ deque([
     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),
+            pprint.pformat(d.keys(), width=20, indent=4),
             """\
 dict_keys([
     'bar',
@@ -2007,7 +1940,7 @@ dict_keys([
     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),
+            pprint.pformat(d.values(), width=20, indent=4),
             """\
 dict_values([
     1,
@@ -2021,7 +1954,7 @@ dict_values([
     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),
+            pprint.pformat(d.items(), width=20, indent=4),
             """\
 dict_items([
     ('bar', 2),
@@ -2035,7 +1968,7 @@ dict_items([
     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),
+            pprint.pformat(s, width=40, indent=4),
             """\
 (
     'The quick brown fox jumped over '
index a7b864c701be772c0c403814791e6e793a60130a..c20468c12b670d8c3ad4f26902f861d78d192ba4 100644 (file)
@@ -1023,15 +1023,19 @@ if feature_macros['USE_STACKCHECK']:
         'PyOS_CheckStack',
     )
 
-EXPECTED_FEATURE_MACROS = set(['HAVE_FORK',
- 'MS_WINDOWS',
- 'PY_HAVE_THREAD_NATIVE_ID',
- 'Py_REF_DEBUG',
- 'Py_TRACE_REFS',
- 'USE_STACKCHECK'])
-WINDOWS_FEATURE_MACROS = {'HAVE_FORK': False,
- 'MS_WINDOWS': True,
- 'PY_HAVE_THREAD_NATIVE_ID': True,
- 'Py_REF_DEBUG': 'maybe',
- 'Py_TRACE_REFS': 'maybe',
- 'USE_STACKCHECK': 'maybe'}
+EXPECTED_FEATURE_MACROS = set([
+    'HAVE_FORK',
+    'MS_WINDOWS',
+    'PY_HAVE_THREAD_NATIVE_ID',
+    'Py_REF_DEBUG',
+    'Py_TRACE_REFS',
+    'USE_STACKCHECK',
+])
+WINDOWS_FEATURE_MACROS = {
+    'HAVE_FORK': False,
+    'MS_WINDOWS': True,
+    'PY_HAVE_THREAD_NATIVE_ID': True,
+    'Py_REF_DEBUG': 'maybe',
+    'Py_TRACE_REFS': 'maybe',
+    'USE_STACKCHECK': 'maybe',
+}
index 0e82c723ec3eaa2495f7ee929eed8a20b4f75a42..f8643552011f4e877144abfe744f1ca0f32c8fd0 100644 (file)
@@ -1162,9 +1162,7 @@ class TestCallList(unittest.TestCase):
         mock.foo.bar().baz('fish', cat='dog')
 
         expected = (
-            "[call(1, 2),\n"
-            " call.foo(a=3),\n"
-            " call.foo.bar(),\n"
+            "[call(1, 2), call.foo(a=3), call.foo.bar(),"
             " call.foo.bar().baz('fish', cat='dog')]"
         )
         self.assertEqual(str(mock.mock_calls), expected)
diff --git a/Misc/NEWS.d/next/Library/2026-04-30-18-56-23.gh-issue-149189.mszW10.rst b/Misc/NEWS.d/next/Library/2026-04-30-18-56-23.gh-issue-149189.mszW10.rst
new file mode 100644 (file)
index 0000000..1fd7f76
--- /dev/null
@@ -0,0 +1,7 @@
+:mod:`pprint` now uses modern defaults: ``indent=4`` and ``width=88``,
+and the default ``compact=False`` output is now formatted similar to
+pretty-printed :func:`json.dumps`, with opening parentheses and brackets
+followed by a newline and the contents indented by one level. The
+*expand* parameter, added in 3.15.0a8, has been removed; ``compact=False``
+(the default) now produces the former ``expand=True`` layout.
+Patch by Hugo van Kemenade.