From f4c1037f3c361b5fa904d3acec7c74f4172c9b30 Mon Sep 17 00:00:00 2001 From: jason kirtland Date: Mon, 22 Aug 2016 14:53:57 -0700 Subject: Exploratory commit for feedback, adds an async adapter, "send_robust" adapter, and positional call signature adapter. --- blinker/_async.py | 24 ++++++++++++++++++++++++ blinker/playground.py | 20 ++++++++++++++++++++ tests/test_async.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 blinker/_async.py create mode 100644 blinker/playground.py create mode 100644 tests/test_async.py diff --git a/blinker/_async.py b/blinker/_async.py new file mode 100644 index 0000000..3bf87d3 --- /dev/null +++ b/blinker/_async.py @@ -0,0 +1,24 @@ +import asyncio + +from blinker.base import Signal + + +try: + schedule = asyncio.ensure_future +except AttributeError: + schedule = asyncio.async + + +@asyncio.coroutine +def _wrap_plain_value(value): + """Pass through a coroutine *value* or wrap a plain value.""" + if asyncio.iscoroutine(value): + value = yield from value + return value + + +def send_async(scheduler=schedule): + def adapter(receiver, sender, kwargs): + result = receiver(sender, **kwargs) + return scheduler(_wrap_plain_value(result)) + return adapter diff --git a/blinker/playground.py b/blinker/playground.py new file mode 100644 index 0000000..8ed30fb --- /dev/null +++ b/blinker/playground.py @@ -0,0 +1,20 @@ +import blinker + + +def quash_exceptions(fn, sender, kwargs): + """Always call all receivers, collecting values or exceptions.""" + try: + return fn(sender, **kwargs), None + except Exception as exc: + return None, exc + + +def _adapt_xyz(fn, sender, kwargs): + return fn(sender, kwargs['x'], kwargs['y'], kwargs['z']) + +class PositionalSignal(blinker.Signal): + """Positional send and receive (x, y, z)""" + receiver_adapter = staticmethod(_adapt_xyz) + + def send(self, sender, x, y, z): + return blinker.Signal.send(self, sender, x=x, y=y, z=z) diff --git a/tests/test_async.py b/tests/test_async.py new file mode 100644 index 0000000..fc01838 --- /dev/null +++ b/tests/test_async.py @@ -0,0 +1,44 @@ +import asyncio + +import blinker +from blinker._async import send_async + + +def test_send_async(): + calls = [] + + @asyncio.coroutine + def receiver_a(sender): + calls.append(receiver_a) + return 'value a' + + @asyncio.coroutine + def receiver_b(sender): + calls.append(receiver_b) + return 'value b' + + def receiver_c(sender): + calls.append(receiver_c) + return 'value c' + + sig = blinker.Signal(None, send_async()) + sig.connect(receiver_a) + sig.connect(receiver_b) + sig.connect(receiver_c) + + @asyncio.coroutine + def collect(): + return sig.send() + + loop = asyncio.get_event_loop() + results = loop.run_until_complete(collect()) + + expected = { + receiver_a: 'value a', + receiver_b: 'value b', + receiver_c: 'value c', + } + + assert set(calls) == set(expected.keys()) + collected_results = {v.result() for r, v in results} + assert collected_results == set(expected.values()) -- cgit v1.2.1