summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason kirtland <jek@discorporate.us>2010-07-21 11:07:13 +0100
committerjason kirtland <jek@discorporate.us>2010-07-21 11:07:13 +0100
commitfa3be696ab410308191ed4af804a31d2ba60144d (patch)
tree3cfd919986622a0d5857967480d4c95d7e69cc2c
parent50ac3faf7d154b6bd57ed3341dae3a31cab82013 (diff)
downloadblinker-fa3be696ab410308191ed4af804a31d2ba60144d.tar.gz
Added Signal.connect_via() decorator.
-rw-r--r--blinker/base.py26
-rw-r--r--docs/source/signals.rst14
-rw-r--r--tests/test_signals.py26
3 files changed, 65 insertions, 1 deletions
diff --git a/blinker/base.py b/blinker/base.py
index 171eb46..d2a9eff 100644
--- a/blinker/base.py
+++ b/blinker/base.py
@@ -110,6 +110,32 @@ class Signal(object):
raise
return receiver
+ def connect_via(self, sender, weak=False):
+ """Connect the decorated function as a receiver for *sender*.
+
+ :param sender: Any object or :obj:`ANY`. The decorated function
+ will only receive :meth:`send` emissions sent by *sender*. If
+ ``ANY``, the receiver will always be notified. A function may be
+ decorated multiple times with differing *sender* values.
+
+ :param weak: If true, the Signal will hold a weakref to the
+ decorated function and automatically disconnect when *receiver*
+ goes out of scope or is garbage collected. Unlike
+ :meth:`connect`, this defaults to False.
+
+ The decorated function will be invoked by :meth:`send` with
+ `sender=` as a single positional argument and any \*\*kwargs that
+ were provided to the call to :meth:`send`.
+
+
+ .. versionadded:: 1.1
+
+ """
+ def decorator(fn):
+ self.connect(fn, sender, weak)
+ return fn
+ return decorator
+
@contextmanager
def connected_to(self, receiver, sender=ANY):
"""Execute a block with the signal temporarily connected to *receiver*.
diff --git a/docs/source/signals.rst b/docs/source/signals.rst
index 8bb967a..b17338f 100644
--- a/docs/source/signals.rst
+++ b/docs/source/signals.rst
@@ -184,7 +184,19 @@ be used as a decorator on functions:
While convenient, this form unfortunately does not allow the
``sender`` or ``weak`` arguments to be customized for the connected
-function.
+function. For this, :meth:`~Signal.connect_via` can be used:
+
+.. doctest::
+
+ >>> dice_roll = signal('dice_roll')
+ >>> @dice_roll.connect_via(1)
+ ... @dice_roll.connect_via(3)
+ ... @dice_roll.connect_via(5)
+ ... def odd_subscriber(sender):
+ ... print("Observed dice roll %r." % sender)
+ ...
+ >>> result = dice_roll.send(3)
+ Observed dice roll 3.
Optimizing Signal Sending
diff --git a/tests/test_signals.py b/tests/test_signals.py
index 34a8fa3..9a5a5ce 100644
--- a/tests/test_signals.py
+++ b/tests/test_signals.py
@@ -198,6 +198,32 @@ def test_filtered_receiver_weakref():
values_are_empty_sets_(sig._by_sender)
+def test_decorated_receiver():
+ sentinel = []
+
+ class Object(object):
+ pass
+ obj = Object()
+
+ sig = blinker.Signal()
+
+ @sig.connect_via(obj)
+ def receiver(sender, **kw):
+ sentinel.append(kw)
+
+ assert not sentinel
+ sig.send()
+ assert not sentinel
+ sig.send(1)
+ assert not sentinel
+ sig.send(obj)
+ assert sig.receivers
+
+ del receiver
+ collect()
+ assert sig.receivers
+
+
def test_no_double_send():
sentinel = []
def received(sender):