Skip to content
Merged
Changes from 3 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
80 changes: 71 additions & 9 deletions peps/pep-0813.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ 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.
``name=value`` is used. If ``name`` is ``None`` or the empty string, then ``value`` is treated as a
positional argument. This is how you would print a positional argument with a tuple value. See
:ref:`examples`.
* 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.
Comment thread
warsaw marked this conversation as resolved.
Outdated
Expand All @@ -85,8 +87,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 +108,8 @@ 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.

.. _examples:

Examples
========

Expand Down Expand Up @@ -167,6 +171,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 ``None`` or the empty string.

.. 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 +224,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 +256,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 +295,18 @@ Footnotes
TBD


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

* `TBD <TBD>`__

* Specify that to pretty print tuples as positional arguments, use the 2-tuple value format, passing
``None`` or the empty string as the argument name.
* 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()``.


Copyright
=========

Expand Down
Loading