Skip to content

Commit 398f467

Browse files
committed
PEP 813: The Pretty Print Protocol
1 parent 9a3ab9c commit 398f467

1 file changed

Lines changed: 195 additions & 0 deletions

File tree

peps/pep-0813.rst

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
PEP: 813
2+
Title: The Pretty Print Protocol
3+
Author: Barry Warsaw <barry@python.org>,
4+
Eric V. Smith <eric at trueblade.com>
5+
Discussions-To: Pending
6+
Status: Draft
7+
Type: Standards Track
8+
Created: 07-Nov-2025
9+
Python-Version: 3.15
10+
Post-History: Pending
11+
12+
13+
Abstract
14+
========
15+
16+
This PEP describes the "pretty print protocol", a collection of changes proposed to make pretty printing more
17+
customizable and convenient.
18+
19+
20+
Motivation
21+
==========
22+
23+
"Pretty printing" is a feature which provides a capability to format object representations for better
24+
readability. The core functionality is implemented by the standard library :mod:`pprint`. ``pprint``
25+
includes a class and APIs which users can invoke to format and print more readable representations of objects.
26+
Important use cases include pretty printing large dictionaries and other complicated objects.
27+
28+
The ``pprint`` module is great as far as it goes. This PEP builds on the features of this module to provide
29+
more customization and convenience.
30+
31+
32+
Rationale
33+
=========
34+
35+
Pretty printing is very useful for displaying complex data structures, like dictionaries read from JSON
36+
content. By providing a way for classes to customize how their instances participate in pretty printing,
37+
users have more options for visually improving the display and debugging of their complex data.
38+
39+
By extending the built-in :py:func:`print` function to automatically pretty print its output, this feature is
40+
made even more convenient, since no extra imports are required, and users can easily just piggyback on
41+
well-worn "print debugging" patterns, at least for the most common use cases.
42+
43+
These two extensions work independently, but hand-in-hand can provide a powerful and convenient new feature.
44+
45+
46+
Specification
47+
=============
48+
49+
There are two parts to this proposal.
50+
51+
52+
``__pretty__()`` methods
53+
------------------------
54+
55+
Classes can implement a new dunder method, ``__pretty__()`` which if present, generates the pretty printed
56+
representation of their instances. This augments ``__repr__()`` which, prior to this proposal, was the only
57+
method used to generate a pretty representation of the object. Since object reprs provide functionality
58+
distinct from pretty printing, some classes may want more control over their pretty display.
59+
60+
``__pretty__()`` is optional; if missing, the standard pretty printers fall back to ``__repr__()`` for full
61+
backward compatibility (technically speaking, :meth:`pprint.saferepr` is used). However, if defined on a
62+
class, ``__pretty__()`` has the same argument signature as :py:func:`PrettyPrinter.format`, taking four
63+
arguments:
64+
65+
* ``object`` - the object to print, which is effectively always ``self``
66+
* ``context`` - a dictionary mapping the ``id()`` of objects which are part of the current presentation
67+
context
68+
* ``maxlevels`` - the requested limit to recursion
69+
* ``levels`` - the current recursion level
70+
71+
Similarly, ``__pretty__()`` returns three values, the string to be used as the pretty printed representation,
72+
a boolean indicating whether the returned value is "readable", and a boolean indicating whether recursion has
73+
been detected. In this context, "readable" means the same as :meth:`PrettyPrinter.isreadable`, i.e. that the
74+
returned value can be used to reconstruct the original object using ``eval()``.
75+
76+
See :py:func:`PrettyPrinter.format` for details.
77+
78+
79+
A new argument to built-in ``print``
80+
------------------------------------
81+
82+
Built-in :py:func:`print` takes a new optional argument, appended to the end of the argument list, called
83+
``pretty``, which can take one of the following values:
84+
85+
* ``None`` - the default; fully backward compatible
86+
* ``True`` - use a temporary instance of the :py:class:`PrettyPrinter` class to get a pretty representation of
87+
the object.
88+
* An instance with a ``pformat()`` method, which has the same signature as
89+
:meth:`PrettyPrinter.pformat`. When given, this will usually be an instance of a subclass of
90+
`PrettyPrinter` with its `pformat()` method overridden. Note that this form requires **an
91+
instance** of a pretty printer, not a class, as only ``print(..., pretty=True)`` performs implicit
92+
instantiation.
93+
94+
95+
Examples
96+
========
97+
98+
A custom ``__pprint__()`` method can be used to customize the representation of the object:
99+
100+
.. _code-block:
101+
102+
>>> class Custom:
103+
... def __str__(self): return 'my str'
104+
... def __repr__(self): return 'my repr'
105+
... def __pprint__(self, context, maxlevels, level): return 'my pprint'
106+
107+
>>> pprint.pp(Custom())
108+
my pprint
109+
110+
Using the ``pretty`` argument to ``print()``:
111+
112+
.. _code-block:
113+
114+
>>> import os
115+
>>> print(os.pathconf_names)
116+
{'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}
117+
>>> print(os.pathconf_names, pretty=True)
118+
{'PC_ALLOC_SIZE_MIN': 16,
119+
'PC_ASYNC_IO': 17,
120+
'PC_CHOWN_RESTRICTED': 7,
121+
'PC_FILESIZEBITS': 18,
122+
'PC_LINK_MAX': 1,
123+
'PC_MAX_CANON': 2,
124+
'PC_MAX_INPUT': 3,
125+
'PC_MIN_HOLE_SIZE': 27,
126+
'PC_NAME_MAX': 4,
127+
'PC_NO_TRUNC': 8,
128+
'PC_PATH_MAX': 5,
129+
'PC_PIPE_BUF': 6,
130+
'PC_PRIO_IO': 19,
131+
'PC_REC_INCR_XFER_SIZE': 20,
132+
'PC_REC_MAX_XFER_SIZE': 21,
133+
'PC_REC_MIN_XFER_SIZE': 22,
134+
'PC_REC_XFER_ALIGN': 23,
135+
'PC_SYMLINK_MAX': 24,
136+
'PC_SYNC_IO': 25,
137+
'PC_VDISABLE': 9}
138+
139+
140+
Backwards Compatibility
141+
=======================
142+
143+
When none of the new features are used, this PEP is fully backward compatible, both for built-in
144+
``print()`` and the ``pprint`` module.
145+
146+
147+
Security Implications
148+
=====================
149+
150+
There are no known security implications for this proposal.
151+
152+
153+
How to Teach This
154+
=================
155+
156+
Documentation and examples are added to the ``pprint`` module and the ``print()`` function.
157+
Beginners don't need to be taught these new features until they want prettier representations of
158+
their objects.
159+
160+
161+
Reference Implementation
162+
========================
163+
164+
The reference implementation is currently available as a `PEP author branch of the CPython main
165+
branch <https://github.com/warsaw/cpython/tree/pprint>`__.
166+
167+
168+
Rejected Ideas
169+
==============
170+
171+
None at this time.
172+
173+
174+
Open Issues
175+
===========
176+
177+
TBD
178+
179+
Acknowledgements
180+
================
181+
182+
TBD
183+
184+
185+
Footnotes
186+
=========
187+
188+
TBD
189+
190+
191+
Copyright
192+
=========
193+
194+
This document is placed in the public domain or under the
195+
CC0-1.0-Universal license, whichever is more permissive.

0 commit comments

Comments
 (0)