Skip to content

Pretty-print builtin frozendict in assertion diffs - #15173

Merged
bluetech merged 1 commit into
pytest-dev:mainfrom
HakeemTheEmperor:fix-frozendict-print
Oct 25, 2026
Merged

bluetech merged 1 commit into
pytest-dev:mainfrom
HakeemTheEmperor:fix-frozendict-print

Conversation

@HakeemTheEmperor

Copy link
Copy Markdown
Contributor

Closes #15172

On Python 3.15, assertion diffs printed frozendict on a single line because
PrettyPrinter._dispatch had no entry for it, so it fell back to a plain repr.
This registers frozendict on 3.15+, reusing _pprint_ordered_dict since both
types repr as Name({...}). Subclasses use their own class name.

The registration and test are guarded by sys.version_info >= (3, 15), with
# noqa: F821 because ruff checks against Python 3.10, where frozendict
doesn't exist.

  • Include new tests or update existing tests when applicable.
  • Allow maintainers to push and squash when merging my commits.
  • Add text like closes #XYZW to the PR description and/or commits.
  • If AI agents were used, they are credited in Co-authored-by commit trailers.
  • Create a new changelog file in the changelog directory.
  • Add yourself to AUTHORS in alphabetical order.

@pyba-chronographer pyba-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Oct 13, 2026

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this.

The pprint.py file is derived from upstream's pprint code: https://github.com/python/cpython/blob/main/Lib/pprint.py

It looks like they frozendict support there is a little different from the approach taken here of reusing OrderedDict formatting.

Do you mind taking a look at the upstream change https://github.com/python/cpython/pull/144908/changes and see if it's relevant for us or not? When in doubt I'd see it's better to follow upstream (except for the specific formatting changes for which we forked from upstream in the first place).

@HakeemTheEmperor

Copy link
Copy Markdown
Contributor Author

Alright

I'm looking into it now

@HakeemTheEmperor

HakeemTheEmperor commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the pointer. I went through the upstream change. It has two parts:

  1. _pprint_frozendict for the main formatting: upstream uses CPython’s aligned layout, while pytest’s fork prints mappings one item per line with trailing commas. Reusing _pprint_ordered_dict keeps frozendict consistent with how pytest already prints dict and OrderedDict, so I’ve kept that.
  2. _safe_repr: this one applies to us. Since frozendict is hashable it can be a dict key, and keys go through _safe_repr, which didn’t know about frozendict, so the depth limit was ignored there. I’ve ported the upstream handling (empty → frozendict(), depth → frozendict({...}), wrapped repr) and added a test for the depth case.

Happy to adjust if you’d rather follow upstream for part 1 as well.

On Python 3.15+, register frozendict in PrettyPrinter._dispatch, reusing
the OrderedDict printer since both repr as Name({...}). Previously it
fell back to a single-line repr, making diffs hard to read.

Closes pytest-dev#15172
@bluetech
bluetech force-pushed the fix-frozendict-print branch from 879c8dd to 6e6c996 Compare October 25, 2026 14:39

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some tweaks. It's good now, thanks.

@bluetech
bluetech merged commit 7d646b5 into pytest-dev:main Oct 25, 2026
67 of 68 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Assertion diff doesn't pretty-print the built-in frozen dict (Python 3.15)

3 participants