diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 78b4c4dcfdd..a741bd338e3 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -558,21 +558,33 @@ def gather(*coros_or_futures, loop=None, return_exceptions=False): prevent the cancellation of one child to cause other children to be cancelled.) """ - arg_to_fut = {arg: async(arg, loop=loop) for arg in set(coros_or_futures)} - children = [arg_to_fut[arg] for arg in coros_or_futures] - n = len(children) - if n == 0: + if not coros_or_futures: outer = futures.Future(loop=loop) outer.set_result([]) return outer - if loop is None: - loop = children[0]._loop - for fut in children: - if fut._loop is not loop: - raise ValueError("futures are tied to different event loops") + + arg_to_fut = {} + for arg in set(coros_or_futures): + if not isinstance(arg, futures.Future): + fut = async(arg, loop=loop) + if loop is None: + loop = fut._loop + # The caller cannot control this future, the "destroy pending task" + # warning should not be emitted. + fut._log_destroy_pending = False + else: + fut = arg + if loop is None: + loop = fut._loop + elif fut._loop is not loop: + raise ValueError("futures are tied to different event loops") + arg_to_fut[arg] = fut + + children = [arg_to_fut[arg] for arg in coros_or_futures] + nchildren = len(children) outer = _GatheringFuture(children, loop=loop) nfinished = 0 - results = [None] * n + results = [None] * nchildren def _done_callback(i, fut): nonlocal nfinished @@ -595,7 +607,7 @@ def gather(*coros_or_futures, loop=None, return_exceptions=False): res = fut._result results[i] = res nfinished += 1 - if nfinished == n: + if nfinished == nchildren: outer.set_result(results) for i, fut in enumerate(children):