Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ peps/pep-0807.rst @dstufft
peps/pep-0809.rst @zooba
peps/pep-0810.rst @pablogsal @DinoV @Yhg1s
peps/pep-0811.rst @sethmlarson @gpshead
peps/pep-0813.rst @warsaw
# ...
peps/pep-2026.rst @hugovk
# ...
Expand Down
196 changes: 196 additions & 0 deletions peps/pep-0813.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
PEP: 813
Title: The Pretty Print Protocol
Author: Barry Warsaw <[email protected]>
Discussions-To: Pending
Status: Draft
Type: Standards Track
Created: 07-Nov-2025
Python-Version: 3.15
Post-History: Pending


Abstract
========

This PEP describes the "pretty print protocol", a collection of changes proposed to make pretty printing more
customizable and convenient.


Motivation
==========

"Pretty printing" is a feature which provides a capability to format object representations for better
readability. The core functionality is implemented by the standard library :mod:`pprint`. ``pprint``
includes a class and APIs which users can invoke to format and print more readable representations of objects.
Important use cases include pretty printing large dictionaries and other complicated objects.

The ``pprint`` module is great as far as it goes. This PEP builds on the features of this module to provide
more customization and convenience.


Rationale
=========

Pretty printing is very useful for displaying complex data structures, like dictionaries read from JSON
content. By providing a way for classes to customize how their instances participate in pretty printing,
users have more options for visually improving the display and debugging of their complex data.

By extending the built-in :func:`print` function to automatically pretty print its output, this feature is
made even more convenient, since no extra imports are required, and users can easily just piggyback on
well-worn "print debugging" patterns, at least for the most common use cases.

These two extensions work independently, but hand-in-hand can provide a powerful and convenient new feature.


Specification
=============

There are two parts to this proposal.


``__pretty__()`` methods
------------------------

Classes can implement a new dunder method, ``__pretty__()`` which if present, generates the pretty printed
representation of their instances. This augments ``__repr__()`` which, prior to this proposal, was the only
method used to generate a pretty representation of the object. Since object reprs provide functionality
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow here, pprint uses custom logic to generate 'pretty' reprs rather than delegating to e.g. container object __repr__() methods. I.e. I'd leave out 'pretty' on the second line here, but I don't know if this matches your thinking.

distinct from pretty printing, some classes may want more control over their pretty display.

``__pretty__()`` is optional; if missing, the standard pretty printers fall back to ``__repr__()``
for full backward compatibility (technically speaking, :py:func:`python:pprint.saferepr` is used).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is always using saferepr part of the PEP spec here?

However, if defined on a class, ``__pretty__()`` has the same argument signature as
:py:meth:`python:pprint.PrettyPrinter.format`, taking four arguments:

* ``object`` - the object to print, which is effectively always ``self``
* ``context`` - a dictionary mapping the ``id()`` of objects which are part of the current presentation
context
* ``maxlevels`` - the requested limit to recursion
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming: suggest using an underscore?

Suggested change
* ``maxlevels`` - the requested limit to recursion
* ``maxlevels`` - the requested limit to recursion (integer)

* ``levels`` - the current recursion level
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is the current level, should it be singular instead of plural?

Suggested change
* ``levels`` - the current recursion level
* ``levels`` - the current recursion level (integer)


Similarly, ``__pretty__()`` returns three values, the string to be used as the pretty printed representation,
a boolean indicating whether the returned value is "readable", and a boolean indicating whether recursion has
been detected. In this context, "readable" means the same as
:py:meth:`python:pprint.PrettyPrinter.isreadable`, i.e. that the returned value can be used to reconstruct the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
:py:meth:`python:pprint.PrettyPrinter.isreadable`, i.e. that the returned value can be used to reconstruct the
:py:meth:`~pprint.PrettyPrinter.isreadable`, i.e. that the returned value can be used to reconstruct the

original object using ``eval()``.

See :py:meth:`python:pprint.PrettyPrinter.format` for details.


