|
20 | 20 | ARG_STAR2, |
21 | 21 | EXCLUDED_ENUM_ATTRIBUTES, |
22 | 22 | SYMBOL_FUNCBASE_TYPES, |
| 23 | + ArgKind, |
23 | 24 | Context, |
24 | 25 | Decorator, |
25 | 26 | FuncBase, |
@@ -1148,8 +1149,16 @@ def analyze_class_attribute_access( |
1148 | 1149 | ) |
1149 | 1150 | return AnyType(TypeOfAny.from_error) |
1150 | 1151 |
|
| 1152 | + # TODO: some logic below duplicates analyze_ref_expr in checkexpr.py |
1151 | 1153 | if isinstance(node.node, TypeInfo): |
1152 | | - return type_object_type(node.node, mx.named_type) |
| 1154 | + if node.node.typeddict_type: |
| 1155 | + # We special-case TypedDict, because they don't define any constructor. |
| 1156 | + return typeddict_callable(node.node, mx.named_type) |
| 1157 | + elif node.node.fullname == "types.NoneType": |
| 1158 | + # We special case NoneType, because its stub definition is not related to None. |
| 1159 | + return TypeType(NoneType()) |
| 1160 | + else: |
| 1161 | + return type_object_type(node.node, mx.named_type) |
1153 | 1162 |
|
1154 | 1163 | if isinstance(node.node, MypyFile): |
1155 | 1164 | # Reference to a module object. |
@@ -1330,6 +1339,31 @@ class B(A[str]): pass |
1330 | 1339 | return t |
1331 | 1340 |
|
1332 | 1341 |
|
| 1342 | +def typeddict_callable(info: TypeInfo, named_type: Callable[[str], Instance]) -> CallableType: |
| 1343 | + """Construct a reasonable type for a TypedDict type in runtime context. |
| 1344 | +
|
| 1345 | + If it appears as a callee, it will be special-cased anyway, e.g. it is |
| 1346 | + also allowed to accept a single positional argument if it is a dict literal. |
| 1347 | +
|
| 1348 | + Note it is not safe to move this to type_object_type() since it will crash |
| 1349 | + on plugin-generated TypedDicts, that may not have the special_alias. |
| 1350 | + """ |
| 1351 | + assert info.special_alias is not None |
| 1352 | + target = info.special_alias.target |
| 1353 | + assert isinstance(target, ProperType) and isinstance(target, TypedDictType) |
| 1354 | + expected_types = list(target.items.values()) |
| 1355 | + kinds = [ArgKind.ARG_NAMED] * len(expected_types) |
| 1356 | + names = list(target.items.keys()) |
| 1357 | + return CallableType( |
| 1358 | + expected_types, |
| 1359 | + kinds, |
| 1360 | + names, |
| 1361 | + target, |
| 1362 | + named_type("builtins.type"), |
| 1363 | + variables=info.defn.type_vars, |
| 1364 | + ) |
| 1365 | + |
| 1366 | + |
1333 | 1367 | def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> ProperType: |
1334 | 1368 | """Return the type of a type object. |
1335 | 1369 |
|
|
0 commit comments