Skip to content

Forward ignore_extra to nested checked types in CheckedPMap.create - #328

Open
lntutor wants to merge 1 commit into
tobgu:masterfrom
lntutor:fix/checkedpmap-forward-ignore-extra-326
Open

Forward ignore_extra to nested checked types in CheckedPMap.create#328
lntutor wants to merge 1 commit into
tobgu:masterfrom
lntutor:fix/checkedpmap-forward-ignore-extra-326

Conversation

@lntutor

@lntutor lntutor commented Jul 26, 2026

Copy link
Copy Markdown

Fixes #326

Description

CheckedPMap.create(..., ignore_extra=True) does not forward ignore_extra to the nested checked key/value CheckedType.create calls. As a result, extra fields in a nested checked value (e.g. a PRecord) still raise even though ignore_extra=True was requested. CheckedPVector / CheckedPSet thread ignore_extra correctly (via the _checked_type_create helper); CheckedPMap was the one collection that dropped it.

from pyrsistent import CheckedPMap, PRecord, field

class Rec(PRecord):
    a = field()

class M(CheckedPMap):
    __key_type__ = str
    __value_type__ = Rec

M.create({"k": {"a": 1, "extra": 2}}, ignore_extra=True)
# before: AttributeError: 'extra' is not among the specified fields for Rec
# after:  M({'k': Rec(a=1)})

Root cause

In CheckedPMap.create (pyrsistent/_checked_types.py), the nested checked_key_type.create(key) and checked_value_type.create(value) calls omitted ignore_extra=ignore_extra. The sibling helper _checked_type_create (used by CheckedPVector/CheckedPSet) already forwards it.

Fix

Pass ignore_extra=ignore_extra to both nested create calls. Both CheckedType.create (the abstract base signature) and PRecord.create accept ignore_extra, so forwarding is safe for every valid key/value type.

Added tests

In tests/checked_map_test.py, mirroring the existing ignore_extra patterns in tests/record_test.py:

  • test_create_forwards_ignore_extra_to_value — the exact case from the issue (value type is a PRecord).
  • test_create_without_ignore_extra_still_raises_for_value — the default (ignore_extra=False) still raises.
  • test_create_forwards_ignore_extra_to_nested_checked_value — value type is a CheckedPVector of records, so ignore_extra has to be forwarded all the way down.

The two positive tests fail on the unpatched code and pass with the fix. Full suite: pytest tests/ → 640 passed, 1 skipped (also verified with PYRSISTENT_NO_C_EXTENSION=1).

Note: the fix also forwards ignore_extra on the key-create path for symmetry with the value path and with _checked_type_create. That path is not separately unit-tested because a record's source data is a dict (unhashable), so it cannot appear as a map key in practice; the meaningful, user-facing path is the value one covered above.

CheckedPMap.create(..., ignore_extra=True) did not pass ignore_extra to
the nested checked key/value CheckedType.create calls, so extra fields
in a nested checked value (e.g. a PRecord) still raised even though
ignore_extra was requested. CheckedPVector/CheckedPSet thread it through
correctly via _checked_type_create; CheckedPMap was the one collection
that dropped it.

Both CheckedType.create and PRecord.create accept ignore_extra, so
forwarding it to the key and value create calls is safe.

Fixes tobgu#326.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G8b9dEaJtpvydzz4ttM7JH
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.

CheckedPMap.create does not forward ignore_extra to nested CheckedType keys/values

1 participant