A new argument to built-in ``print``
------------------------------------

Built-in :func:`print` takes a new optional argument, appended to the end of the argument list, called
``pretty``, which can take one of the following values:

* ``None`` - the default. No pretty printing is invoked. Fully backward compatible
* ``True`` - use a temporary instance of the :py:class:`python:pprint.PrettyPrinter` class to get a
pretty representation of the object.
* An instance with a ``pformat()`` method, which has the same signature as
:py:meth:`python:pprint.PrettyPrinter.pformat`. When given, this will usually be an instance of a
subclass of ``PrettyPrinter`` with its ``pformat()`` method overridden. Note that this form
requires **an instance** of a pretty printer, not a class, as only ``print(..., pretty=True)``
performs implicit instantiation.


Examples
========

A custom ``__pprint__()`` method can be used to customize the representation of the object:

.. code-block::

>>> class Custom:
... def __str__(self): return 'my str'
... def __repr__(self): return 'my repr'
... def __pprint__(self, context, maxlevels, level):
... return 'my pprint', False, False

>>> pprint.pp(Custom())
my pprint

Using the ``pretty`` argument to ``print()``:

.. code-block::

>>> import os
>>> print(os.pathconf_names)
{'PC_ASYNC_IO': 17, 'PC_CHOWN_RESTRICTED': 7, 'PC_FILESIZEBITS': 18, 'PC_LINK_MAX': 1, 'PC_MAX_CANON': 2, 'PC_MAX_INPUT': 3, 'PC_NAME_MAX': 4, 'PC_NO_TRUNC': 8, 'PC_PATH_MAX': 5, 'PC_PIPE_BUF': 6, 'PC_PRIO_IO': 19, 'PC_SYNC_IO': 25, 'PC_VDISABLE': 9, 'PC_MIN_HOLE_SIZE': 27, 'PC_ALLOC_SIZE_MIN': 16, 'PC_REC_INCR_XFER_SIZE': 20, 'PC_REC_MAX_XFER_SIZE': 21, 'PC_REC_MIN_XFER_SIZE': 22, 'PC_REC_XFER_ALIGN': 23, 'PC_SYMLINK_MAX': 24}
>>> print(os.pathconf_names, pretty=True)
{'PC_ALLOC_SIZE_MIN': 16,
'PC_ASYNC_IO': 17,
'PC_CHOWN_RESTRICTED': 7,
'PC_FILESIZEBITS': 18,
'PC_LINK_MAX': 1,
'PC_MAX_CANON': 2,
'PC_MAX_INPUT': 3,
'PC_MIN_HOLE_SIZE': 27,
'PC_NAME_MAX': 4,
'PC_NO_TRUNC': 8,
'PC_PATH_MAX': 5,
'PC_PIPE_BUF': 6,
'PC_PRIO_IO': 19,
'PC_REC_INCR_XFER_SIZE': 20,
'PC_REC_MAX_XFER_SIZE': 21,
'PC_REC_MIN_XFER_SIZE': 22,
'PC_REC_XFER_ALIGN': 23,
'PC_SYMLINK_MAX': 24,
'PC_SYNC_IO': 25,
'PC_VDISABLE': 9}


Backwards Compatibility
=======================

When none of the new features are used, this PEP is fully backward compatible, both for built-in
``print()`` and the ``pprint`` module.


Security Implications
=====================

There are no known security implications for this proposal.


How to Teach This
=================

Documentation and examples are added to the ``pprint`` module and the ``print()`` function.
Beginners don't need to be taught these new features until they want prettier representations of
their objects.


Reference Implementation
========================

The reference implementation is currently available as a `PEP author branch of the CPython main
branch <https://github.com/warsaw/cpython/tree/pprint>`__.


Rejected Ideas
==============

None at this time.


Open Issues
===========

TBD

Acknowledgements
================

TBD


Footnotes
=========

TBD


Copyright
=========

This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.