Skip to content

fix(pprint): pretty-print frozendict (Python 3.15+) key-per-line in assertion diffs - #15260

Closed
Abhiroop3917 wants to merge 2 commits into
pytest-dev:mainfrom
Abhiroop3917:fix/pprint-frozendict-15172
Closed

Abhiroop3917 wants to merge 2 commits into
pytest-dev:mainfrom
Abhiroop3917:fix/pprint-frozendict-15172

Conversation

@Abhiroop3917

Copy link
Copy Markdown

Type of changes

  • Bug fix
  • New feature
  • Documentation / docstrings
  • Tests
  • Other

AI?

  • AI was used to generate this PR

Checklist

  • I've run the latest black with default args on new code.
  • I've updated CHANGELOG.md and CONTRIBUTORS.md where appropriate.
  • I've added tests for new code.
  • I accept that @pytest-dev/pytest may be pedantic in the code review.

Description

Python 3.15 added frozendict as a built-in type (PEP 814). When an assertion comparing two lists of frozendicts fails with -vv, the "Full diff" prints each frozendict on a single line because _pytest/_io/pprint.py has no dispatch handler for it, falling through to repr().

A dict with the same contents gets one key per line, making the changed value easy to spot. With frozendict the change is buried mid-line.

Root cause: PrettyPrinter._dispatch has handlers for dict, OrderedDict, defaultdict, MappingProxyType, etc., but not frozendict.

Fix: Add _pprint_frozendict, mirroring _pprint_ordered_dict, and register it only when builtins.frozendict exists (Python 3.15+). Older Python versions are completely unaffected.

Before:

Full diff:
  [
      frozendict({'name': 'alice', 'age': 30, 'city': 'Lagos'}),
-     frozendict({'name': 'bob', 'age': 26, 'city': 'Abuja'}),
+     frozendict({'name': 'bob', 'age': 25, 'city': 'Abuja'}),
  ]

After:

Full diff:
  [
      frozendict({
          'name': 'alice',
          'age': 30,
          'city': 'Lagos',
      }),
      frozendict({
          'name': 'bob',
-         'age': 26,
+         'age': 25,
          'city': 'Abuja',
      }),
  ]

closes #15172

…iffs

Python 3.15 adds frozendict as a built-in (PEP 814). Because pprint.py had
no dispatch handler for it, frozendict values fell back to a single-line
repr(), hiding the changed key mid-line in assertion diffs.

Add _pprint_frozendict, registered only when builtins.frozendict exists, so
Python < 3.15 is unaffected. The handler mirrors _pprint_ordered_dict:
wraps the dict formatting in frozendict({...}) so each key prints on its
own line, matching the dict behaviour users already rely on.

Closes pytest-dev#15172
@pyba-chronographer pyba-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Oct 25, 2026
@bluetech

Copy link
Copy Markdown
Member

Thanks, but there is already a PR open for this.

@bluetech bluetech closed this Oct 25, 2026
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)

2 participants