@@ -25,22 +25,23 @@ includes a class and APIs which users can invoke to format and print more readab
2525versus the standard ``repr() `` built-in function. Important use cases include pretty printing large
2626dictionaries and other complicated objects for debugging purposes.
2727
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.
28+ This PEP builds on the features of the module to provide more customization and user convenience. It is also
29+ inspired by the `Rich library's pretty printing protocol
30+ <https://rich.readthedocs.io/en/latest/pretty.html#rich-repr-protocol> `_.
3031
3132
3233Rationale
3334=========
3435
3536Pretty printing is very useful for displaying complex data structures, like dictionaries read from JSON
3637content. 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+ users have more options for visually improving the display of their complex data, especially for debugging .
3839
39- By extending the built-in :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.
40+ By extending the built-in :func: `print ` function to automatically pretty print its output, debugging with
41+ user-friendly display is made even more convenient. Since no extra imports are required, users can easily
42+ just piggyback on well-worn "print debugging" patterns, at least for the most common use cases.
4243
43- These two extensions work independently, but hand-in-hand can provide a powerful and convenient new feature .
44+ These extensions work both independently and complimentary, to provide powerful new use cases .
4445
4546
4647Specification
@@ -52,33 +53,33 @@ There are several parts to this proposal.
5253``__pprint__() `` methods
5354------------------------
5455
55- Classes can implement a new dunder method, ``__pprint__() `` 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 custom representation of the object. Since object reprs provide functionality
56+ Classes can implement a new dunder method, ``__pprint__() `` which if present, generates parts of their
57+ instance's pretty printed representation . This augments ``__repr__() `` which, prior to this proposal, was the
58+ only method used to generate a custom representation of the object. Since object reprs provide functionality
5859distinct from pretty printing, some classes may want more control over their pretty display. The
5960:py:class: `python:pprint.PrettyPrinter ` class is modified to respect an object's ``__pprint__() `` method if
6061present.
6162
62- ``__pprint__() `` is optional; if missing, the standard pretty printers fall back to ``__repr__() ``
63- for full backward compatibility (technically speaking, :py:func: `python:pprint.saferepr ` is used).
64- However, if defined on a class, ``__pprint__() `` has the same argument signature as
65- :py:meth: `python:pprint.PrettyPrinter.format `, taking four arguments:
63+ ``__pprint__() `` is optional; if missing, the standard pretty printers fall back to ``__repr__() `` for full
64+ backward compatibility (technically speaking, :py:func: `python:pprint.saferepr ` is used). However, if defined
65+ on a class, ``__pprint__() `` takes a single argument, the object to be pretty printed (i.e. ``self ``).
6666
67- * ``self `` - this object (described in ``PrettyPrinter.format() `` method as ``object ``)
68- * ``context `` - a dictionary mapping the ``id() `` of objects which are part of the current presentation
69- context
70- * ``maxlevels `` - the requested limit to recursion
71- * ``levels `` - the current recursion level
67+ The method is expected to return or yield a sequence of values, which are used to construct a pretty
68+ representation of the object. These values are wrapped in standard class "chrome", such as the
69+ class name. The printed representation will usually look like a class constructor, with positional,
70+ keyword, and default arguments. The values can be any of the following formats:
7271
73- Similarly, ``__pprint__() `` returns three values:
72+ * A single value, representing a positional argument. The value itself is used.
73+ * A 2-tuple of ``(name, value) `` representing a keyword argument. A representation of
74+ ``name=value `` is used.
75+ * A 3-tuple of ``(name, value, default_value) `` representing a keyword argument with a default
76+ value. If ``value `` equals ``default_value ``, then this tuple is skipped, otherwise
77+ ``name=value `` is used.
7478
75- * the string to be used as the pretty printed representation
76- * a boolean indicating whether the returned value is "readable" (defined by
77- :py:meth: `python:pprint.PrettyPrinter.isreadable `, i.e. that the returned value can be used to reconstruct the
78- original object using ``eval() ``).
79- * boolean indicating whether recursion has been detected.
79+ .. note ::
8080
81- See :py:meth: `python:pprint.PrettyPrinter.format ` for details.
81+ This protocol is compatible with the `Rich library's pretty printing protocol
82+ <https://rich.readthedocs.io/en/latest/pretty.html#rich-repr-protocol> `_.
8283
8384
8485A new argument to built-in ``print ``
@@ -100,26 +101,42 @@ Built-in :func:`print` takes a new optional argument, appended to the end of the
100101Examples
101102========
102103
103- A custom ``__pprint__() `` method can be used to customize the representation of the object:
104+ A custom ``__pprint__() `` method can be used to customize the representation of the object, such as with this
105+ class:
104106
105- .. code-block ::
107+ .. code-block :: python
106108
107- >>> class Custom :
108- ... def __str__ (self): return 'my str'
109- ... def __repr__(self): return 'my repr'
110- ... def __pprint__(self, context, maxlevels, level):
111- ... return 'my pprint', False, False
109+ class Bass :
110+ def __init__ (self , strings : int , pickups : str , active : bool = False ):
111+ self ._strings = strings
112+ self ._pickups = pickups
113+ self ._active = active
112114
113- >>> pprint.pp(Custom())
114- my pprint
115+ def __pprint__ (self ):
116+ yield self ._strings
117+ yield ' pickups' , self ._pickups
118+ yield ' active' , self ._active, False
115119
116- Using the `` pretty `` argument to `` print() `` :
120+ Now let's create a couple of instances, and pretty print them :
117121
118- .. code-block ::
122+ .. code-block :: pycon
123+
124+ >>> precision = Bass(4, 'split coil P', active=False)
125+ >>> stingray = Bass(5, 'humbucker', active=True)
126+
127+ >>> pprint.pprint(precision)
128+ Bass(4, pickups='split coil P')
129+ >>> pprint.pprint(stingray)
130+ Bass(5, pickups='humbucker', active=True)
131+
132+ Here's an example of using the ``pretty `` argument to built-in ``print() ``:
133+
134+ .. code-block :: pycon
119135
120136 >>> import os
121137 >>> print(os.pathconf_names)
122138 {'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}
139+
123140 >>> print(os.pathconf_names, pretty=True)
124141 {'PC_ALLOC_SIZE_MIN': 16,
125142 'PC_ASYNC_IO': 17,
@@ -180,10 +197,36 @@ None at this time.
180197Open Issues
181198===========
182199
183- TBD
200+ The output format and APIs are heavily inspired by `Rich
201+ <https://rich.readthedocs.io/en/latest/pretty.html#rich-repr-protocol> `_. The idea is that Rich could
202+ implement an API compatible with ``print(..., pretty=RichPrinter) `` fairly easily. Rich's API is designed to
203+ print constructor-like representations of instances, which means that it's not possible to control much of the
204+ "class chrome" around the arguments. Rich does support using angle brackets (i.e. ``<...> ``) instead of
205+ parentheses by setting the attribute ``.angular=True `` on the rich repr method. This PEP does not support
206+ that feature, although it likely could in the future.
207+
208+ This also means that there's no way to control the pretty printed format of built-in types like strings,
209+ dicts, lists, etc. This seems fine as ``pprint `` is not intended to be as feature-rich (pun intended!) as
210+ Rich. This PEP purposefully deems such fancy features as out-of-scope.
211+
212+ One consequence of ``print(..., pretty=True) `` is that it can be more less obvious if you wanted to print
213+ multiple objects with, say a newline between the object representations. Compare these two outputs:
214+
215+ .. code-block :: pycon
216+
217+ >>> print(precision, '\n', stingray, pretty=True)
218+ Bass(4, pickups='split coil P') '\n' Bass(5, pickups='humbucker', active=True)
219+
220+ >>> print(precision, stingray, sep='\n', pretty=True)
221+ Bass(4, pickups='split coil P')
222+ Bass(5, pickups='humbucker', active=True)
223+
224+ It's likely you'll want the second output, but more complicated multi-object displays could get even less
225+ convenient and/or more verbose.
226+
184227
185- Acknowledgements
186- ================
228+ Acknowledgments
229+ ===============
187230
188231TBD
189232
0 commit comments