diff options
author | jason kirtland <jek@discorporate.us> | 2010-07-21 11:07:13 +0100 |
---|---|---|
committer | jason kirtland <jek@discorporate.us> | 2010-07-21 11:07:13 +0100 |
commit | fa3be696ab410308191ed4af804a31d2ba60144d (patch) | |
tree | 3cfd919986622a0d5857967480d4c95d7e69cc2c | |
parent | 50ac3faf7d154b6bd57ed3341dae3a31cab82013 (diff) | |
download | blinker-fa3be696ab410308191ed4af804a31d2ba60144d.tar.gz |
Added Signal.connect_via() decorator.
-rw-r--r-- | blinker/base.py | 26 | ||||
-rw-r--r-- | docs/source/signals.rst | 14 | ||||
-rw-r--r-- | tests/test_signals.py | 26 |
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): |