Skip to content

Conversation

@hrideymarwah15
Copy link

@hrideymarwah15 hrideymarwah15 commented Jan 16, 2026

Summary

This PR fixes issue #13503 by preserving dictionary insertion order in assertion failure output instead of sorting keys alphabetically.

Problem

Since Python 3.7+, dictionaries maintain insertion order. However, pytest's assertion output was sorting dictionary keys alphabetically, which:

  • Doesn't match Python's native dict display behavior
  • Makes debugging confusing when developers expect insertion order
  • Provides misleading output for ordered data structures

Solution

Removed sorted() calls in the PrettyPrinter class:

  • _pprint_dict method: Changed sorted(object.items(), key=_safe_tuple) to object.items()
  • _safe_repr method: Changed sorted(object.items(), key=_safe_tuple) to object.items()

Changes

  • Modified src/_pytest/_io/pprint.py to preserve dict insertion order (2 lines changed)
  • Added test test_dict_preserves_insertion_order in testing/io/test_pprint.py (33 lines added)
  • Allow maintainers to push and squash when merging

Example

Before:

assert {'z': 1, 'a': 2, 'm': 3} == {'z': 1, 'a': 3, 'm': 3}
# Output showed: {'a': 2, 'm': 3, 'z': 1} (alphabetical)

After:

assert {'z': 1, 'a': 2, 'm': 3} == {'z': 1, 'a': 3, 'm': 3}
# Output shows: {'z': 1, 'a': 2, 'm': 3} (insertion order)

Closes #13503

Remove sorted() calls in PrettyPrinter to preserve dict insertion order.

Since Python 3.7+, dicts maintain insertion order. Sorting keys
alphabetically in assertion failures is confusing and doesn't match
how Python naturally displays dicts.

Changes:
- _pprint_dict: Remove sorted() on object.items()
- _safe_repr: Remove sorted() on dict.items() iteration

Fixes pytest-dev#13503
Add test_dict_preserves_insertion_order to verify that dictionary
keys maintain their insertion order in assertion output, not
alphabetical order.

This test ensures the fix for issue pytest-dev#13503 works correctly and
prevents future regressions.

Related to pytest-dev#13503
Copilot AI review requested due to automatic review settings January 16, 2026 12:24
@psf-chronographer psf-chronographer bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Jan 16, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes issue #13503 by preserving dictionary insertion order in assertion failure output instead of sorting keys alphabetically, aligning pytest's output with Python 3.7+ dict behavior.

Changes:

  • Removed alphabetical sorting of dictionary keys in PrettyPrinter class methods
  • Added test to verify insertion order preservation
  • Added changelog entry documenting the bugfix

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/_pytest/_io/pprint.py Removed sorted() calls in _pprint_dict and _safe_repr methods to preserve dict insertion order
testing/io/test_pprint.py Added test_dict_preserves_insertion_order test to verify insertion order is maintained
changelog/13503.bugfix.rst Added changelog entry documenting the bugfix
Comments suppressed due to low confidence (1)

src/_pytest/_io/pprint.py:37

  • The docstring's last sentence mentions 'dict.items() must have _safe_key applied' which is now outdated since the PR removes sorting from dict items. While _safe_key is still used for sets (line 239), the documentation should be clarified to avoid confusion. Consider updating to: 'Does not work recursively, so for collections that are sorted (like sets), both key and value must have _safe_key applied.'
class _safe_key:
    """Helper function for key functions when sorting unorderable objects.

    The wrapped-object will fallback to a Py2.x style comparison for
    unorderable types (sorting first comparing the type name and then by
    the obj ids).  Does not work recursively, so dict.items() must have
    _safe_key applied to both the key and the value.

    """

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

pre-commit-ci bot and others added 6 commits January 16, 2026 12:34
Improve code coverage by adding test that triggers the _safe_repr
code path with depth limiting, ensuring both modified lines in
pprint.py are fully covered.

This addresses Codecov target of 100% diff coverage.
Call _safe_repr directly to ensure the dict sorting code path
in _safe_repr is tested, achieving 100% diff coverage.
@nicoddemus
Copy link
Member

Thanks, but duplicate of #14066.

@nicoddemus nicoddemus closed this Jan 16, 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.

Failure output order of dictionary keys is alphabetical instead of insertion order

2 participants