Skip to content

Commit 25eb99c

Browse files
authored
Add better types for asyncio.gather (#9678)
1 parent c30c85d commit 25eb99c

File tree

2 files changed

+73
-11
lines changed

2 files changed

+73
-11
lines changed

stdlib/asyncio/tasks.pyi

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ _T2 = TypeVar("_T2")
6868
_T3 = TypeVar("_T3")
6969
_T4 = TypeVar("_T4")
7070
_T5 = TypeVar("_T5")
71+
_T6 = TypeVar("_T6")
7172
_FT = TypeVar("_FT", bound=Future[Any])
7273
_FutureLike: TypeAlias = Future[_T] | Generator[Any, None, _T] | Awaitable[_T]
7374
_TaskYieldType: TypeAlias = Future[object] | None
@@ -131,6 +132,19 @@ if sys.version_info >= (3, 10):
131132
return_exceptions: Literal[False] = False,
132133
) -> Future[tuple[_T1, _T2, _T3, _T4, _T5]]: ...
133134
@overload
135+
def gather( # type: ignore[misc]
136+
__coro_or_future1: _FutureLike[_T1],
137+
__coro_or_future2: _FutureLike[_T2],
138+
__coro_or_future3: _FutureLike[_T3],
139+
__coro_or_future4: _FutureLike[_T4],
140+
__coro_or_future5: _FutureLike[_T5],
141+
__coro_or_future6: _FutureLike[_T6],
142+
*,
143+
return_exceptions: Literal[False] = False,
144+
) -> Future[tuple[_T1, _T2, _T3, _T4, _T5, _T6]]: ...
145+
@overload
146+
def gather(*coros_or_futures: _FutureLike[_T], return_exceptions: Literal[False] = False) -> Future[list[_T]]: ... # type: ignore[misc]
147+
@overload
134148
def gather(__coro_or_future1: _FutureLike[_T1], *, return_exceptions: bool) -> Future[tuple[_T1 | BaseException]]: ... # type: ignore[misc]
135149
@overload
136150
def gather( # type: ignore[misc]
@@ -166,7 +180,27 @@ if sys.version_info >= (3, 10):
166180
tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException, _T4 | BaseException, _T5 | BaseException]
167181
]: ...
168182
@overload
169-
def gather(*coros_or_futures: _FutureLike[Any], return_exceptions: bool = False) -> Future[list[Any]]: ...
183+
def gather( # type: ignore[misc]
184+
__coro_or_future1: _FutureLike[_T1],
185+
__coro_or_future2: _FutureLike[_T2],
186+
__coro_or_future3: _FutureLike[_T3],
187+
__coro_or_future4: _FutureLike[_T4],
188+
__coro_or_future5: _FutureLike[_T5],
189+
__coro_or_future6: _FutureLike[_T6],
190+
*,
191+
return_exceptions: bool,
192+
) -> Future[
193+
tuple[
194+
_T1 | BaseException,
195+
_T2 | BaseException,
196+
_T3 | BaseException,
197+
_T4 | BaseException,
198+
_T5 | BaseException,
199+
_T6 | BaseException,
200+
]
201+
]: ...
202+
@overload
203+
def gather(*coros_or_futures: _FutureLike[_T], return_exceptions: bool) -> Future[list[_T | BaseException]]: ...
170204

171205
else:
172206
@overload
@@ -212,6 +246,22 @@ else:
212246
return_exceptions: Literal[False] = False,
213247
) -> Future[tuple[_T1, _T2, _T3, _T4, _T5]]: ...
214248
@overload
249+
def gather( # type: ignore[misc]
250+
__coro_or_future1: _FutureLike[_T1],
251+
__coro_or_future2: _FutureLike[_T2],
252+
__coro_or_future3: _FutureLike[_T3],
253+
__coro_or_future4: _FutureLike[_T4],
254+
__coro_or_future5: _FutureLike[_T5],
255+
__coro_or_future6: _FutureLike[_T6],
256+
*,
257+
loop: AbstractEventLoop | None = None,
258+
return_exceptions: Literal[False] = False,
259+
) -> Future[tuple[_T1, _T2, _T3, _T4, _T5, _T6]]: ...
260+
@overload
261+
def gather( # type: ignore[misc]
262+
*coros_or_futures: _FutureLike[_T], loop: AbstractEventLoop | None = None, return_exceptions: Literal[False] = False
263+
) -> Future[list[_T]]: ...
264+
@overload
215265
def gather( # type: ignore[misc]
216266
__coro_or_future1: _FutureLike[_T1], *, loop: AbstractEventLoop | None = None, return_exceptions: bool
217267
) -> Future[tuple[_T1 | BaseException]]: ...
@@ -249,16 +299,24 @@ else:
249299
__coro_or_future3: _FutureLike[_T3],
250300
__coro_or_future4: _FutureLike[_T4],
251301
__coro_or_future5: _FutureLike[_T5],
302+
__coro_or_future6: _FutureLike[_T6],
252303
*,
253304
loop: AbstractEventLoop | None = None,
254305
return_exceptions: bool,
255306
) -> Future[
256-
tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException, _T4 | BaseException, _T5 | BaseException]
307+
tuple[
308+
_T1 | BaseException,
309+
_T2 | BaseException,
310+
_T3 | BaseException,
311+
_T4 | BaseException,
312+
_T5 | BaseException,
313+
_T6 | BaseException,
314+
]
257315
]: ...
258316
@overload
259-
def gather(
260-
*coros_or_futures: _FutureLike[Any], loop: AbstractEventLoop | None = None, return_exceptions: bool = False
261-
) -> Future[list[Any]]: ...
317+
def gather( # type: ignore[misc]
318+
*coros_or_futures: _FutureLike[_T], loop: AbstractEventLoop | None = None, return_exceptions: bool
319+
) -> Future[list[_T | BaseException]]: ...
262320

263321
def run_coroutine_threadsafe(coro: _FutureLike[_T], loop: AbstractEventLoop) -> concurrent.futures.Future[_T]: ...
264322

test_cases/stdlib/asyncio/check_gather.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
import asyncio
4-
from typing import Any, Awaitable, List, Tuple, Union
4+
from typing import Awaitable, List, Tuple, Union
55
from typing_extensions import assert_type
66

77

@@ -21,14 +21,18 @@ async def test_gather(awaitable1: Awaitable[int], awaitable2: Awaitable[str]) ->
2121
assert_type(b, Tuple[Union[int, BaseException], Union[str, BaseException]])
2222

2323
c = await asyncio.gather(awaitable1, awaitable2, awaitable1, awaitable1, awaitable1, awaitable1)
24-
assert_type(c, List[Any])
24+
assert_type(c, Tuple[int, str, int, int, int, int])
25+
26+
d = await asyncio.gather(awaitable1, awaitable1, awaitable1, awaitable1, awaitable1, awaitable1, awaitable1)
27+
assert_type(d, List[int])
2528

2629
awaitables_list: list[Awaitable[int]] = [awaitable1]
27-
d = await asyncio.gather(*awaitables_list)
28-
assert_type(d, List[Any])
30+
e = await asyncio.gather(*awaitables_list)
31+
assert_type(e, List[int])
2932

30-
e = await asyncio.gather()
31-
assert_type(e, List[Any])
33+
# this case isn't reliable between typecheckers, no one would ever call it with no args anyway
34+
# f = await asyncio.gather()
35+
# assert_type(f, list[Any])
3236

3337

3438
asyncio.run(test_gather(coro1(), coro2()))

0 commit comments

Comments
 (0)