-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Accept compatible dict in place of TypedDict #3035
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
Conversation
test-data/unit/check-typeddict.test
Outdated
|
||
f({'x': 1, 'y': 3}) | ||
f({'x': 1, 'y': 'z'}) # E: Argument 1 to "f" has incompatible type "TypedDict(x=int, y=str)"; expected "Point" | ||
# E:-1: Incompatible types (expression has type "str", TypedDict item "y" has type "int") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think only one of these error messages should be shown, not both.
mypy/test/data.py
Outdated
@@ -379,7 +379,7 @@ def expand_errors(input: List[str], output: List[str], fnam: str) -> None: | |||
# The first in the split things isn't a comment | |||
for possible_err_comment in input[i].split('#')[1:]: | |||
m = re.search( | |||
'^([ENW]):((?P<col>\d+):)? (?P<message>.*)$', | |||
'^([ENW]):((?P<col>\d+):)?((?P<backtrack>-\d+):)? (?P<message>.*)$', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer this as a separate PR, proposed syntax is debatable and could only delay this PR.
test-data/unit/README.md
Outdated
@@ -29,7 +29,11 @@ Add the test in this format anywhere in the file: | |||
- `# E: abc...` indicates that this line should result in type check error | |||
with text "abc..." | |||
- note a space after `E:` and `flags:` | |||
- lines without `# E: ` should cause no type check errors | |||
- `# E:12` adds column number to the expected error | |||
- `# E:-1` means that the error was expected 2 lines ago (helpful for multiple errors in a line) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you already do 4 = 3 # E: error one # E: error two
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JelleZijlstra Yup ;)
@ilevkivskyi One error is about TypedDict
not matching the dict
structure. But it then infers the wrong TypedDict
anyway (to keep going), and that doesn't fit the function call. I can probably change it to make it one error, but it would require more logic elsewhere in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kwargs=e, | ||
context=e | ||
) | ||
return self.type_context[-1].copy_modified() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please and a comment here about why you do it like this, and how it works?
f({'x': 1, 'y': 'z'}) # E: Incompatible types (expression has type "str", TypedDict item "y" has type "int") | ||
|
||
f(dict(x=1, y=3)) | ||
f(dict(x=1, y=3, z=4)) # E: Expected items ['x', 'y'] but found ['x', 'y', 'z']. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add one more test case with few tests where you assign to variables with explicit types, like:
p: Point = {'x', 'hi'}
and/or
p: Point
p = dict(x='bye')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also maybe a test for
p = Point(x=1, y=2)
p = {x='hi'}
test-data/unit/check-typeddict.test
Outdated
|
||
Point = TypedDict('Point', {'x': int, 'y': int}) | ||
|
||
p1: Point = {'x': 'hi'} # # E: Expected items ['x', 'y'] but found ['x']. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: # # E:
-> # E:
mypy/checkexpr.py
Outdated
@@ -1694,6 +1694,9 @@ def visit_dict_expr(self, e: DictExpr) -> Type: | |||
|
|||
Translate it into a call to dict(), with provisions for **expr. | |||
""" | |||
# if we find a DictExpr inside a context that expected TypedDict, | |||
# we try to convert the dictionary into TypedDict | |||
# w 8000 e warn if they are not compatible or if we don't have enough info to verify |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not what I wanted. I wanted an explanation that we need to silence one of two errors, and why the code below actually silences the second error. Sorry for misunderstanding.
OK, now it LGTM. |
@pkch Thanks! |
Fixes #2487, #2488