1
1
"""
2
- Tests TypeIs functionality.
2
+ Tests TypeIs functionality, including async support .
3
3
"""
4
4
5
5
# Specification: https://typing.readthedocs.io/en/latest/spec/narrowing.html#typeis
@@ -20,7 +20,6 @@ def func1(names: tuple[str, ...]):
20
20
else :
21
21
assert_type (names , tuple [str , ...])
22
22
23
-
24
23
# > The final narrowed type may be narrower than **R**, due to the constraints of the
25
24
# > argument's previously-known type
26
25
@@ -37,7 +36,6 @@ async def func2(val: int | Awaitable[int]):
37
36
else :
38
37
assert_type (val , int )
39
38
40
-
41
39
T_A = TypeVar ("T_A" , bound = "A" )
42
40
43
41
class A :
@@ -65,7 +63,6 @@ class B(A):
65
63
# > passed to the function. The function may accept additional arguments,
66
64
# > but they are not affected by type narrowing.
67
65
68
-
69
66
def func3 () -> None :
70
67
val1 = object ()
71
68
if A ().tg_1 (val1 ):
@@ -95,7 +92,6 @@ def func3() -> None:
95
92
if B ().tg4 (val7 ):
96
93
assert_type (val7 , B )
97
94
98
-
99
95
# > If a type narrowing function
100
96
# > is implemented as an instance method or class method, the first positional
101
97
# > argument maps to the second parameter (after self or cls).
@@ -115,39 +111,30 @@ def tg_2(cls) -> TypeIs[int]: # E
115
111
# > contexts, it is treated as a subtype of bool. For example, ``Callable[..., TypeIs[int]]``
116
112
# > is assignable to ``Callable[..., bool]``.
117
113
118
-
119
114
def takes_callable_bool (f : Callable [[object ], bool ]) -> None :
120
115
pass
121
116
122
-
123
117
def takes_callable_str (f : Callable [[object ], str ]) -> None :
124
118
pass
125
119
126
-
127
120
def simple_typeguard (val : object ) -> TypeIs [int ]:
128
121
return isinstance (val , int )
129
122
130
-
131
123
takes_callable_bool (simple_typeguard ) # OK
132
124
takes_callable_str (simple_typeguard ) # E
133
125
134
-
135
126
class CallableBoolProto (Protocol ):
136
127
def __call__ (self , val : object ) -> bool : ...
137
128
138
-
139
129
class CallableStrProto (Protocol ):
140
130
def __call__ (self , val : object ) -> str : ...
141
131
142
-
143
132
def takes_callable_bool_proto (f : CallableBoolProto ) -> None :
144
133
pass
145
134
146
-
147
135
def takes_callable_str_proto (f : CallableStrProto ) -> None :
148
136
pass
149
137
150
-
151
138
takes_callable_bool_proto (simple_typeguard ) # OK
152
139
takes_callable_str_proto (simple_typeguard ) # E
153
140
@@ -170,23 +157,19 @@ def is_int_typeguard(val: object) -> TypeGuard[int]:
170
157
takes_typeis (is_int_typeguard ) # E
171
158
takes_typeis (is_int_typeis ) # OK
172
159
173
-
174
160
# > Unlike ``TypeGuard``, ``TypeIs`` is invariant in its argument type:
175
161
# > ``TypeIs[B]`` is not a subtype of ``TypeIs[A]``,
176
162
# > even if ``B`` is a subtype of ``A``.
177
163
178
164
def takes_int_typeis (f : Callable [[object ], TypeIs [int ]]) -> None :
179
165
pass
180
166
181
-
182
167
def int_typeis (val : object ) -> TypeIs [int ]:
183
168
return isinstance (val , int )
184
169
185
-
186
170
def bool_typeis (val : object ) -> TypeIs [bool ]:
187
171
return isinstance (val , bool )
188
172
189
-
190
173
takes_int_typeis (int_typeis ) # OK
191
174
takes_int_typeis (bool_typeis ) # E
192
175
@@ -195,6 +178,18 @@ def bool_typeis(val: object) -> TypeIs[bool]:
195
178
def bad_typeis (x : int ) -> TypeIs [str ]: # E
196
179
return isinstance (x , str )
197
180
198
-
199
181
def bad_typeis_variance (x : list [object ]) -> TypeIs [list [int ]]: # E
200
182
return all (isinstance (x , int ) for x in x )
183
+
184
+ # -------------------- ASYNC TYPEIS SUPPORT --------------------
185
+
186
+ async def async_typeis_test (val : object ) -> TypeIs [int ]:
187
+ return isinstance (val , int )
188
+
189
+ async def test_async_typeis ():
190
+ val : int | str = 10
191
+ if await async_typeis_test (val ): # Ensure narrowing works here
192
+ assert_type (val , int )
193
+ else :
194
+ assert_type (val , str )
195
+
0 commit comments