Пример #1
0
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
Пример #2
0
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