Skip to content
Open
Changes from all 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
94 changes: 84 additions & 10 deletions peps/pep-0813.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ class name. The printed representation will usually look like a class construct
keyword, and default arguments. The values can be any of the following formats:

* A single value, representing a positional argument. The value itself is used.
* A 2-tuple of ``(name, value)`` representing a keyword argument. A representation of
``name=value`` is used.
* A 2-tuple of ``(name, value)`` representing a keyword argument. A
representation of ``name=value`` is used. If ``name`` is "false-y", then
``value`` is treated as a positional argument. This is how you would print
a positional argument with a tuple value. See :ref:`examples`. Otherwise,
``name`` **MUST** exactly be a ``str``.
* A 3-tuple of ``(name, value, default_value)`` representing a keyword argument with a default
value. If ``value`` equals ``default_value``, then this tuple is skipped, otherwise
``name=value`` is used.
Expand All @@ -85,8 +88,8 @@ keyword, and default arguments. The values can be any of the following formats:
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:
Built-in :func:`print` gains a new optional keyword-only argument 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
Expand All @@ -106,6 +109,17 @@ will be added. The effect of this specifier with an expression ``value`` will b
:py:func:`python:pprint.pformat`, passing ``value`` as the only argument. In this initial specification, it
will be an error to provide any format specifier if ``!p`` is used.

Additions to the C-API
----------------------

To support ``!p``, a new function, ``PyObject_Pretty()`` is added to the
`Limited C API <https://docs.python.org/3/c-api/stable.html#limited-c-api>`_.
This function takes a single ``PyObject *``, the object to pretty print. This
function imports the ``pprint`` module and calls :func:`pprint.pformat` with
this object as its argument, returning the results.

.. _examples:

Examples
========

Expand Down Expand Up @@ -167,6 +181,21 @@ Here's an example of using the ``pretty`` argument to built-in ``print()``:
'PC_SYNC_IO': 25,
'PC_VDISABLE': 9}

Here's an example where a positional argument has a tuple value. In this case, you use the 2-tuple format,
with the ``name`` being "false-y".

.. code-block:: pycon

>>> class Things:
... def __pprint__(self):
... yield (None, (1, 2))
... yield ('', (3, 4))
... yield ('arg', (5, 6))
...
>>> from rich.pretty import pprint
>>> pprint(Things())
Things((1, 2), (3, 4), arg=(5, 6))


Backwards Compatibility
=======================
Expand Down Expand Up @@ -205,13 +234,18 @@ None at this time.
Open Issues
===========

Rich compatibility
------------------

The output format and APIs are heavily inspired by `Rich
<rich-repr-protocol_>`_. The idea is that Rich could
implement an API compatible with ``print(..., pretty=RichPrinter)`` fairly easily. Rich's API is designed to
print constructor-like representations of instances, which means that it's not possible to control much of the
"class chrome" around the arguments. Rich does support using angle brackets (i.e. ``<...>``) instead of
parentheses by setting the attribute ``.angular=True`` on the rich repr method. This PEP does not support
that feature, although it likely could in the future.
<rich-repr-protocol_>`_. The idea is that Rich could implement an API
compatible with ``print(..., pretty=RichPrinter)`` fairly easily. Rich's API
is designed to print constructor-like representations of instances, which
means that it's not possible to control much of the "class chrome" around the
arguments. Rich does support using angle brackets (i.e. ``<...>``) instead of
parentheses by setting the attribute ``.angular=True`` on the rich repr
method. This PEP does not support that feature, although it likely could in
the future.

This also means that there's no way to control the pretty printed format of built-in types like strings,
dicts, lists, etc. This seems fine as ``pprint`` is not intended to be as feature-rich (pun intended!) as
Expand All @@ -232,6 +266,32 @@ multiple objects with, say a newline between the object representations. Compar
It's likely you'll want the second output, but more complicated multi-object displays could get even less
convenient and/or more verbose.

print's pretty argument could just take a callable
--------------------------------------------------

There was [a suggestion](https://discuss.python.org/t/pep-813-the-pretty-print-protocol/106242/2) in the DPO
thread that the third form of ``print(..., pretty=not_none_or_true)`` could generalize to any
callable taking a single argument, rather than requiring it to be an instance with a
``pformat()``-compatible method. We don't need both, but the suggested generalization could be useful. I.e.

.. code-block:: python

pprint(myobj, pretty=MyPrinter())

vs.

.. code-block:: python

pprint(myobj, pretty=MyPrinter().pformat)


Deferred Ideas
==============

Possibly add support for ``!p`` conversions to t-strings.

``!p`` conversions could include format specifiers.


Acknowledgments
===============
Expand All @@ -245,6 +305,20 @@ Footnotes
TBD


Change History
==============

* `TBD <TBD>`__

* Specify that to pretty print tuples as positional arguments, use the 2-tuple value format, passing
a "false-y" value as the argument name.
* Clarify that a truth-y ``name`` must be a ``str``.
* Specify that the ``!p`` conversion in f-strings and ``str.format()`` implicitly perform an
import of the ``pprint`` module.
* Clarify the language around the new optional keyword-only argument ``pretty`` to ``print()``.
* Describe the new Limited C API function ``PyObject_Pretty()``.


Copyright
=========

Expand Down
Loading