-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
/
check-typeguard.test
296 lines (261 loc) · 10.2 KB
/
check-typeguard.test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
[case testTypeGuardBasic]
from typing_extensions import TypeGuard
class Point: pass
def is_point(a: object) -> TypeGuard[Point]: pass
def main(a: object) -> None:
if is_point(a):
reveal_type(a) # N: Revealed type is '__main__.Point'
else:
reveal_type(a) # N: Revealed type is 'builtins.object'
[builtins fixtures/tuple.pyi]
[case testTypeGuardTypeArgsNone]
from typing_extensions import TypeGuard
def foo(a: object) -> TypeGuard: # E: TypeGuard must have exactly one type argument
pass
[builtins fixtures/tuple.pyi]
[case testTypeGuardTypeArgsTooMany]
from typing_extensions import TypeGuard
def foo(a: object) -> TypeGuard[int, int]: # E: TypeGuard must have exactly one type argument
pass
[builtins fixtures/tuple.pyi]
[case testTypeGuardTypeArgType]
from typing_extensions import TypeGuard
def foo(a: object) -> TypeGuard[42]: # E: Invalid type: try using Literal[42] instead?
pass
[builtins fixtures/tuple.pyi]
[case testTypeGuardRepr]
from typing_extensions import TypeGuard
def foo(a: object) -> TypeGuard[int]:
pass
reveal_type(foo) # N: Revealed type is 'def (a: builtins.object) -> TypeGuard[builtins.int]'
[builtins fixtures/tuple.pyi]
[case testTypeGuardCallArgsNone]
from typing_extensions import TypeGuard
class Point: pass
# TODO: error on the 'def' line (insufficient args for type guard)
def is_point() -> TypeGuard[Point]: pass
def main(a: object) -> None:
if is_point():
reveal_type(a) # N: Revealed type is 'builtins.object'
[builtins fixtures/tuple.pyi]
[case testTypeGuardCallArgsMultiple]
from typing_extensions import TypeGuard
class Point: pass
def is_point(a: object, b: object) -> TypeGuard[Point]: pass
def main(a: object, b: object) -> None:
if is_point(a, b):
reveal_type(a) # N: Revealed type is '__main__.Point'
reveal_type(b) # N: Revealed type is 'builtins.object'
[builtins fixtures/tuple.pyi]
[case testTypeGuardIsBool]
from typing_extensions import TypeGuard
def f(a: TypeGuard[int]) -> None: pass
reveal_type(f) # N: Revealed type is 'def (a: builtins.bool)'
a: TypeGuard[int]
reveal_type(a) # N: Revealed type is 'builtins.bool'
class C:
a: TypeGuard[int]
reveal_type(C().a) # N: Revealed type is 'builtins.bool'
[builtins fixtures/tuple.pyi]
[case testTypeGuardWithTypeVar]
from typing import TypeVar, Tuple
from typing_extensions import TypeGuard
T = TypeVar('T')
def is_two_element_tuple(a: Tuple[T, ...]) -> TypeGuard[Tuple[T, T]]: pass
def main(a: Tuple[T, ...]):
if is_two_element_tuple(a):
reveal_type(a) # N: Revealed type is 'Tuple[T`-1, T`-1]'
[builtins fixtures/tuple.pyi]
[case testTypeGuardNonOverlapping]
from typing import List
from typing_extensions import TypeGuard
def is_str_list(a: List[object]) -> TypeGuard[List[str]]: pass
def main(a: List[object]):
if is_str_list(a):
reveal_type(a) # N: Revealed type is 'builtins.list[builtins.str]'
[builtins fixtures/tuple.pyi]
[case testTypeGuardUnionIn]
from typing import Union
from typing_extensions import TypeGuard
def is_foo(a: Union[int, str]) -> TypeGuard[str]: pass
def main(a: Union[str, int]) -> None:
if is_foo(a):
reveal_type(a) # N: Revealed type is 'builtins.str'
[builtins fixtures/tuple.pyi]
[case testTypeGuardUnionOut]
from typing import Union
from typing_extensions import TypeGuard
def is_foo(a: object) -> TypeGuard[Union[int, str]]: pass
def main(a: object) -> None:
if is_foo(a):
reveal_type(a) # N: Revealed type is 'Union[builtins.int, builtins.str]'
[builtins fixtures/tuple.pyi]
[case testTypeGuardNonzeroFloat]
from typing_extensions import TypeGuard
def is_nonzero(a: object) -> TypeGuard[float]: pass
def main(a: int):
if is_nonzero(a):
reveal_type(a) # N: Revealed type is 'builtins.float'
[builtins fixtures/tuple.pyi]
[case testTypeGuardHigherOrder]
from typing import Callable, TypeVar, Iterable, List
from typing_extensions import TypeGuard
T = TypeVar('T')
R = TypeVar('R')
def filter(f: Callable[[T], TypeGuard[R]], it: Iterable[T]) -> Iterable[R]: pass
def is_float(a: object) -> TypeGuard[float]: pass
a: List[object] = ["a", 0, 0.0]
b = filter(is_float, a)
reveal_type(b) # N: Revealed type is 'typing.Iterable[builtins.float*]'
[builtins fixtures/tuple.pyi]
[case testTypeGuardMethod]
from typing_extensions import TypeGuard
class C:
def main(self, a: object) -> None:
if self.is_float(a):
reveal_type(self) # N: Revealed type is '__main__.C'
reveal_type(a) # N: Revealed type is 'builtins.float'
def is_float(self, a: object) -> TypeGuard[float]: pass
[builtins fixtures/tuple.pyi]
[case testTypeGuardCrossModule]
import guard
from points import Point
def main(a: object) -> None:
if guard.is_point(a):
reveal_type(a) # N: Revealed type is 'points.Point'
[file guard.py]
from typing_extensions import TypeGuard
import points
def is_point(a: object) -> TypeGuard[points.Point]: pass
[file points.py]
class Point: pass
[builtins fixtures/tuple.pyi]
[case testTypeGuardBodyRequiresBool]
from typing_extensions import TypeGuard
def is_float(a: object) -> TypeGuard[float]:
return "not a bool" # E: Incompatible return value type (got "str", expected "bool")
[builtins fixtures/tuple.pyi]
[case testTypeGuardNarrowToTypedDict]
from typing import Dict, TypedDict
from typing_extensions import TypeGuard
class User(TypedDict):
name: str
id: int
def is_user(a: Dict[str, object]) -> TypeGuard[User]:
return isinstance(a.get("name"), str) and isinstance(a.get("id"), int)
def main(a: Dict[str, object]) -> None:
if is_user(a):
reveal_type(a) # N: Revealed type is 'TypedDict('__main__.User', {'name': builtins.str, 'id': builtins.int})'
[builtins fixtures/dict.pyi]
[typing fixtures/typing-typeddict.pyi]
[case testTypeGuardInAssert]
from typing_extensions import TypeGuard
def is_float(a: object) -> TypeGuard[float]: pass
def main(a: object) -> None:
assert is_float(a)
reveal_type(a) # N: Revealed type is 'builtins.float'
[builtins fixtures/tuple.pyi]
[case testTypeGuardFromAny]
from typing import Any
from typing_extensions import TypeGuard
def is_objfloat(a: object) -> TypeGuard[float]: pass
def is_anyfloat(a: Any) -> TypeGuard[float]: pass
def objmain(a: object) -> None:
if is_objfloat(a):
reveal_type(a) # N: Revealed type is 'builtins.float'
if is_anyfloat(a):
reveal_type(a) # N: Revealed type is 'builtins.float'
def anymain(a: Any) -> None:
if is_objfloat(a):
reveal_type(a) # N: Revealed type is 'builtins.float'
if is_anyfloat(a):
reveal_type(a) # N: Revealed type is 'builtins.float'
[builtins fixtures/tuple.pyi]
[case testTypeGuardNegatedAndElse]
from typing import Union
from typing_extensions import TypeGuard
def is_int(a: object) -> TypeGuard[int]: pass
def is_str(a: object) -> TypeGuard[str]: pass
def intmain(a: Union[int, str]) -> None:
if not is_int(a):
reveal_type(a) # N: Revealed type is 'Union[builtins.int, builtins.str]'
else:
reveal_type(a) # N: Revealed type is 'builtins.int'
def strmain(a: Union[int, str]) -> None:
if is_str(a):
reveal_type(a) # N: Revealed type is 'builtins.str'
else:
reveal_type(a) # N: Revealed type is 'Union[builtins.int, builtins.str]'
[builtins fixtures/tuple.pyi]
[case testTypeGuardClassMethod]
from typing_extensions import TypeGuard
class C:
@classmethod
def is_float(cls, a: object) -> TypeGuard[float]: pass
def method(self, a: object) -> None:
if self.is_float(a):
reveal_type(a) # N: Revealed type is 'builtins.float'
def main(a: object) -> None:
if C.is_float(a):
reveal_type(a) # N: Revealed type is 'builtins.float'
[builtins fixtures/classmethod.pyi]
[case testTypeGuardRequiresPositionalArgs]
from typing_extensions import TypeGuard
def is_float(a: object, b: object = 0) -> TypeGuard[float]: pass
def main1(a: object) -> None:
# This is debatable -- should we support these cases?
if is_float(a=a, b=1): # E: Type guard requires positional argument
reveal_type(a) # N: Revealed type is 'builtins.object'
if is_float(b=1, a=a): # E: Type guard requires positional argument
reveal_type(a) # N: Revealed type is 'builtins.object'
ta = (a,)
if is_float(*ta): # E: Type guard requires positional argument
reveal_type(ta) # N: Revealed type is 'Tuple[builtins.object]'
reveal_type(a) # N: Revealed type is 'builtins.object'
la = [a]
if is_float(*la): # E: Type guard requires positional argument
reveal_type(la) # N: Revealed type is 'builtins.list[builtins.object*]'
reveal_type(a) # N: Revealed type is 'builtins.object*'
[builtins fixtures/tuple.pyi]
[case testTypeGuardOverload-skip]
# flags: --strict-optional
from typing import overload, Any, Callable, Iterable, Iterator, List, Optional, TypeVar
from typing_extensions import TypeGuard
T = TypeVar("T")
R = TypeVar("R")
@overload
def filter(f: Callable[[T], TypeGuard[R]], it: Iterable[T]) -> Iterator[R]: ...
@overload
def filter(f: Callable[[T], bool], it: Iterable[T]) -> Iterator[T]: ...
def filter(*args): pass
def is_int_typeguard(a: object) -> TypeGuard[int]: pass
def is_int_bool(a: object) -> bool: pass
def main(a: List[Optional[int]]) -> None:
bb = filter(lambda x: x is not None, a)
reveal_type(bb) # N: Revealed type is 'typing.Iterator[Union[builtins.int, None]]'
# Also, if you replace 'bool' with 'Any' in the second overload, bb is Iterator[Any]
cc = filter(is_int_typeguard, a)
reveal_type(cc) # N: Revealed type is 'typing.Iterator[builtins.int*]'
dd = filter(is_int_bool, a)
reveal_type(dd) # N: Revealed type is 'typing.Iterator[Union[builtins.int, None]]'
[builtins fixtures/tuple.pyi]
[typing fixtures/typing-full.pyi]
[case testTypeGuardDecorated]
from typing import TypeVar
from typing_extensions import TypeGuard
T = TypeVar("T")
def decorator(f: T) -> T: pass
@decorator
def is_float(a: object) -> TypeGuard[float]:
pass
def main(a: object) -> None:
if is_float(a):
reveal_type(a) # N: Revealed type is 'builtins.float'
[builtins fixtures/tuple.pyi]
[case testTypeGuardMethodOverride-skip]
from typing_extensions import TypeGuard
class C:
def is_float(self, a: object) -> TypeGuard[float]: pass
class D(C):
def is_float(self, a: object) -> bool: pass # E: Some error
[builtins fixtures/tuple.pyi]