Repository navigation
PEP 813: bring the implementation in line with the PEP draft - #2
Conversation
PEP 813 specifies PyObject_Pretty() in the limited C API. It calls the printer (the default one when printer is NULL), joins the lines it returns with '\n', and returns the str, mirroring PyObject_Str() and friends. It raises TypeError if the printer returns a str, whose items are characters rather than lines, or if any line is not a str. FORMAT_PRETTY and str.format() now call it, so the join and its checks live in one place. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…__(). Both methods would be defined on the same class, so the MRO rule would use the generated __pprint__(), which describes every field, instead of the hand-written __repr__(), which may hide some of them. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Re-export the protocol's names from pprint, lazily, so that importing
pprint stays cheap.
* Add pprint.LEAF, which decompose() returns for a leaf, and
pprint.DescriptionType.
* Add pprint.FormattableNumber. int and float delegate to it, and the
Printer formats it with its new number_format option, a format spec.
If format() raises, the number is printed with repr().
* Add a Layout.hug attribute. When exactly one item is a container, the
other items stay on the opening and closing lines, as PrettyPrinter does
with expand=True. defaultdict, mappingproxy, the MappingViews and deque
use it.
* Split strings and bytes when rendering, so that the split depends on the
column, as in PrettyPrinter. Only a literal that is the whole object is
parenthesized. The continuation lines of a nested literal are aligned
under its first piece.
* Match PrettyPrinter for bytearray and deque, print OrderedDict as
OrderedDict({...}), use '(...)' for tuple recursion, and describe an
Interpolation positionally, to agree with repr().
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This fixes test_embed's test_frozenmain. Co-Authored-By: Claude Opus 5.5 <[email protected]>
What's left after this PRThese are the remaining differences from the PEP draft, and questions for the two of us. To do
Differences from
|
list(range(100_000)) |
0.51 s |
| 100,000 floats | 0.52 s |
[None] * 100_000, leaves with no __pprint__() |
0.38 s |
pprint.pformat(list(range(100_000))) |
0.08 s |
So the FormattableNumber delegation adds about a third over a plain leaf. The bigger gap is that the document-based printer is about 6× slower than PrettyPrinter overall. The PEP accepts some cost for maintainability, but the renderer may be worth profiling before this goes upstream.
🤖 Generated with Claude Code
This brings the branch in line with the current PEP 813 draft (python/peps#5191). Each commit has the details.
PyObject_Pretty()in the limited C API (I think its removal was accidental). It joins the printer's lines and returns astr, likePyObject_Str(). It raisesTypeErrorif the printer returns astr, which used to give one line per character, or a line that isn't astr.FORMAT_PRETTYandstr.format()both call it.__repr__()no longer gets a generated__pprint__(). The generated method won under the MRO rule, so it bypassed the hand-writtenrepr(), including one that hides a secret field.pprint, lazily, soimport pprintdoesn't import_pprintordataclasses.pprint.LEAF, whichdecompose()returns as(LEAF, None)for a leaf.pprint.DescriptionType.pprint.FormattableNumber, used byintandfloat, together with anumber_formatoption that replacesunderscore_numbers. It's a format spec, such as'_'or',', and the printer falls back torepr()ifformat()raises.Layout.hug, which keepsdefaultdict(<class 'list'>, {and similar on one line, asPrettyPrinter(expand=True)does.PrettyPrinter. Only a top-level literal is parenthesized.PrettyPrinter:bytearray,deque(includingmaxlen),mappingproxy, theMappingViews anddefaultdict, plus strings and bytes inside containers.repr(): tuple recursion now prints(...), andInterpolationis described positionally.Programs/test_frozenmain.his regenerated for the new opcode, which fixestest_embed.Testing
test__pprintcompare the output withpprint.pformat()for these cases, in both modes.test_fstringcover the printer result checks, andtest_dataclassescovers the__repr__()bug.test_remote_pdb, which hung in my environment and was stopped. It doesn't touch any of this code.🤖 Generated with Claude Code