-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Odd error message when kwargs passed as **dict #5382
Comments
(I just tried defining |
@scop Hey, take a look at this SO question. It should help you understand why you're getting the first error. The answer to this question will explain you that the type of the def __init__(self, max_workers: Optional[int] = ...,
thread_name_prefix: str = ...) -> None: ... but mypy thinks you're passing |
I've hit the same issue with passing a dict of kwargs. I'm also on mypy 0.620, python 3.6.5. Here's a small repro: def test(a: int = 1, b: str = 'hi', c: bool = True) -> None:
return None
kwargs = {"a": 1, "b": "hello", "c": False}
test(**kwargs) This code is correct at runtime, but generates the following mypy errors:
I can suppress this error by either:
Something that I might expect to help, but doesn't, is annotating The first two ways are not really fixes, and the third is not always an option. Is there a good way to keep mypy from emitting this false positive? |
class Options(TypedDict):
a: int
b: str
c: bool
kwargs: Options = {"a": 1, "b": "hello", "c": False}
test(**kwargs) # OK Note however that this may trade false positive for false negative because of #5198 |
Also this is not really a false positive. There is no way mypy can guarantee that a key will be e.g. deleted from this dictionary (it will however prevent you from deleting keys if this is a |
This happened again, so raising priority to normal. Btw we can at least infer |
This appeared three more times, so raising priority to high. |
Hit this today, inconsistently, in several places. I can confirm that adding an explicit |
If the general problem is hard to solve. Would it be easier (and still valuable) to add support for something like:
|
Supporting frozen typed dicts is also a possible solution. We can even support both things (this and the older idea of inferring typed dict types for dict literals appearing directly in a call).
The core team has very limited resources, if you want to work on this, please go ahead. |
I got this today as well, using a TypedDict fixed the mypy error :) |
I got this today as well. Unfortunately using a TypedDict doesn't work in my case 😢
causes a new error Using |
Similar to #8890 |
I've just hit this error with Example from dataclasses import dataclass
@dataclass(slots=True, kw_only=True, frozen=True)
class TestClass:
ID: int
name: str
domain: str
secure: bool
data = {
"ID": 1,
"name": "example",
"domain": "example.com",
"secure": True,
}
TestClass(**data) Output > mypy test_my.py
test_my.py:20: error: Argument 1 to "TestClass" has incompatible type "**Dict[str, object]"; expected "int"
test_my.py:20: error: Argument 1 to "TestClass" has incompatible type "**Dict[str, object]"; expected "str"
test_my.py:20: error: Argument 1 to "TestClass" has incompatible type "**Dict[str, object]"; expected "bool"
Found 3 errors in 1 file (checked 1 source file) Versions
|
I run into this problem today with below case: error_kwargs = {
"tags": {
"foo": bar,
},
"contexts": {"foo": {"bar": "bar"}},
}
if error_msg in self.non_retryable_errors:
raise NonRetryableResponseError(**error_kwargs)
else:
raise RetryableResponseError(**error_kwargs) I chose to just annotate |
Hit this with pydantic's create_model: fields = {
"test": (str, "")
}
create_model("model", **fields) |
We can now at least check kwargs with differing types in a function definition by using Unpack with TypedDict, though the error message without that is still a little confusing. https://github.com/python/mypy/blob/master/CHANGELOG.md#mypy-17 |
This seems related to python/mypy#5382
Checking this with mypy 0.620:
...yields:
Let's ignore the first error for now. But the second seems to have an incorrect message, specifically I think the **Dict[str, None] in it is weird. Just guessing, is it trying to assign something to the ThreadPoolExecutor's thread_name_prefix arg which is a str? Maybe the None from max_workers because passing kwargs as a dict like this might result in random/varying order of the dict items? But if that's the case, I'd expect it to say something else than **Dict[str, None] as the culprit, maybe None or int, but not the whole **dict.
Another thought is that when kwargs is passed as **dicts like this, their order is not really defined, so "Argument 1" isn't very helpful. Would be better to say the argument's name.
But maybe I'm just all off track here -- will leave the rest to someone who actually has an informed opinion :)
The text was updated successfully, but these errors were encountered: