Skip to content

Commit

Permalink
Fix crash on unimported Any in TypedDict (#16510)
Browse files Browse the repository at this point in the history
Fixes #16498

Fix is trivial: no operations can be done with `Required` types before
unwrapping (because they are not real types).

---------

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
  • Loading branch information
ilevkivskyi and JelleZijlstra committed Nov 17, 2023
1 parent b425bd6 commit 8c8aa10
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
20 changes: 11 additions & 9 deletions mypy/semanal_typeddict.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,17 @@ def check_typeddict(
types = [ # unwrap Required[T] to just T
t.item if isinstance(t, RequiredType) else t for t in types
]

# Perform various validations after unwrapping.
for t in types:
check_for_explicit_any(
t, self.options, self.api.is_typeshed_stub_file, self.msg, context=call
)
if self.options.disallow_any_unimported:
for t in types:
if has_any_from_unimported_type(t):
self.msg.unimported_type_becomes_any("Type of a TypedDict key", t, call)

existing_info = None
if isinstance(node.analyzed, TypedDictExpr):
existing_info = node.analyzed.info
Expand Down Expand Up @@ -451,15 +462,6 @@ def parse_typeddict_args(
# One of the types is not ready, defer.
return None
items, types, ok = res
for t in types:
check_for_explicit_any(
t, self.options, self.api.is_typeshed_stub_file, self.msg, context=call
)

if self.options.disallow_any_unimported:
for t in types:
if has_any_from_unimported_type(t):
self.msg.unimported_type_becomes_any("Type of a TypedDict key", t, dictexpr)
assert total is not None
return args[0].value, items, types, total, tvar_defs, ok

Expand Down
12 changes: 12 additions & 0 deletions test-data/unit/check-typeddict.test
Original file line number Diff line number Diff line change
Expand Up @@ -3396,3 +3396,15 @@ reveal_type(b["a"]) # N: Revealed type is "Union[builtins.str, None]"
reveal_type(b["g"]) # N: Revealed type is "Union[builtins.int, None]"
[builtins fixtures/dict.pyi]
[typing fixtures/typing-typeddict.pyi]

[case testNoCrashOnUnImportedAnyNotRequired]
# flags: --disallow-any-unimported
from typing import NotRequired, Required, TypedDict
from thismoduledoesntexist import T # type: ignore[import]

B = TypedDict("B", { # E: Type of a TypedDict key becomes "Any" due to an unfollowed import
"T1": NotRequired[T],
"T2": Required[T],
})
[builtins fixtures/dict.pyi]
[typing fixtures/typing-typeddict.pyi]

0 comments on commit 8c8aa10

Please sign in to comment.