X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ec873c943d71f0d5f13e3398557071448cda6c23..a4027e74873007e3430af3bd77019bcab76f6c04:/wxPython/wx/py/dispatcher.py?ds=inline diff --git a/wxPython/wx/py/dispatcher.py b/wxPython/wx/py/dispatcher.py deleted file mode 100644 index c2a46734e6..0000000000 --- a/wxPython/wx/py/dispatcher.py +++ /dev/null @@ -1,262 +0,0 @@ -"""Provides global signal dispatching services.""" - -__author__ = "Patrick K. O'Brien " -__cvsid__ = "$Id$" -__revision__ = "$Revision$"[11:-2] - -import exceptions -import types -import weakref - - -class DispatcherError(exceptions.Exception): - def __init__(self, args=None): - self.args = args - - -class Parameter: - """Used to represent default parameter values.""" - def __repr__(self): - return self.__class__.__name__ - -class Any(Parameter): pass -Any = Any() - -class Anonymous(Parameter): pass -Anonymous = Anonymous() - - -connections = {} -senders = {} -_boundMethods = weakref.WeakKeyDictionary() - - -def connect(receiver, signal=Any, sender=Any, weak=True): - """ - Connect receiver to sender for signal. - - * If sender is Any, receiver will receive signal from any sender. - * If signal is Any, receiver will receive any signal from sender. - * If sender is None, receiver will receive signal from Anonymous. - * If signal is Any and sender is None, receiver will receive any - signal from Anonymous. - * If signal is Any and sender is Any, receiver will receive any - signal from any sender. - * If weak is true, weak references will be used. - """ - if signal is None: - raise DispatcherError, 'signal cannot be None' - if weak: - receiver = safeRef(receiver) - senderkey = id(sender) - signals = {} - if connections.has_key(senderkey): - signals = connections[senderkey] - else: - connections[senderkey] = signals - # Keep track of senders for cleanup. - if sender not in (None, Any): - def remove(object, senderkey=senderkey): - _removeSender(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: - weakSender = weakref.ref(sender, remove) - senders[senderkey] = weakSender - except: - pass - receivers = [] - if signals.has_key(signal): - receivers = signals[signal] - else: - signals[signal] = receivers - try: - receivers.remove(receiver) - except ValueError: - pass - receivers.append(receiver) - -def disconnect(receiver, signal=Any, sender=Any, weak=True): - """Disconnect receiver from sender for signal. - - Disconnecting is not required. The use of disconnect is the same as for - connect, only in reverse. Think of it as undoing a previous connection.""" - if signal is None: - raise DispatcherError, 'signal cannot be None' - if weak: - receiver = safeRef(receiver) - senderkey = id(sender) - try: - receivers = connections[senderkey][signal] - except KeyError: - raise DispatcherError, \ - 'No receivers for signal %r from sender %s' % (signal, sender) - try: - receivers.remove(receiver) - except ValueError: - raise DispatcherError, \ - 'No connection to receiver %s for signal %r from sender %s' % \ - (receiver, signal, sender) - _cleanupConnections(senderkey, signal) - -def send(signal, sender=Anonymous, **kwds): - """Send signal from sender to all connected receivers. - - Return a list of tuple pairs [(receiver, response), ... ]. - If sender is not specified, signal is sent anonymously.""" - senderkey = id(sender) - anykey = id(Any) - # Get receivers that receive *this* signal from *this* sender. - receivers = [] - try: - receivers.extend(connections[senderkey][signal]) - except KeyError: - pass - # Add receivers that receive *any* signal from *this* sender. - anyreceivers = [] - try: - anyreceivers = connections[senderkey][Any] - except KeyError: - pass - for receiver in anyreceivers: - if receivers.count(receiver) == 0: - receivers.append(receiver) - # Add receivers that receive *this* signal from *any* sender. - anyreceivers = [] - try: - anyreceivers = connections[anykey][signal] - except KeyError: - pass - for receiver in anyreceivers: - if receivers.count(receiver) == 0: - receivers.append(receiver) - # Add receivers that receive *any* signal from *any* sender. - anyreceivers = [] - try: - anyreceivers = connections[anykey][Any] - except KeyError: - pass - for receiver in anyreceivers: - if receivers.count(receiver) == 0: - receivers.append(receiver) - # Call each receiver with whatever arguments it can accept. - # Return a list of tuple pairs [(receiver, response), ... ]. - responses = [] - for receiver in receivers: - if type(receiver) is weakref.ReferenceType \ - or isinstance(receiver, BoundMethodWeakref): - # Dereference the weak reference. - receiver = receiver() - if receiver is None: - # This receiver is dead, so skip it. - continue - response = _call(receiver, signal=signal, sender=sender, **kwds) - responses += [(receiver, response)] - return responses - -def _call(receiver, **kwds): - """Call receiver with only arguments it can accept.""" -## if type(receiver) is types.InstanceType: - if hasattr(receiver, '__call__') and \ - (hasattr(receiver.__call__, 'im_func') or hasattr(receiver.__call__, 'im_code')): - # receiver is a class instance; assume it is callable. - # Reassign receiver to the actual method that will be called. - receiver = receiver.__call__ - if hasattr(receiver, 'im_func'): - # receiver is a method. Drop the first argument, usually 'self'. - fc = receiver.im_func.func_code - acceptable = fc.co_varnames[1:fc.co_argcount] - elif hasattr(receiver, 'func_code'): - # receiver is a function. - fc = receiver.func_code - acceptable = fc.co_varnames[0:fc.co_argcount] - else: - raise DispatcherError, 'Unknown receiver %s of type %s' % (receiver, type(receiver)) - if not (fc.co_flags & 8): - # fc does not have a **kwds type parameter, therefore - # remove unacceptable arguments. - for arg in kwds.keys(): - if arg not in acceptable: - del kwds[arg] - return receiver(**kwds) - - -def safeRef(object): - """Return a *safe* weak reference to a callable object.""" - if hasattr(object, 'im_self'): - if object.im_self is not None: - # Turn a bound method into a BoundMethodWeakref instance. - # Keep track of these instances for lookup by disconnect(). - selfkey = object.im_self - funckey = object.im_func - if not _boundMethods.has_key(selfkey): - _boundMethods[selfkey] = weakref.WeakKeyDictionary() - if not _boundMethods[selfkey].has_key(funckey): - _boundMethods[selfkey][funckey] = \ - BoundMethodWeakref(boundMethod=object) - return _boundMethods[selfkey][funckey] - return weakref.ref(object, _removeReceiver) - - -class BoundMethodWeakref: - """BoundMethodWeakref class.""" - - def __init__(self, boundMethod): - """Return a weak-reference-like instance for a bound method.""" - self.isDead = 0 - def remove(object, self=self): - """Set self.isDead to true when method or instance is destroyed.""" - self.isDead = 1 - _removeReceiver(receiver=self) - self.weakSelf = weakref.ref(boundMethod.im_self, remove) - self.weakFunc = weakref.ref(boundMethod.im_func, remove) - - def __repr__(self): - """Return the closest representation.""" - return '' % (self.weakSelf, self.weakFunc) - - def __call__(self): - """Return a strong reference to the bound method.""" - if self.isDead: - return None - else: - object = self.weakSelf() - method = self.weakFunc().__name__ - try: # wxPython hack to handle wxDead objects. - return getattr(object, method) - except AttributeError: -## _removeReceiver(receiver=self) - return None - - -def _removeReceiver(receiver): - """Remove receiver from connections.""" - for senderkey in connections.keys(): - for signal in connections[senderkey].keys(): - receivers = connections[senderkey][signal] - try: - receivers.remove(receiver) - except: - pass - _cleanupConnections(senderkey, signal) - -def _cleanupConnections(senderkey, signal): - """Delete any empty signals for senderkey. Delete senderkey if empty.""" - receivers = connections[senderkey][signal] - if not receivers: - # No more connected receivers. Therefore, remove the signal. - signals = connections[senderkey] - del signals[signal] - if not signals: - # No more signal connections. Therefore, remove the sender. - _removeSender(senderkey) - -def _removeSender(senderkey): - """Remove senderkey from connections.""" - del connections[senderkey] - # Senderkey will only be in senders dictionary if sender - # could be weakly referenced. - try: - del senders[senderkey] - except: - pass