|
| 1 | +PEP: 9999 |
| 2 | +Title: The pprint protocol |
| 3 | +Author: Barry Warsaw < [email protected]>, |
| 4 | + Eric V. Smith <eric at trueblade.com> |
| 5 | +Discussions-To: Pending |
| 6 | +Status: Draft |
| 7 | +Type: Standards Track |
| 8 | +Created: 03-Nov-2025 |
| 9 | +Python-Version: 3.15 |
| 10 | +Post-History: Pending |
| 11 | + |
| 12 | + |
| 13 | +Abstract |
| 14 | +======== |
| 15 | + |
| 16 | +This PEP describes the "pprint 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 the built-in :py:func:`repr` function |
| 58 | +provides functionality potentially separate from pretty printing, some classes may want more control over |
| 59 | +object display between those two use cases. |
| 60 | + |
| 61 | +``__pretty__()`` is optional; if missing, the standard pretty printers fall back to ``__repr__()`` for full |
| 62 | +backward compatibility. However, if defined on a class, ``__pretty__()`` has the same argument signature as |
| 63 | +:py:func:`PrettyPrinter.format`, taking four 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 | +See :py:func:`PrettyPrinter.format` for details. |
| 72 | + |
| 73 | +Unlike that function, ``__pretty__()`` returns a single value, the string to be used as the pretty printed |
| 74 | +representation. |
| 75 | + |
| 76 | + |
| 77 | +A new argument to built-in ``print`` |
| 78 | +------------------------------------ |
| 79 | + |
| 80 | +Built-in :py:func:`print` takes a new optional argument, appended to the end of the argument list, called |
| 81 | +``pretty``, which can take one of the following values: |
| 82 | + |
| 83 | +* ``None`` - the default; fully backward compatible |
| 84 | +* ``True`` - use a temporary instance of the :py:class:`PrettyPrinter` class to get a pretty representation of |
| 85 | + the object. |
| 86 | +* An instance with a ``pformat()`` method, which has the same signature as |
| 87 | + :meth:`PrettyPrinter.pformat`. When given, this will usually be an instance of a subclass of |
| 88 | + `PrettyPrinter` with its `pformat()` method overridden. Note that this form requires **an |
| 89 | + instance** of a pretty printer, not a class, as only ``print(..., pretty=True)`` performs implicit |
| 90 | + instantiation. |
| 91 | + |
| 92 | + |
| 93 | +Backwards Compatibility |
| 94 | +======================= |
| 95 | + |
| 96 | +When none of the new features are used, this PEP is fully backward compatible, both for built-in |
| 97 | +``print()`` and the ``pprint`` module. |
| 98 | + |
| 99 | + |
| 100 | +Security Implications |
| 101 | +===================== |
| 102 | + |
| 103 | +There are no known security implications for this proposal. |
| 104 | + |
| 105 | + |
| 106 | +How to Teach This |
| 107 | +================= |
| 108 | + |
| 109 | +Documentation and examples are added to the ``pprint`` module and the ``print()`` function. |
| 110 | +Beginners don't need to be taught these new features until they want prettier representations of |
| 111 | +their objects. |
| 112 | + |
| 113 | + |
| 114 | +Reference Implementation |
| 115 | +======================== |
| 116 | + |
| 117 | +The reference implementation is currently available as a `PEP author branch of the CPython main |
| 118 | +branch <https://github.com/warsaw/cpython/tree/pprint>`__. |
| 119 | + |
| 120 | + |
| 121 | +Rejected Ideas |
| 122 | +============== |
| 123 | + |
| 124 | +None at this time. |
| 125 | + |
| 126 | + |
| 127 | +Open Issues |
| 128 | +=========== |
| 129 | + |
| 130 | +As currently defined, the ``__pretty__()`` method is defined as taking four arguments and returning |
| 131 | +a single string. This is close to -- but not quite -- the full signature for |
| 132 | +``PrettyPrinter.format()``, and was chosen for reference implementation convenience. It's not |
| 133 | +clear that custom pretty representations need ``context``, ``maxlevels``, and ``levels``, so perhaps |
| 134 | +the argument list should be simplified? If not, then perhaps ``__pretty__()`` should *exactly* |
| 135 | +match ``PrettyPrinter.format()``? That does, however complicate the protocol for users. |
| 136 | + |
| 137 | + |
| 138 | +Acknowledgements |
| 139 | +================ |
| 140 | + |
| 141 | +TBD |
| 142 | + |
| 143 | + |
| 144 | +Footnotes |
| 145 | +========= |
| 146 | + |
| 147 | +TBD |
| 148 | + |
| 149 | + |
| 150 | +Copyright |
| 151 | +========= |
| 152 | + |
| 153 | +This document is placed in the public domain or under the |
| 154 | +CC0-1.0-Universal license, whichever is more permissive. |
0 commit comments