Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate better error message for incompatible **kwargs #8874

Open
JukkaL opened this issue May 22, 2020 · 10 comments · May be fixed by #13146, kr321/mypy#3 or #17186
Open

Generate better error message for incompatible **kwargs #8874

JukkaL opened this issue May 22, 2020 · 10 comments · May be fixed by #13146, kr321/mypy#3 or #17186
Labels

Comments

@JukkaL
Copy link
Collaborator

JukkaL commented May 22, 2020

This output is from #8772:

$ mypy test.py 
test.py:6: error: Argument 2 to "dumps" has incompatible type "**Dict[str, int]"; expected "bool"
test.py:6: error: Argument 2 to "dumps" has incompatible type "**Dict[str, int]"; expected "Optional[Type[JSONEncoder]]"
test.py:6: error: Argument 2 to "dumps" has incompatible type "**Dict[str, int]"; expected "Optional[Tuple[str, str]]"
test.py:6: error: Argument 2 to "dumps" has incompatible type "**Dict[str, int]"; expected "Optional[Callable[[Any], Any]]"
Found 4 errors in 1 file (checked 1 source file)

The error messages are pretty confusing. We should special case this and produce a customized error message that explains the situation better.

Here's the code that triggers the errors:

import json

json_kwargs = dict(indent=2)

json.dumps({}, **json_kwargs)

Some ideas about what to do:

  • Generate a single error message instead of multiple ones.
  • Add a note suggesting the use of Dict[str, Any] or a TypedDict type for the **kwargs argument.
  • Maybe also explain that mypy matches the value type against all arguments, or add a link to documentation (add something to common issues, for example).
@rohitkg98
Copy link

I would like to work on this. Seems straight forward, just need to change code here, right?

@rohitkg98
Copy link

I believe there should be multiple error messages, to inform of all callable argument type mismatch.

@Uttam-Singhh
Copy link

Can I work on it??

@rohitkg98
Copy link

Sure, I have not been able to continue work on it, feel free to do so. Take a look at the PR I made, let me know if you need help!

@Uttam-Singhh
Copy link

@rohitkg98 I was looking at your PR and I saw that it passed all the checks then why it was not merged?
I am new to open source. Can you please help and guide me on how to work on this issue & why was your code not merged?

@noob8boi
Copy link
Contributor

noob8boi commented Nov 5, 2021

is this issue still open?

@JelleZijlstra JelleZijlstra added the topic-calls Function calls, *args, **kwargs, defaults label Mar 19, 2022
@JukkaL
Copy link
Collaborator Author

JukkaL commented Jul 16, 2022

One idea for a note:

...: note: Consider using a TypedDict type or "Dict[str, Any]" for the ** argument

@reka reka linked a pull request Jul 16, 2022 that will close this issue
@Arzugar
Copy link

Arzugar commented Apr 7, 2024

Hi, I plan to work on this issue.
My take on this issue is that as discussed in #8772 this behavior is to be expected, and an error message should indeed be thrown.
But the message needs improvement. I will implement what has been proposed in PR #8960 by gvanrossum and modify existing tests accordingly in order to get it merged.

As a new and inexperienced contributor I'm open to any suggestions or comments.

@Arzugar
Copy link

Arzugar commented Apr 10, 2024

Hello,
I could really use someone's opinion on this case :

def f(a: int = 42, b: str = "hello world"): ...


d = dict(a=3, b="Bye")  # is inferred as Dict[str, object]
f(**d)

This code cannot be statically typed, and so we should indicate to the user a way of making it work.
My question is : which of the following solution is the best ? My personal opinion is that the first one should be preferred, because it seems safer.

Solution 1

from typing import TypedDict

class Params(TypedDict):
    a: int
    b: str


d: Params = dict(a=3, b="hello")

f(**d)

Solution 2

d: Dict[str, Any] = dict(a=3, b="hello")
f(**d)

@hauntsaninja
Copy link
Collaborator

I think both have their place, the note Jukka suggests here #8874 (comment) seems like a good phrasing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment