Skip to content

Conversation

@Vikash-Kumar-23
Copy link

Summary
This PR addresses issue #20706, where mypy failed to catch a TypeError occurring at runtime when non-string keys were used within dictionary unpacking (**).

In Python, keyword unpacking via the ** operator requires all keys to be valid identifiers (strings). While mypy caught this in most contexts, it missed the error inside dict() constructors because the unpacked mapping was incorrectly being matched to positional parameters in the constructor's overloads.

Changes
Updated visit_dict_expr: Modified this method in mypy/checkexpr.py to validate **expr items before they are unpacked.

Key Validation: Integrated a check to ensure unpacked expressions are mappings with keys compatible with builtins.str.

Error Diagnostic: Triggered invalid_keyword_var_arg when non-string keys are detected to align static analysis with runtime behavior.

Checklist
[x] Read the Contributing Guidelines.

[x] Added tests for all changed behavior.

[x] Verified that my code passes the local test suite using pytest mypy/test/testcheck.py.

Verification
Verified locally with the following reproduction script:

Python
d: dict[int, int] = {10: 20}
dict(**d) # Now correctly reports: error: Argument after ** must have string keys [arg-type]

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 1, 2026

Diff from mypy_primer, showing the effect of this PR on open source code:

optuna (https://github.com/optuna/optuna)
+ optuna/storages/journal/_storage.py:645: error: Argument after ** must have string keys  [arg-type]

prefect (https://github.com/PrefectHQ/prefect)
+ src/prefect/settings/profiles.py:178: error: Argument after ** must have string keys  [arg-type]

anyio (https://github.com/agronholm/anyio)
+ src/anyio/streams/stapled.py:59: error: Argument after ** must have string keys  [arg-type]
+ src/anyio/streams/stapled.py:60: error: Argument after ** must have string keys  [arg-type]
+ src/anyio/streams/stapled.py:95: error: Argument after ** must have string keys  [arg-type]
+ src/anyio/streams/stapled.py:96: error: Argument after ** must have string keys  [arg-type]
+ src/anyio/streams/tls.py:266: error: Argument after ** must be a mapping, not "Mapping[T_Attr, Callable[[], T_Attr]] | Mapping[T_Attr, Callable[[], T_Attr]]"  [arg-type]

zulip (https://github.com/zulip/zulip)
+ zerver/lib/display_recipient.py:209: error: Argument after ** must have string keys  [arg-type]

paasta (https://github.com/yelp/paasta)
+ paasta_tools/kubernetes/application/tools.py:87: error: Argument after ** must have string keys  [arg-type]

strawberry (https://github.com/strawberry-graphql/strawberry)
+ strawberry/schema/schema_converter.py:265: error: Argument after ** must have string keys  [arg-type]

cki-lib (https://gitlab.com/cki-project/cki-lib)
+ tests/kcidb/test_validate.py:200: error: Argument after ** must be a mapping, not "Collection[str]"  [arg-type]

core (https://github.com/home-assistant/core)
+ homeassistant/util/unit_system.py:264: error: Argument after ** must have string keys  [arg-type]
+ homeassistant/util/unit_system.py:324: error: Argument after ** must have string keys  [arg-type]
+ homeassistant/util/unit_system.py:344: error: Argument after ** must have string keys  [arg-type]
+ homeassistant/util/unit_system.py:406: error: Argument after ** must have string keys  [arg-type]
+ homeassistant/components/knocki/coordinator.py:51: error: Argument after ** must have string keys  [arg-type]
+ homeassistant/components/duke_energy/coordinator.py:205: error: Argument after ** must have string keys  [arg-type]
+ homeassistant/components/systemmonitor/coordinator.py:135: error: Argument after ** must have string keys  [arg-type]

sympy (https://github.com/sympy/sympy)
+ sympy/physics/units/unitsystem.py:75: error: Argument after ** must have string keys  [arg-type]

pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/frame.py:18533: error: Argument after ** must have string keys  [arg-type]

ibis (https://github.com/ibis-project/ibis)
+ ibis/common/collections.py:263: error: Argument after ** must be a mapping, not "Self"  [arg-type]
+ ibis/common/collections.py:272: error: Argument after ** must be a mapping, not "Self"  [arg-type]
+ ibis/expr/types/relations.py:2447: error: Argument after ** must be a mapping, not "tuple[Value, ...]"  [arg-type]

jax (https://github.com/google/jax)
+ jax/_src/dtypes.py:684: error: Argument after ** must have string keys  [arg-type]
+ jax/_src/dtypes.py:705: error: Argument after ** must have string keys  [arg-type]
+ jax/_src/checkify.py:288: error: Argument after ** must have string keys  [arg-type]
+ jax/_src/checkify.py:289: error: Argument after ** must have string keys  [arg-type]
+ jax/_src/checkify.py:290: error: Argument after ** must have string keys  [arg-type]
+ jax/_src/checkify.py:291: error: Argument after ** must have string keys  [arg-type]

pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
+ tests/dtypes.py:75: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:76: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:77: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:78: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:82: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:85: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:88: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:93: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:96: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:98: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:104: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:105: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:106: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:107: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:111: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:114: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:117: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:122: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:125: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:127: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:134: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:135: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:138: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:143: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:146: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:149: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:170: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:173: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:176: error: Argument after ** must have string keys  [arg-type]
+ tests/dtypes.py:259: error: Argument after ** must have string keys  [arg-type]

pwndbg (https://github.com/pwndbg/pwndbg)
+ pwndbg/aglib/signal.py:96: error: Argument after ** must have string keys  [arg-type]

artigraph (https://github.com/artigraph/artigraph)
+ src/arti/internal/mappings.py:34: error: Argument after ** must have string keys  [arg-type]

xarray (https://github.com/pydata/xarray)
+ xarray/core/dataset.py: note: In member "_to_dataframe" of class "Dataset":
+ xarray/core/dataset.py:7241: error: Argument after ** must have string keys  [arg-type]
+ xarray/core/dataset.py:7242: error: Argument after ** must have string keys  [arg-type]
+ xarray/tests/test_units.py: note: In function "extract_units":
+ xarray/tests/test_units.py:126: error: Argument after ** must have string keys  [arg-type]
+ xarray/tests/test_units.py:133: error: Argument after ** must have string keys  [arg-type]
+ xarray/tests/test_units.py:137: error: Argument after ** must have string keys  [arg-type]
+ xarray/tests/test_units.py:141: error: Argument after ** must have string keys  [arg-type]
+ xarray/tests/test_units.py: note: In member "test_broadcast_equals" of class "TestVariable":
+ xarray/tests/test_units.py:1850: error: Argument after ** must have string keys  [arg-type]
+ xarray/tests/test_units.py: note: In member "test_broadcast_equals" of class "TestDataArray":
+ xarray/tests/test_units.py:3161: error: Argument after ** must have string keys  [arg-type]
+ xarray/tests/test_units.py: note: At top level:

nox (https://github.com/wntrblm/nox)
+ nox/manifest.py:271: error: Argument after ** must have string keys  [arg-type]

Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

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

Add tests, analyse the primer diff, make sure you account for this #20706 (comment)

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.

2 participants