def connect(self, receiver, sender=ANY, weak=True): """Connect *receiver* to signal events sent by *sender*. :param receiver: A callable. Will be invoked by :meth:`send` with `sender=` as a single positional argument and any \*\*kwargs that were provided to a call to :meth:`send`. :param sender: Any object or :obj:`ANY`, defaults to ``ANY``. Restricts notifications delivered to *receiver* to only those :meth:`send` emissions sent by *sender*. If ``ANY``, the receiver will always be notified. A *receiver* may be connected to multiple *sender* values on the same Signal through multiple calls to :meth:`connect`. :param weak: If true, the Signal will hold a weakref to *receiver* and automatically disconnect when *receiver* goes out of scope or is garbage collected. Defaults to True. """ receiver_id = hashable_identity(receiver) if weak: receiver_ref = reference(receiver, self._cleanup_receiver) receiver_ref.receiver_id = receiver_id else: receiver_ref = receiver if sender is ANY: sender_id = ANY_ID else: sender_id = hashable_identity(sender) self.receivers.setdefault(receiver_id, receiver_ref) self._by_sender[sender_id].add(receiver_id) self._by_receiver[receiver_id].add(sender_id) del receiver_ref if sender is not ANY and sender_id not in self._weak_senders: # wire together a cleanup for weakref-able senders try: sender_ref = reference(sender, self._cleanup_sender) sender_ref.sender_id = sender_id except TypeError: pass else: self._weak_senders.setdefault(sender_id, sender_ref) del sender_ref # broadcast this connection. if receivers raise, disconnect. if receiver_connected.receivers and self is not receiver_connected: try: receiver_connected.send(self, receiver_arg=receiver, sender_arg=sender, weak_arg=weak) except: self.disconnect(receiver, sender) raise return receiver
def connect(self, receiver, weak=True): """\ Connect a signal receiver to me. `proc` will be called with two positional arguments: the destination object and the signal that's transmitted. Whatever keywords args the sender set in its .send() call are passed as-is. """ if not hasattr(self,'_receivers'): self._receivers = dict() receiver_id = hashable_identity(receiver) if weak: receiver_ref = reference(receiver, self._cleanup_receiver) receiver_ref.receiver_id = receiver_id else: receiver_ref = receiver self._receivers.setdefault(receiver_id, receiver_ref)
def connect(self, receiver, sender=ANY, weak=True): """Connect *receiver* to signal events send by *sender*. :param receiver: A callable. Will be invoked by :meth:`send`. Will be invoked with `sender=` as a named argument and any \*\*kwargs that were provided to a call to :meth:`send`. :param sender: Any object or :attr:`Signal.ANY`. Restricts notifications to *receiver* to only those :meth:`send` emissions sent by *sender*. If ``ANY``, the receiver will always be notified. A *receiver* may be connected to multiple *sender* on the same Signal. Defaults to ``ANY``. :param weak: If true, the Signal will hold a weakref to *receiver* and automatically disconnect when *receiver* goes out of scope or is garbage collected. Defaults to True. """ receiver_id = hashable_identity(receiver) if weak: receiver_ref = reference(receiver, self._cleanup_receiver) receiver_ref.receiver_id = receiver_id else: receiver_ref = receiver if sender is ANY: sender_id = ANY_ID else: sender_id = hashable_identity(sender) # 主要需要登记 receiver_id, sender_id, receiver_ref # receiver_ref 对应两种情况 1. 当要求存入弱引用时(选项weak 为 true,需要对传入的引用做一次弱引用的封装) # 2. 选项为false时,直接赋值为原值就好了 # receiver的引用保存在 receivers dict 中,通过receiver_id进行查询 self.receivers.setdefault(receiver_id, receiver_ref) # _by_sender 字典用来保存对应于每个sender的receiver 订阅者 # _by_receiver 字典相反,用来保存对于每个 receiver 订阅者的 sender self._by_sender[sender_id].add(receiver_id) self._by_receiver[receiver_id].add(sender_id) # todo 这个del 很奇怪,每次函数结束receiver_ref是会被自动删除的才对,为什么要自行del del receiver_ref if sender is not ANY and sender_id not in self._weak_senders: # wire together a cleanup for weakref-able senders try: sender_ref = reference(sender, self._cleanup_sender) sender_ref.sender_id = sender_id except TypeError: pass # 第一次碰到 try-except中的else。这个else对应于 没有exception抛出的情况 要执行的内容 else: self._weak_senders.setdefault(sender_id, sender_ref) del sender_ref # broadcast this connection. if receivers raise, disconnect. # todo receiver_connected 的作用? # 每次对任意一个Signal(当然receriver_connected Signal除外), # 都会触发receiver_connected信号,我们可以对receiver_connected 信号进行订阅,做一些有用的事情,比如记录每次信号触发的信息 if receiver_connected.receivers and self is not receiver_connected: # 判断 self is not receiver_connected 十分重要,不然会引起死循环 try: receiver_connected.send( self, # sender 是Signal自己 receiver_arg= receiver, # 下面的args 是记录的信号收发的信息,三要素:收信人,寄信人,是否要求弱引用 sender_arg=sender, weak_arg=weak) except: self.disconnect(receiver, sender) raise return receiver