WIP: broaden isdict() to support generic Mapping types (#14461) [no review yet]#14463
Draft
RonnyPfannschmidt wants to merge 1 commit into
Draft
WIP: broaden isdict() to support generic Mapping types (#14461) [no review yet]#14463RonnyPfannschmidt wants to merge 1 commit into
RonnyPfannschmidt wants to merge 1 commit into
Conversation
) [AI-assisted experiment — not ready for review] Change isdict() from isinstance(x, dict) to isinstance(x, Mapping) so that non-dict Mapping types (MappingProxyType, ChainMap, UserDict, bidict, immutables.Map, etc.) get structured "Differing items / Omitting N identical items / Left contains N more items" output instead of falling through to the generic iterable diff. Adds tests for stdlib mapping types and xfail tests documenting known-problematic external types where set(keys) diverges from the mapping's own key equality (case-insensitive dicts, multi-valued dicts). Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Sonnet 4 <claude@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
[AI-assisted WIP experiment — no review yet]
Broadens
isdict()fromisinstance(x, dict)toisinstance(x, Mapping)so non-dict Mapping types get structured assertion diff output (#14461).src/_pytest/assertion/util.py_compare_eq_dictalready acceptsMappingin its type signature, so only the guard needed changingdictis a subclass ofMappingMapping types surveyed
Now get structured diff (previously fell through to generic iterable diff):
types.MappingProxyType(stdlib)collections.ChainMap(stdlib)collections.UserDict(stdlib)immutables.Mapbidict/frozenbidicthttpx.Headers(normalizes keys on iteration, so set() works)Already handled (dict subclasses):
collections.OrderedDictpython-box.Box/dynaconf.DynaBoxsortedcontainers.SortedDictKnown-problematic — xfail tests added as documentation:
requests.CaseInsensitiveDict— iterates original-cased keys, soset(left) & set(right)misses common keys when casing differs (misleading, not crash)multidict.MultiDict—set()collapses duplicate keys,__getitem__returns only first value (silently lossy, not crash)multidict.CIMultiDict— both problems combinedKey insight
The failure modes for non-dict Mappings are misleading output, not crashes. The
_compare_eq_dictalgorithm (set(keys)intersection/difference +mapping[k]lookups) works correctly for the vast majority of real-world Mapping implementations. The problematic types (case-insensitive, multi-valued) produce suboptimal but still safe output — which is better than the current state of no structured diff at all.Test plan
TestAssert_reprcompare*tests pass (no regression)Made with Cursor