diff --git a/peps/pep-0813.rst b/peps/pep-0813.rst index f582710c0ed..6d5937e16d5 100644 --- a/peps/pep-0813.rst +++ b/peps/pep-0813.rst @@ -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. @@ -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 @@ -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 `_. +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 ======== @@ -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 ======================= @@ -205,13 +234,18 @@ None at this time. Open Issues =========== +Rich compatibility +------------------ + The output format and APIs are heavily inspired by `Rich -`_. 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. +`_. 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 @@ -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 =============== @@ -245,6 +305,20 @@ Footnotes TBD +Change History +============== + +* `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 =========