@@ -22,6 +22,28 @@ def _make_id(target):
2222NO_RECEIVERS = object ()
2323
2424
25+ async def _gather (* coros ):
26+ if len (coros ) == 0 :
27+ return []
28+
29+ if len (coros ) == 1 :
30+ return [await coros [0 ]]
31+
32+ async def run (i , coro ):
33+ results [i ] = await coro
34+
35+ try :
36+ async with asyncio .TaskGroup () as tg :
37+ results = [None ] * len (coros )
38+ for i , coro in enumerate (coros ):
39+ tg .create_task (run (i , coro ))
40+ return results
41+ except BaseExceptionGroup as exception_group :
42+ if len (exception_group .exceptions ) == 1 :
43+ raise exception_group .exceptions [0 ]
44+ raise
45+
46+
2547class Signal :
2648 """
2749 Base class for all signals
@@ -186,7 +208,7 @@ def send(self, sender, **named):
186208
187209 If any receivers are asynchronous, they are called after all the
188210 synchronous receivers via a single call to async_to_sync(). They are
189- also executed concurrently with asyncio.gather ().
211+ also executed concurrently with asyncio.TaskGroup ().
190212
191213 Arguments:
192214
@@ -211,7 +233,7 @@ def send(self, sender, **named):
211233 if async_receivers :
212234
213235 async def asend ():
214- async_responses = await asyncio . gather (
236+ async_responses = await _gather (
215237 * (
216238 receiver (signal = self , sender = sender , ** named )
217239 for receiver in async_receivers
@@ -235,7 +257,7 @@ async def asend(self, sender, **named):
235257 sync_to_async() adaption before executing any asynchronous receivers.
236258
237259 If any receivers are asynchronous, they are grouped and executed
238- concurrently with asyncio.gather ().
260+ concurrently with asyncio.TaskGroup ().
239261
240262 Arguments:
241263
@@ -268,9 +290,9 @@ def sync_send():
268290 async def sync_send ():
269291 return []
270292
271- responses , async_responses = await asyncio . gather (
293+ responses , async_responses = await _gather (
272294 sync_send (),
273- asyncio . gather (
295+ _gather (
274296 * (
275297 receiver (signal = self , sender = sender , ** named )
276298 for receiver in async_receivers
@@ -294,7 +316,7 @@ def send_robust(self, sender, **named):
294316
295317 If any receivers are asynchronous, they are called after all the
296318 synchronous receivers via a single call to async_to_sync(). They are
297- also executed concurrently with asyncio.gather ().
319+ also executed concurrently with asyncio.TaskGroup ().
298320
299321 Arguments:
300322
@@ -340,7 +362,7 @@ async def asend_and_wrap_exception(receiver):
340362 return response
341363
342364 async def asend ():
343- async_responses = await asyncio . gather (
365+ async_responses = await _gather (
344366 * (
345367 asend_and_wrap_exception (receiver )
346368 for receiver in async_receivers
@@ -359,7 +381,7 @@ async def asend_robust(self, sender, **named):
359381 sync_to_async() adaption before executing any asynchronous receivers.
360382
361383 If any receivers are asynchronous, they are grouped and executed
362- concurrently with asyncio.gather .
384+ concurrently with asyncio.TaskGroup .
363385
364386 Arguments:
365387
@@ -414,9 +436,9 @@ async def asend_and_wrap_exception(receiver):
414436 return err
415437 return response
416438
417- responses , async_responses = await asyncio . gather (
439+ responses , async_responses = await _gather (
418440 sync_send (),
419- asyncio . gather (
441+ _gather (
420442 * (asend_and_wrap_exception (receiver ) for receiver in async_receivers ),
421443 ),
422444 )
0 commit comments