|
| 1 | +From 6eafc5e3487866001d0447514e67d3861c13bb7b Mon Sep 17 00:00:00 2001 |
| 2 | +From: Jukka Lehtosalo < [email protected]> |
| 3 | +Date: Mon, 5 Jul 2021 14:52:15 +0100 |
| 4 | +Subject: [PATCH] Fixes to generic builtin types (#10766) |
| 5 | + |
| 6 | +This fixes these issues: |
| 7 | + |
| 8 | +* Allow variable-length tuple (tuple[int, ...]) in type aliases |
| 9 | +* Allow generic built-in types (e.g. list[int]) in stubs in all Python versions |
| 10 | + |
| 11 | +Fixes #9980. Fixes #10303. Fixes #10731. |
| 12 | +--- |
| 13 | + mypy/semanal.py | 11 +++++-- |
| 14 | + mypy/typeanal.py | 3 +- |
| 15 | + test-data/unit/check-generic-alias.test | 43 +++++++++++++++++++++++++ |
| 16 | + 3 files changed, 53 insertions(+), 4 deletions(-) |
| 17 | + |
| 18 | +--- a/mypy/semanal.py |
| 19 | ++++ b/mypy/semanal.py |
| 20 | +@@ -76,7 +76,7 @@ |
| 21 | + get_nongen_builtins, get_member_expr_fullname, REVEAL_TYPE, |
| 22 | + REVEAL_LOCALS, is_final_node, TypedDictExpr, type_aliases_source_versions, |
| 23 | + EnumCallExpr, RUNTIME_PROTOCOL_DECOS, FakeExpression, Statement, AssignmentExpr, |
| 24 | +- ParamSpecExpr |
| 25 | ++ ParamSpecExpr, EllipsisExpr |
| 26 | + ) |
| 27 | + from mypy.tvar_scope import TypeVarLikeScope |
| 28 | + from mypy.typevars import fill_typevars |
| 29 | +@@ -91,7 +91,8 @@ |
| 30 | + FunctionLike, UnboundType, TypeVarDef, TupleType, UnionType, StarType, |
| 31 | + CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue, |
| 32 | + TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, |
| 33 | +- get_proper_type, get_proper_types, TypeAliasType) |
| 34 | ++ get_proper_type, get_proper_types, TypeAliasType |
| 35 | ++) |
| 36 | + from mypy.typeops import function_type |
| 37 | + from mypy.type_visitor import TypeQuery |
| 38 | + from mypy.nodes import implicit_module_attrs |
| 39 | +@@ -3844,7 +3845,8 @@ |
| 40 | + # ...or directly. |
| 41 | + else: |
| 42 | + n = self.lookup_type_node(base) |
| 43 | +- if n and n.fullname in get_nongen_builtins(self.options.python_version): |
| 44 | ++ if (n and n.fullname in get_nongen_builtins(self.options.python_version) and |
| 45 | ++ not self.is_stub_file): |
| 46 | + self.fail(no_subscript_builtin_alias(n.fullname, propose_alt=False), expr) |
| 47 | + |
| 48 | + def analyze_type_application_args(self, expr: IndexExpr) -> Optional[List[Type]]: |
| 49 | +@@ -3860,6 +3862,9 @@ |
| 50 | + types = [] # type: List[Type] |
| 51 | + if isinstance(index, TupleExpr): |
| 52 | + items = index.items |
| 53 | ++ is_tuple = isinstance(expr.base, RefExpr) and expr.base.fullname == 'builtins.tuple' |
| 54 | ++ if is_tuple and len(items) == 2 and isinstance(items[-1], EllipsisExpr): |
| 55 | ++ items = items[:-1] |
| 56 | + else: |
| 57 | + items = [index] |
| 58 | + for item in items: |
| 59 | +--- a/mypy/typeanal.py |
| 60 | ++++ b/mypy/typeanal.py |
| 61 | +@@ -281,7 +281,8 @@ |
| 62 | + return AnyType(TypeOfAny.from_error) |
| 63 | + elif (fullname == 'typing.Tuple' or |
| 64 | + (fullname == 'builtins.tuple' and (self.options.python_version >= (3, 9) or |
| 65 | +- self.api.is_future_flag_set('annotations')))): |
| 66 | ++ self.api.is_future_flag_set('annotations') or |
| 67 | ++ self.allow_unnormalized))): |
| 68 | + # Tuple is special because it is involved in builtin import cycle |
| 69 | + # and may be not ready when used. |
| 70 | + sym = self.api.lookup_fully_qualified_or_none('builtins.tuple') |
| 71 | +--- a/test-data/unit/check-generic-alias.test |
| 72 | ++++ b/test-data/unit/check-generic-alias.test |
| 73 | +@@ -239,3 +239,46 @@ |
| 74 | + from typing import Tuple |
| 75 | + t10: Tuple[int, ...] = t09 |
| 76 | + [builtins fixtures/tuple.pyi] |
| 77 | ++ |
| 78 | ++[case testTypeAliasWithBuiltinTuple] |
| 79 | ++# flags: --python-version 3.9 |
| 80 | ++ |
| 81 | ++A = tuple[int, ...] |
| 82 | ++a: A = () |
| 83 | ++b: A = (1, 2, 3) |
| 84 | ++c: A = ('x', 'y') # E: Incompatible types in assignment (expression has type "Tuple[str, str]", variable has type "Tuple[int, ...]") |
| 85 | ++ |
| 86 | ++B = tuple[int, str] |
| 87 | ++x: B = (1, 'x') |
| 88 | ++y: B = ('x', 1) # E: Incompatible types in assignment (expression has type "Tuple[str, int]", variable has type "Tuple[int, str]") |
| 89 | ++ |
| 90 | ++reveal_type(tuple[int, ...]()) # N: Revealed type is "builtins.tuple[builtins.int*]" |
| 91 | ++[builtins fixtures/tuple.pyi] |
| 92 | ++ |
| 93 | ++[case testTypeAliasWithBuiltinTupleInStub] |
| 94 | ++# flags: --python-version 3.6 |
| 95 | ++import m |
| 96 | ++reveal_type(m.a) # N: Revealed type is "builtins.tuple[builtins.int]" |
| 97 | ++reveal_type(m.b) # N: Revealed type is "Tuple[builtins.int, builtins.str]" |
| 98 | ++ |
| 99 | ++[file m.pyi] |
| 100 | ++A = tuple[int, ...] |
| 101 | ++a: A |
| 102 | ++B = tuple[int, str] |
| 103 | ++b: B |
| 104 | ++[builtins fixtures/tuple.pyi] |
| 105 | ++ |
| 106 | ++[case testTypeAliasWithBuiltinListInStub] |
| 107 | ++# flags: --python-version 3.6 |
| 108 | ++import m |
| 109 | ++reveal_type(m.a) # N: Revealed type is "builtins.list[builtins.int]" |
| 110 | ++reveal_type(m.b) # N: Revealed type is "builtins.list[builtins.list[builtins.int]]" |
| 111 | ++ |
| 112 | ++[file m.pyi] |
| 113 | ++A = list[int] |
| 114 | ++a: A |
| 115 | ++B = list[list[int]] |
| 116 | ++b: B |
| 117 | ++class C(list[int]): |
| 118 | ++ pass |
| 119 | ++[builtins fixtures/list.pyi] |
0 commit comments