def test_ShortCircuit(self): """Test that creation short-circuits to reuse existing references""" sd = {} for s in self.ss: sd[s] = 1 for t in self.ts: if hasattr(t, 'x'): assert safe_ref(t.x) in sd else: assert safe_ref(t) in sd
def test_ShortCircuit(self): """Test that creation short-circuits to reuse existing references""" sd = {} for s in self.ss: sd[s] = 1 for t in self.ts: if hasattr(t, 'x'): assert sd.has_key(safe_ref(t.x)) else: assert sd.has_key(safe_ref(t))
def unregister_callback(self, callback): cb_ref = saferef.safe_ref(callback) try: callback_refs = CHANNELS_CBK.setdefault(self.__name, set()) callback_refs.remove(cb_ref) except: return
def unregister_callback(self, callback): cb_ref = saferef.safe_ref(callback) try: callback_refs = CHANNELS_CBK.setdefault(self.__name,set()) callback_refs.remove(cb_ref) except: return
def setUp(self): ts = [] ss = [] self.closure_count = 0 self.ts = ts self.ss = ss for x in range(5000): t = _Sample1() ts.append(t) s = safe_ref(t.x, self._closure) ss.append(s) ts.append(_sample2) ss.append(safe_ref(_sample2, self._closure)) for x in range(30): t = _Sample3() ts.append(t) s = safe_ref(t, self._closure) ss.append(s)
def disconnect(receiver, signal=All, sender=Any, weak=True): """Disconnect ``receiver`` from ``sender`` for ``signal``. - ``receiver``: The registered receiver to disconnect. - ``signal``: The registered signal to disconnect. - ``sender``: The registered sender to disconnect. - ``weak``: The weakref state to disconnect. ``disconnect`` reverses the process of ``connect``, the semantics for the individual elements are logically equivalent to a tuple of ``(receiver, signal, sender, weak)`` used as a key to be deleted from the internal routing tables. (The actual process is slightly more complex but the semantics are basically the same). Note: Using ``disconnect`` is not required to cleanup routing when an object is deleted; the framework will remove routes for deleted objects automatically. It's only necessary to disconnect if you want to stop routing to a live object. Returns ``None``, may raise ``DispatcherTypeError`` or ``DispatcherKeyError``. """ if signal is None: raise error.DispatcherTypeError( 'Signal cannot be None (receiver=%r sender=%r)' % (receiver, sender)) if weak: receiver = saferef.safe_ref(receiver) senderkey = id(sender) try: signals = connections[senderkey] receivers = signals[signal] except KeyError: raise error.DispatcherKeyError( 'No receivers found for signal %r from sender %r' % (signal, sender) ) try: # also removes from receivers _remove_old_back_refs(senderkey, signal, receiver, receivers) except ValueError: raise error.DispatcherKeyError( 'No connection to receiver %s for signal %s from sender %s' % (receiver, signal, sender) ) _cleanup_connections(senderkey, signal) # Update stats. if __debug__: global disconnects disconnects += 1
def connect(handler, signal, sender=dispatcher.Any, priority=0): """ Connects a callback to a signal, so that the callback will be automatically invoked when that signal is sent. Parameters: :handler: This can be any callable that that takes the right arguments for the signal. For most signals this means a single argument that will be an ``ExecutionContext`` instance. But please see documentation for individual signals in the :ref:`signals reference <instruments_method_map>`. :signal: The signal to which the handler will be subscribed. Please see :ref:`signals reference <instruments_method_map>` for the list of standard WA signals. .. note:: There is nothing that prevents instruments from sending their own signals that are not part of the standard set. However the signal must always be an :class:`wa.core.signal.Signal` instance. :sender: The handler will be invoked only for the signals emitted by this sender. By default, this is set to :class:`louie.dispatcher.Any`, so the handler will be invoked for signals from any sender. :priority: An integer (positive or negative) the specifies the priority of the handler. Handlers with higher priority will be called before handlers with lower priority. The call order of handlers with the same priority is not specified. Defaults to 0. .. note:: Priorities for some signals are inverted (so highest priority handlers get executed last). Please see :ref:`signals reference <instruments_method_map>` for details. """ logger.debug('Connecting {} to {}({}) with priority {}'.format( handler, signal, sender, priority)) if getattr(signal, 'invert_priority', False): priority = -priority senderkey = id(sender) if senderkey in dispatcher.connections: signals = dispatcher.connections[senderkey] else: dispatcher.connections[senderkey] = signals = {} if signal in signals: receivers = signals[signal] else: receivers = signals[signal] = _prioritylist_wrapper() dispatcher.connect(handler, signal, sender) receivers.add(saferef.safe_ref(handler, on_delete=_remove_receiver), priority)
def connect(self, receiver, sender=None, weak=True, dispatch_uid=None): """Connect receiver to sender for signal. :param receiver: A function or an instance method which is to receive signals. Receivers must be hashable objects. if weak is ``True``, then receiver must be weak-referencable (more precisely :func:`saferef.safe_ref()` must be able to create a reference to the receiver). Receivers must be able to accept keyword arguments. If receivers have a ``dispatch_uid`` attribute, the receiver will not be added if another receiver already exists with that ``dispatch_uid``. :keyword sender: The sender to which the receiver should respond. Must either be of type :class:`Signal`, or ``None`` to receive events from any sender. :keyword weak: Whether to use weak references to the receiver. By default, the module will attempt to use weak references to the receiver objects. If this parameter is false, then strong references will be used. :keyword dispatch_uid: An identifier used to uniquely identify a particular instance of a receiver. This will usually be a string, though it may be anything hashable. """ if dispatch_uid: lookup_key = (dispatch_uid, _make_id(sender)) else: lookup_key = (_make_id(receiver), _make_id(sender)) if weak: receiver = saferef.safe_ref(receiver, on_delete=self._remove_receiver) for r_key, _ in self.receivers: if r_key == lookup_key: break else: self.receivers.append((lookup_key, receiver))
def connect(receiver, signal=All, sender=Any, weak=True): """Connect ``receiver`` to ``sender`` for ``signal``. - ``receiver``: A callable Python object which is to receive messages/signals/events. Receivers must be hashable objects. If weak is ``True``, then receiver must be weak-referencable (more precisely ``saferef.safe_ref()`` must be able to create a reference to the receiver). Receivers are fairly flexible in their specification, as the machinery in the ``robustapply`` module takes care of most of the details regarding figuring out appropriate subsets of the sent arguments to apply to a given receiver. Note: If ``receiver`` is itself a weak reference (a callable), it will be de-referenced by the system's machinery, so *generally* weak references are not suitable as receivers, though some use might be found for the facility whereby a higher-level library passes in pre-weakrefed receiver references. - ``signal``: The signal to which the receiver should respond. If ``All``, receiver will receive all signals from the indicated sender (which might also be ``All``, but is not necessarily ``All``). Otherwise must be a hashable Python object other than ``None`` (``DispatcherError`` raised on ``None``). - ``sender``: The sender to which the receiver should respond. If ``Any``, receiver will receive the indicated signals from any sender. If ``Anonymous``, receiver will only receive indicated signals from ``send``/``send_exact`` which do not specify a sender, or specify ``Anonymous`` explicitly as the sender. Otherwise can be any python object. - ``weak``: Whether to use weak references to the receiver. By default, the module will attempt to use weak references to the receiver objects. If this parameter is ``False``, then strong references will be used. Returns ``None``, may raise ``DispatcherTypeError``. """ if signal is None: raise error.DispatcherTypeError( f"Signal cannot be None (receiver={receiver!r} sender={sender!r})") if weak: receiver = saferef.safe_ref(receiver, on_delete=_remove_receiver) senderkey = id(sender) if senderkey in connections: signals = connections[senderkey] else: connections[senderkey] = signals = {} # Keep track of senders for cleanup. # Is Anonymous something we want to clean up? if sender not in (None, Anonymous, Any): def remove(object, senderkey=senderkey): _remove_sender(senderkey=senderkey) # Skip objects that can not be weakly referenced, which means # they won't be automatically cleaned up, but that's too bad. try: weak_sender = weakref.ref(sender, remove) senders[senderkey] = weak_sender except Exception: pass receiver_id = id(receiver) # get current set, remove any current references to # this receiver in the set, including back-references if signal in signals: receivers = signals[signal] _remove_old_back_refs(senderkey, signal, receiver, receivers) else: receivers = signals[signal] = [] try: current = senders_back.get(receiver_id) if current is None: senders_back[receiver_id] = current = [] if senderkey not in current: current.append(senderkey) except Exception: pass receivers.append(receiver) # Update stats. if __debug__: global connects connects += 1
def connect(receiver, signal=All, sender=Any, weak=True): """Connect ``receiver`` to ``sender`` for ``signal``. - ``receiver``: A callable Python object which is to receive messages/signals/events. Receivers must be hashable objects. If weak is ``True``, then receiver must be weak-referencable (more precisely ``saferef.safe_ref()`` must be able to create a reference to the receiver). Receivers are fairly flexible in their specification, as the machinery in the ``robustapply`` module takes care of most of the details regarding figuring out appropriate subsets of the sent arguments to apply to a given receiver. Note: If ``receiver`` is itself a weak reference (a callable), it will be de-referenced by the system's machinery, so *generally* weak references are not suitable as receivers, though some use might be found for the facility whereby a higher-level library passes in pre-weakrefed receiver references. - ``signal``: The signal to which the receiver should respond. If ``All``, receiver will receive all signals from the indicated sender (which might also be ``All``, but is not necessarily ``All``). Otherwise must be a hashable Python object other than ``None`` (``DispatcherError`` raised on ``None``). - ``sender``: The sender to which the receiver should respond. If ``Any``, receiver will receive the indicated signals from any sender. If ``Anonymous``, receiver will only receive indicated signals from ``send``/``send_exact`` which do not specify a sender, or specify ``Anonymous`` explicitly as the sender. Otherwise can be any python object. - ``weak``: Whether to use weak references to the receiver. By default, the module will attempt to use weak references to the receiver objects. If this parameter is ``False``, then strong references will be used. Returns ``None``, may raise ``DispatcherTypeError``. """ if signal is None: raise error.DispatcherTypeError( 'Signal cannot be None (receiver=%r sender=%r)' % (receiver, sender)) if weak: receiver = saferef.safe_ref(receiver, on_delete=_remove_receiver) senderkey = id(sender) if connections.has_key(senderkey): signals = connections[senderkey] else: connections[senderkey] = signals = {} # Keep track of senders for cleanup. # Is Anonymous something we want to clean up? if sender not in (None, Anonymous, Any): def remove(object, senderkey=senderkey): _remove_sender(senderkey=senderkey) # Skip objects that can not be weakly referenced, which means # they won't be automatically cleaned up, but that's too bad. try: weak_sender = weakref.ref(sender, remove) senders[senderkey] = weak_sender except: pass receiver_id = id(receiver) # get current set, remove any current references to # this receiver in the set, including back-references if signals.has_key(signal): receivers = signals[signal] _remove_old_back_refs(senderkey, signal, receiver, receivers) else: receivers = signals[signal] = [] try: current = senders_back.get(receiver_id) if current is None: senders_back[receiver_id] = current = [] if senderkey not in current: current.append(senderkey) except: pass receivers.append(receiver) # Update stats. if __debug__: global connects connects += 1
def register_callback(self, callback): if callable(callback): cb_ref = saferef.safe_ref(callback) self._callback_refs.add(cb_ref)
def unregister_callback(self, callback): cb_ref = saferef.safe_ref(callback) try: self._callback_refs.remove(cb_ref) except: return
def test_In(self): """Test the `in` operator for safe references (cmp)""" for t in self.ts[:50]: assert safe_ref(t.x) in self.ss
def register_callback(self, callback): if callable(callback): cb_ref = saferef.safe_ref(callback) callback_refs = CHANNELS_CBK.setdefault(self.__name,set()) callback_refs.add(cb_ref)
def register_callback(self, callback): if callable(callback): cb_ref = saferef.safe_ref(callback) callback_refs = CHANNELS_CBK.setdefault(self.__name, set()) callback_refs.add(cb_ref)