mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Dict unpacking type checks don't consider **kwargs

Open dinatamas opened this issue 1 year ago • 1 comments

Bug Report:

In the below example (playground gist), mypy behaves differently with respect to **kwargs:

def func(x: bool = False, **kwargs):
    print(x, kwargs)

# This is accepted by mypy.
func(y="y")

# This is flagged by mypy.
data = {"y": "y"}
func(**data)

The error is Argument 1 to "func" has incompatible type "**dict[str, str]"; expected "bool" [arg-type]. This is incorrect because the function has **kwargs, so the dict / function call should be considered type correct.

Your Environment:

  • Mypy version used: latest (1.11.1)
  • Mypy command-line flags: -
  • Mypy configuration options from mypy.ini (and other config files): -
  • Python version used: 3.12

dinatamas avatar Aug 04 '24 17:08 dinatamas

Some related issues:

  • https://github.com/python/mypy/issues/15317
  • https://github.com/python/mypy/issues/5382

153957 avatar Oct 15 '24 16:10 153957

I have overlooked that data may specify x.

def func(x: bool = False, **kwargs):
    print(x, kwargs)

data = {"x": "a"}
func(**data)  # warning

Since mypy has no way to know the content of the dictionary (unless it's a TypedDict or frozendict), it is correct to flag this function call.

If func only expects strings, mypy accepts this.

def func(x: str = "text", **kwargs):
    print(x, kwargs)

data = {"x": "a", "y": "b"}
func(**data)  # ok

It also accepts this if x is explicitly provided.

def func(x: bool = False, **kwargs):
    print(x, kwargs)

data = {"y": "b"}
func(x=True, **data)  # ok

dinatamas avatar Dec 01 '24 09:12 dinatamas

Hence mypy's behavior is correct and I'm closing this ticket.

dinatamas avatar Dec 01 '24 09:12 dinatamas