summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorpgjones <philip.graham.jones@googlemail.com>2022-07-23 11:56:12 +0100
committerPhil Jones <philip.graham.jones@googlemail.com>2023-01-24 20:19:57 +0000
commit5ed9c956aaf68a8e2defa9722109aa2c7bcf7ae1 (patch)
treef103622c530a5a4fa121319e4b35d040ebcf80dc /docs
parent0d4ca6e72c155e30aedd4315e8678ee9cada32b4 (diff)
downloadblinker-5ed9c956aaf68a8e2defa9722109aa2c7bcf7ae1.tar.gz
Add a send_async method to the Signal
This allows for signals to send to coroutine receivers by awaiting them. The _async_wrapper and _sync_wrapper allows for conversion of sync and async receivers as required if defined. If not defined a runtime error is raised. The wrappers are used to avoid any direct tie into asyncio, trio, greenbacks, asgiref, or other specific async implementation.
Diffstat (limited to 'docs')
-rw-r--r--docs/index.rst63
1 files changed, 63 insertions, 0 deletions
diff --git a/docs/index.rst b/docs/index.rst
index 9c733bb..c2f111a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -272,6 +272,69 @@ See the documentation of the :obj:`receiver_connected` built-in signal
for an example.
+Async receivers
+---------------
+
+Receivers can be coroutine functions which can be called and awaited
+via the :meth:`~Signal.send_async` method:
+
+.. code-block:: python
+
+ sig = blinker.Signal()
+
+ async def receiver():
+ ...
+
+ sig.connect(receiver)
+ await sig.send_async()
+
+This however requires that all receivers are awaitable which then
+precludes the usage of :meth:`~Signal.send`. To mix and match the
+:meth:`~Signal.send_async` method takes a ``_sync_wrapper`` argument
+such as:
+
+.. code-block:: python
+
+ sig = blinker.Signal()
+
+ def receiver():
+ ...
+
+ sig.connect(receiver)
+
+ def wrapper(func):
+
+ async def inner(*args, **kwargs):
+ func(*args, **kwargs)
+
+ return inner
+
+ await sig.send_async(_sync_wrapper=wrapper)
+
+The equivalent usage for :meth:`~Signal.send` is via the
+``_async_wrapper`` argument. This usage is will depend on your event
+loop, and in the simple case whereby you aren't running within an
+event loop the following example can be used:
+
+.. code-block:: python
+
+ sig = blinker.Signal()
+
+ async def receiver():
+ ...
+
+ sig.connect(receiver)
+
+ def wrapper(func):
+
+ def inner(*args, **kwargs):
+ asyncio.run(func(*args, **kwargs))
+
+ return inner
+
+ await sig.send(_async_wrapper=wrapper)
+
+
API Documentation
-----------------