Skip to content

Conversation

@hauntsaninja
Copy link
Collaborator

@hauntsaninja hauntsaninja commented Dec 15, 2025

Fixes #10023 , fixes #13674 , closes #10237

@hauntsaninja hauntsaninja changed the title Allow literals as kwargs keys Allow literals as kwargs dict keys Dec 15, 2025
@github-actions
Copy link
Contributor

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

pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/generic.py:4771: error: Unused "type: ignore[misc]" comment  [unused-ignore]
+ pandas/core/generic.py:4842: error: Unused "type: ignore[misc]" comment  [unused-ignore]
+ pandas/core/generic.py:5610: error: Unused "type: ignore" comment  [unused-ignore]

rotki (https://github.com/rotki/rotki)
+ rotkehlchen/exchanges/binance.py:355: error: Unused "type: ignore" comment  [unused-ignore]

xarray (https://github.com/pydata/xarray)
- xarray/core/common.py:460: error: Keywords must be strings  [misc]
+ xarray/core/common.py:460: error: Argument after ** must have string keys  [arg-type]
- xarray/core/dataset.py:5204: error: Keywords must be strings  [misc]
+ xarray/core/dataset.py:5204: error: Argument after ** must have string keys  [arg-type]

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Thanks!

@JukkaL JukkaL merged commit eb144ce into python:master Dec 15, 2025
23 checks passed
return (
is_subtype(
(
# This is a little ad hoc, ideally we would have a map_instance_to_supertype
Copy link
Contributor

Choose a reason for hiding this comment

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

Imo this whole approach is technically incorrect. SupportsKeysAndGetItem is invariant in key type, so prescribing str will cause errors if a dict with literal keys is given

Comment on lines +571 to +579
[case testLiteralKwargs]
from typing import Any, Literal
kw: dict[Literal["a", "b"], Any]
def func(a, b): ...
func(**kw)

badkw: dict[Literal["one", 1], Any]
func(**badkw) # E: Argument after ** must have string keys
[builtins fixtures/dict.pyi]
Copy link
Contributor

Choose a reason for hiding this comment

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

This modified test produces false-positive for good_kw:

# [case testLiteralKwargs]
from typing import Literal

def func(a: int, b: int) -> None: ...
class A: pass

good_kw: dict[Literal["a", "b"], int]
bad_kw: dict[Literal["one", 1], int]

func(**good_kw)
func(**bad_kw)  # E: Argument after ** must have string keys
# [builtins fixtures/dict.pyi]

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hm, this PR does handle correctly handle that test case. The patch is ad hoc though, so e.g. it would fail if you changed it to Mapping

Copy link
Contributor

Choose a reason for hiding this comment

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

You're right, I think tested with the wrong commit

Copy link
Contributor

Choose a reason for hiding this comment

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

I did make the proposed change into a helper function: #20419

@randolf-scholz
Copy link
Contributor

I've added a code that fixes the good_kw case here: c96d66e

I could move this into a separate PR, and maybe it's worth making that procedure into a helper function?

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.

Literal of type string not accepted as keyword name Mypy incorrectly warns when passing literals as kwarg keywords

3 participants