Browse Source

[5.0.x] Fixed #35174 -- Fixed Signal.asend()/asend_robust() crash when all receivers are asynchronous.

Regression in e83a88566a71a2353cebc35992c110be0f8628af.

Backport of 1b5338d03ecc962af8ab4678426bc60b0672b8dd from main
Vašek Dohnal 1 year ago
parent
commit
761e913191
3 changed files with 26 additions and 2 deletions
  1. 6 2
      django/dispatch/dispatcher.py
  2. 4 0
      docs/releases/5.0.3.txt
  3. 16 0
      tests/signals/tests.py

+ 6 - 2
django/dispatch/dispatcher.py

@@ -244,7 +244,9 @@ class Signal:
                 return responses
 
         else:
-            sync_send = list
+
+            async def sync_send():
+                return []
 
         responses, async_responses = await asyncio.gather(
             sync_send(),
@@ -380,7 +382,9 @@ class Signal:
                 return responses
 
         else:
-            sync_send = list
+
+            async def sync_send():
+                return []
 
         async def asend_and_wrap_exception(receiver):
             try:

+ 4 - 0
docs/releases/5.0.3.txt

@@ -11,3 +11,7 @@ Bugfixes
 
 * Fixed a regression in Django 5.0.2 where ``intcomma`` template filter could
   return a leading comma for string representation of floats (:ticket:`35172`).
+
+* Fixed a bug in Django 5.0 that caused a crash of ``Signal.asend()`` and
+  ``asend_robust()`` when all receivers were asynchronous functions
+  (:ticket:`35174`).

+ 16 - 0
tests/signals/tests.py

@@ -626,3 +626,19 @@ class AsyncReceiversTests(SimpleTestCase):
                 (async_handler, 1),
             ],
         )
+
+    async def test_asend_only_async_receivers(self):
+        async_handler = AsyncHandler()
+        signal = dispatch.Signal()
+        signal.connect(async_handler)
+
+        result = await signal.asend(self.__class__)
+        self.assertEqual(result, [(async_handler, 1)])
+
+    async def test_asend_robust_only_async_receivers(self):
+        async_handler = AsyncHandler()
+        signal = dispatch.Signal()
+        signal.connect(async_handler)
+
+        result = await signal.asend_robust(self.__class__)
+        self.assertEqual(result, [(async_handler, 1)])