diff options
| author | Thomas Grainger <tagrain@gmail.com> | 2025-04-10 09:43:32 +0100 |
|---|---|---|
| committer | Jacob Walls <jacobtylerwalls@gmail.com> | 2025-11-07 13:17:25 -0500 |
| commit | 27687475265f88bc0a0bcbfe2ba26da306bbfc20 (patch) | |
| tree | 782339a9a58101b25dfd065426016978bcfa08eb /django/dispatch | |
| parent | 2501958b5127020411df6271445ccfd0906df70e (diff) | |
Fixed #36315 -- Used TaskGroup instead of asyncio.gather().
Diffstat (limited to 'django/dispatch')
| -rw-r--r-- | django/dispatch/dispatcher.py | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/django/dispatch/dispatcher.py b/django/dispatch/dispatcher.py index 120f2ac6de..63fb75285e 100644 --- a/django/dispatch/dispatcher.py +++ b/django/dispatch/dispatcher.py @@ -22,6 +22,28 @@ NONE_ID = _make_id(None) NO_RECEIVERS = object() +async def _gather(*coros): + if len(coros) == 0: + return [] + + if len(coros) == 1: + return [await coros[0]] + + async def run(i, coro): + results[i] = await coro + + try: + async with asyncio.TaskGroup() as tg: + results = [None] * len(coros) + for i, coro in enumerate(coros): + tg.create_task(run(i, coro)) + return results + except BaseExceptionGroup as exception_group: + if len(exception_group.exceptions) == 1: + raise exception_group.exceptions[0] + raise + + class Signal: """ Base class for all signals @@ -186,7 +208,7 @@ class Signal: If any receivers are asynchronous, they are called after all the synchronous receivers via a single call to async_to_sync(). They are - also executed concurrently with asyncio.gather(). + also executed concurrently with asyncio.TaskGroup(). Arguments: @@ -211,7 +233,7 @@ class Signal: if async_receivers: async def asend(): - async_responses = await asyncio.gather( + async_responses = await _gather( *( receiver(signal=self, sender=sender, **named) for receiver in async_receivers @@ -235,7 +257,7 @@ class Signal: sync_to_async() adaption before executing any asynchronous receivers. If any receivers are asynchronous, they are grouped and executed - concurrently with asyncio.gather(). + concurrently with asyncio.TaskGroup(). Arguments: @@ -268,9 +290,9 @@ class Signal: async def sync_send(): return [] - responses, async_responses = await asyncio.gather( + responses, async_responses = await _gather( sync_send(), - asyncio.gather( + _gather( *( receiver(signal=self, sender=sender, **named) for receiver in async_receivers @@ -294,7 +316,7 @@ class Signal: If any receivers are asynchronous, they are called after all the synchronous receivers via a single call to async_to_sync(). They are - also executed concurrently with asyncio.gather(). + also executed concurrently with asyncio.TaskGroup(). Arguments: @@ -340,7 +362,7 @@ class Signal: return response async def asend(): - async_responses = await asyncio.gather( + async_responses = await _gather( *( asend_and_wrap_exception(receiver) for receiver in async_receivers @@ -359,7 +381,7 @@ class Signal: sync_to_async() adaption before executing any asynchronous receivers. If any receivers are asynchronous, they are grouped and executed - concurrently with asyncio.gather. + concurrently with asyncio.TaskGroup. Arguments: @@ -414,9 +436,9 @@ class Signal: return err return response - responses, async_responses = await asyncio.gather( + responses, async_responses = await _gather( sync_send(), - asyncio.gather( + _gather( *(asend_and_wrap_exception(receiver) for receiver in async_receivers), ), ) |
