Skip to content

PEP 813: sorting and None printer fixes, and a lazily loaded protocol module - #5

Merged
ericvsmith merged 2 commits into
ericvsmith:PEP-813-pprintfrom
warsaw:pep813-sorting-and-none-printer
Oct 23, 2026
Merged

ericvsmith merged 2 commits into
ericvsmith:PEP-813-pprintfrom
warsaw:pep813-sorting-and-none-printer

Conversation

@warsaw

@warsaw warsaw commented Oct 23, 2026 •

Copy link
Copy Markdown

Fixes found while comparing the implementation with the PEP, plus a restructuring of how the protocol code is loaded.

Keyword sorting. A sortable layout with keyword items failed with TypeError: unexpected document node. Keyword items are now sorted by name, after the positional and key/value items, so the output stays valid call syntax: Example('y', 'z', a=10, b=0), never Example(a=10, 'z').

None printer. convert(1, 'p', None) used the default printer, but f'{1!p:{None}}' raised TypeError: 'NoneType' object is not callable. PyObject_Pretty() now treats None like NULL, so all three spellings agree. Interpolation.printer already uses None to mean that no printer was given. The C API docs are updated, and convert() no longer special-cases None.

_pprint_protocol. _load_protocol() and the module __getattr__/__dir__ are gone. The Python half of the protocol (Printer, decompose, Keyword, Entry, Expand, LEAF, DescriptionType and the renderer) now lives at module level in a new private module, Lib/_pprint_protocol.py. pprint re-exports it with lazy from _pprint_protocol import ..., so import pprint alone still imports neither it nor dataclasses, and upstream's test_pprint.test_lazy_import passes unchanged. The C names still come from _pprint. pprint's own function-local imports of dataclasses and re are now lazy imports at the top.

Import cycles. The __pprint__() methods in collections, _collections_abc and dataclasses imported helpers from pprint inside the function. Those helpers are now inlined into the methods, which take Layout, KWARGS, ITEMS and DELEGATE from the C _pprint module with lazy imports. Nothing imports pprint to describe a built-in type any more, so test_lazy_import's forced-eager mode works.

Python/stdlib_module_names.h is regenerated, which also adds the missing _pprint entry.

Tests: test__pprint, test_pprint, test_fstring, test_string, test_tstring, test_dataclasses, test_capi, test_collections, test___all__, test_lazy_import, test_embed, test_site, test_typing, test_enum, test_inspect, test_pydoc and test_sys pass.

🤖 Generated with Claude Code

warsaw and others added 2 commits October 23, 2026 14:43
…ault

Sorting a sortable layout that contains keyword items failed with
TypeError.  Keyword items are now sorted by name after the other items,
so the output stays in call order, as in Example('y', 'z', a=10, b=0).

PyObject_Pretty() now treats a printer of None like NULL and uses the
default printer.  So f'{obj!p:{None}}' matches f'{obj!p}' and
string.templatelib.convert(obj, 'p', None), where None already meant
that no printer was given.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cycles

The protocol code lived inside _load_protocol(), which a module
__getattr__ ran on first use and then copied into the module globals.
It now lives at module level in a new private module, _pprint_protocol,
and pprint re-exports its names with lazy imports.  Importing pprint
alone still does not import dataclasses or the protocol module.

The __pprint__() methods in collections, _collections_abc and
dataclasses imported helpers from pprint inside the function to avoid
import cycles.  The helpers are now inlined into those methods, and
the names they need come from the C _pprint module with lazy imports,
so there is no cycle even when lazy imports are forced eager.

pprint's own function-local imports of dataclasses and re are now lazy
imports at the top of the module.  string.templatelib.convert() no
longer special-cases a printer of None, since PyObject_Pretty() handles
it.  Regenerate stdlib_module_names.h, which also adds the missing
_pprint entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@warsaw
warsaw requested a review from ericvsmith as a code owner October 23, 2026 22:15
@warsaw warsaw changed the title PEP 813: sort keyword items last, and treat a None printer as the default PEP 813: sorting and None printer fixes, and a lazily loaded protocol module Oct 23, 2026
@ericvsmith
ericvsmith merged commit 60a3d64 into ericvsmith:PEP-813-pprint Oct 23, 2026
2 of 3 checks passed
@warsaw
warsaw deleted the pep813-sorting-and-none-printer branch October 23, 2026 22:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants