summaryrefslogtreecommitdiff
path: root/tests/signals
diff options
context:
space:
mode:
authorJon Janzen <jon@jonjanzen.com>2020-11-07 13:19:20 +0300
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-03-07 08:39:25 +0100
commite83a88566a71a2353cebc35992c110be0f8628af (patch)
tree466c863fc3bfe6fc9946b5a3f7163c62e58ecbb9 /tests/signals
parent9a07999aef7958c9b5441e368cd90646d0edc5c9 (diff)
downloaddjango-e83a88566a71a2353cebc35992c110be0f8628af.tar.gz
Fixed #32172 -- Adapted signals to allow async handlers.
co-authored-by: kozzztik <kozzztik@mail.ru> co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
Diffstat (limited to 'tests/signals')
-rw-r--r--tests/signals/tests.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/tests/signals/tests.py b/tests/signals/tests.py
index 0385033b07..0f161eeeb1 100644
--- a/tests/signals/tests.py
+++ b/tests/signals/tests.py
@@ -1,5 +1,7 @@
+import asyncio
from unittest import mock
+from django import dispatch
from django.apps.registry import Apps
from django.db import models
from django.db.models import signals
@@ -530,3 +532,94 @@ class LazyModelRefTests(BaseSignalSetup, SimpleTestCase):
apps2 = Apps()
signals.post_init.connect(self.receiver, sender=Book, apps=apps2)
self.assertEqual(list(apps2._pending_operations), [])
+
+
+class SyncHandler:
+ param = 0
+
+ def __call__(self, **kwargs):
+ self.param += 1
+ return self.param
+
+
+class AsyncHandler:
+ _is_coroutine = asyncio.coroutines._is_coroutine
+ param = 0
+
+ async def __call__(self, **kwargs):
+ self.param += 1
+ return self.param
+
+
+class AsyncReceiversTests(SimpleTestCase):
+ async def test_asend(self):
+ sync_handler = SyncHandler()
+ async_handler = AsyncHandler()
+ signal = dispatch.Signal()
+ signal.connect(sync_handler)
+ signal.connect(async_handler)
+ result = await signal.asend(self.__class__)
+ self.assertEqual(result, [(sync_handler, 1), (async_handler, 1)])
+
+ def test_send(self):
+ sync_handler = SyncHandler()
+ async_handler = AsyncHandler()
+ signal = dispatch.Signal()
+ signal.connect(sync_handler)
+ signal.connect(async_handler)
+ result = signal.send(self.__class__)
+ self.assertEqual(result, [(sync_handler, 1), (async_handler, 1)])
+
+ def test_send_robust(self):
+ class ReceiverException(Exception):
+ pass
+
+ receiver_exception = ReceiverException()
+
+ async def failing_async_handler(**kwargs):
+ raise receiver_exception
+
+ sync_handler = SyncHandler()
+ async_handler = AsyncHandler()
+ signal = dispatch.Signal()
+ signal.connect(failing_async_handler)
+ signal.connect(async_handler)
+ signal.connect(sync_handler)
+ result = signal.send_robust(self.__class__)
+ # The ordering here is different than the order that signals were
+ # connected in.
+ self.assertEqual(
+ result,
+ [
+ (sync_handler, 1),
+ (failing_async_handler, receiver_exception),
+ (async_handler, 1),
+ ],
+ )
+
+ async def test_asend_robust(self):
+ class ReceiverException(Exception):
+ pass
+
+ receiver_exception = ReceiverException()
+
+ async def failing_async_handler(**kwargs):
+ raise receiver_exception
+
+ sync_handler = SyncHandler()
+ async_handler = AsyncHandler()
+ signal = dispatch.Signal()
+ signal.connect(failing_async_handler)
+ signal.connect(async_handler)
+ signal.connect(sync_handler)
+ result = await signal.asend_robust(self.__class__)
+ # The ordering here is different than the order that signals were
+ # connected in.
+ self.assertEqual(
+ result,
+ [
+ (sync_handler, 1),
+ (failing_async_handler, receiver_exception),
+ (async_handler, 1),
+ ],
+ )