diff options
Diffstat (limited to 'blinker/base.py')
-rw-r--r-- | blinker/base.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/blinker/base.py b/blinker/base.py index d2a9eff..17c6833 100644 --- a/blinker/base.py +++ b/blinker/base.py @@ -16,6 +16,7 @@ from blinker._utilities import ( contextmanager, defaultdict, hashable_identity, + lazy_property, reference, symbol, ) @@ -33,6 +34,42 @@ class Signal(object): #: without an additional import. ANY = ANY + @lazy_property + def receiver_connected(self): + """Emitted after each :meth:`connect`. + + The signal sender is the signal instance, and the :meth:`connect` + arguments are passed through: *receiver*, *sender*, and *weak*. + + .. versionadded:: 1.2 + + """ + return Signal(doc="Emitted after a receiver connects.") + + @lazy_property + def receiver_disconnected(self): + """Emitted after :meth:`disconnect`. + + The sender is the signal instance, and the :meth:`disconnect` arguments + are passed through: *receiver* and *sender*. + + Note, this signal is emitted **only** when :meth:`disconnect` is + called explicitly. + + The disconnect signal can not be emitted by an automatic disconnect + (due to a weakly referenced receiver or sender going out of scope), + as the receiver and/or sender instances are no longer available for + use at the time this signal would be emitted. + + An alternative approach is available by subscribing to + :attr:`receiver_connected` and setting up a custom weakref cleanup + callback on weak receivers and senders. + + .. versionadded:: 1.2 + + """ + return Signal(doc="Emitted after a receiver disconnects.") + def __init__(self, doc=None): """ :param doc: optional. If provided, will be assigned to the signal's @@ -99,6 +136,16 @@ class Signal(object): del sender_ref # broadcast this connection. if receivers raise, disconnect. + if ('receiver_connected' in self.__dict__ and + self.receiver_connected.receivers): + try: + self.receiver_connected.send(self, + receiver=receiver, + sender=sender, + weak=weak) + except: + self.disconnect(receiver, sender) + raise if receiver_connected.receivers and self is not receiver_connected: try: receiver_connected.send(self, @@ -273,6 +320,12 @@ class Signal(object): receiver_id = hashable_identity(receiver) self._disconnect(receiver_id, sender_id) + if ('receiver_disconnected' in self.__dict__ and + self.receiver_disconnected.receivers): + self.receiver_disconnected.send(self, + receiver=receiver, + sender=sender) + def _disconnect(self, receiver_id, sender_id): if sender_id == ANY_ID: if self._by_receiver.pop(receiver_id, False): @@ -310,6 +363,13 @@ Sent by a :class:`Signal` after a receiver connects. :keyword sender_arg: the sender to connect to :keyword weak_arg: true if the connection to receiver_arg is a weak reference +.. deprecated:: 1.2 + +As of 1.2, individual signals have their own private +:attr:`~Signal.receiver_connected` and +:attr:`~Signal.receiver_disconnected` signals with a slightly simplified +call signature. This global signal is planned to be removed in 1.6. + """) |