pep8'd sugar3.dispatch

master
William Orr 11 years ago committed by Daniel Narvaez
parent 220c9b68ef
commit 51f07bba81

@ -1,6 +1,7 @@
"""Multi-consumer multi-producer dispatching mechanism
Originally based on pydispatch (BSD) http://pypi.python.org/pypi/PyDispatcher/2.0.1
Originally based on pydispatch (BSD)
http://pypi.python.org/pypi/PyDispatcher/2.0.1
See license.txt for original license.
Heavily modified for Django's purposes.

@ -8,11 +8,13 @@ from sugar3.dispatch import saferef
WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref)
def _make_id(target):
if hasattr(target, 'im_func'):
return (id(target.im_self), id(target.im_func))
return id(target)
class Signal(object):
"""Base class for all signals
@ -21,7 +23,8 @@ class Signal(object):
"""
def __init__(self, providing_args=None):
"""providing_args -- A list of the arguments this signal can pass along in
"""providing_args -- A list of the arguments
this signal can pass along in
a send() call.
"""
self.receivers = []
@ -67,7 +70,8 @@ class Signal(object):
lookup_key = (_make_id(receiver), _make_id(sender))
if weak:
receiver = saferef.safeRef(receiver, onDelete=self._remove_receiver)
receiver = saferef.safeRef(
receiver, onDelete=self._remove_receiver)
for r_key, _ in self.receivers:
if r_key == lookup_key:
@ -75,7 +79,8 @@ class Signal(object):
else:
self.receivers.append((lookup_key, receiver))
def disconnect(self, receiver=None, sender=None, weak=True, dispatch_uid=None):
def disconnect(self, receiver=None, sender=None, weak=True,
dispatch_uid=None):
"""Disconnect receiver from sender for signal
receiver -- the registered receiver to disconnect. May be none if
@ -140,7 +145,8 @@ class Signal(object):
Return a list of tuple pairs [(receiver, response), ... ],
may raise DispatcherKeyError
if any receiver raises an error (specifically any subclass of Exception),
if any receiver raises an error (specifically any subclass of
Exception),
the error instance is returned as the result for that receiver.
"""

@ -5,9 +5,11 @@ Provides a way to safely weakref any function, including bound methods (which
aren't handled by the core weakref module).
"""
import weakref, traceback
import weakref
import traceback
def safeRef(target, onDelete = None):
def safeRef(target, onDelete=None):
"""Return a *safe* weak reference to a callable target
target -- the object to be weakly referenced, if it's a
@ -22,7 +24,9 @@ def safeRef(target, onDelete = None):
if target.im_self is not None:
# Turn a bound method into a BoundMethodWeakref instance.
# Keep track of these instances for lookup by disconnect().
assert hasattr(target, 'im_func'), """safeRef target %r has im_self, but no im_func, don't know how to create reference"""%( target,)
assert hasattr(target, 'im_func'), \
"safeRef target %r has im_self, but no im_func, " \
"don't know how to create reference" % (target,)
reference = get_bound_method_weakref(
target=target,
onDelete=onDelete
@ -31,7 +35,8 @@ def safeRef(target, onDelete = None):
if callable(onDelete):
return weakref.ref(target, onDelete)
else:
return weakref.ref( target )
return weakref.ref(target)
class BoundMethodWeakref(object):
"""'Safe' and reusable weak references to instance methods
@ -69,7 +74,7 @@ class BoundMethodWeakref(object):
_allInstances = weakref.WeakValueDictionary()
def __new__( cls, target, onDelete=None, *arguments,**named ):
def __new__(cls, target, onDelete=None, *arguments, **named):
"""Create new instance or return current instance
Basically this method of construction allows us to
@ -82,14 +87,14 @@ class BoundMethodWeakref(object):
of already-referenced methods.
"""
key = cls.calculateKey(target)
current =cls._allInstances.get(key)
current = cls._allInstances.get(key)
if current is not None:
current.deletionMethods.append( onDelete)
current.deletionMethods.append(onDelete)
return current
else:
base = super( BoundMethodWeakref, cls).__new__( cls )
base = super(BoundMethodWeakref, cls).__new__(cls)
cls._allInstances[key] = base
base.__init__( target, onDelete, *arguments,**named)
base.__init__(target, onDelete, *arguments, **named)
return base
def __init__(self, target, onDelete=None):
@ -111,39 +116,38 @@ class BoundMethodWeakref(object):
methods = self.deletionMethods[:]
del self.deletionMethods[:]
try:
del self.__class__._allInstances[ self.key ]
del self.__class__._allInstances[self.key]
except KeyError:
pass
for function in methods:
try:
if callable( function ):
function( self )
if callable(function):
function(self)
except Exception, e:
try:
traceback.print_exc()
except AttributeError:
print '''Exception during saferef %s cleanup function %s: %s'''%(
self, function, e
)
print "Exception during saferef %s cleanup "
"function %s: %s" % (self, function, e)
self.deletionMethods = [onDelete]
self.key = self.calculateKey( target )
self.key = self.calculateKey(target)
self.weakSelf = weakref.ref(target.im_self, remove)
self.weakFunc = weakref.ref(target.im_func, remove)
self.selfName = str(target.im_self)
self.funcName = str(target.im_func.__name__)
def calculateKey( cls, target ):
def calculateKey(cls, target):
"""Calculate the reference key for this reference
Currently this is a two-tuple of the id()'s of the
target object and the target function respectively.
"""
return (id(target.im_self),id(target.im_func))
calculateKey = classmethod( calculateKey )
return (id(target.im_self), id(target.im_func))
calculateKey = classmethod(calculateKey)
def __str__(self):
"""Give a friendly representation of the object"""
return """%s( %s.%s )"""%(
return """%s( %s.%s )""" % (
self.__class__.__name__,
self.selfName,
self.funcName,
@ -151,15 +155,15 @@ class BoundMethodWeakref(object):
__repr__ = __str__
def __nonzero__( self ):
def __nonzero__(self):
"""Whether we are still a valid reference"""
return self() is not None
def __cmp__( self, other ):
def __cmp__(self, other):
"""Compare with another reference"""
if not isinstance (other,self.__class__):
return cmp( self.__class__, type(other) )
return cmp( self.key, other.key)
if not isinstance(other, self.__class__):
return cmp(self.__class__, type(other))
return cmp(self.key, other.key)
def __call__(self):
"""Return a strong reference to the bound method
@ -179,14 +183,15 @@ class BoundMethodWeakref(object):
return function.__get__(target)
return None
class BoundNonDescriptorMethodWeakref(BoundMethodWeakref):
"""A specialized BoundMethodWeakref, for platforms where instance methods
are not descriptors.
It assumes that the function name and the target attribute name are the
same, instead of assuming that the function is a descriptor. This approach
is equally fast, but not 100% reliable because functions can be stored on an
attribute named differenty than the function's name such as in:
is equally fast, but not 100% reliable because functions can be stored on
an attribute named differenty than the function's name such as in:
class A: pass
def foo(self): return "foo"
@ -239,12 +244,14 @@ class BoundNonDescriptorMethodWeakref(BoundMethodWeakref):
return getattr(target, function.__name__)
return None
def get_bound_method_weakref(target, onDelete):
"""Instantiates the appropiate BoundMethodWeakRef, depending on the details of
the underlying class method implementation"""
"""Instantiates the appropiate BoundMethodWeakRef, depending on the
details of the underlying class method implementation"""
if hasattr(target, '__get__'):
# target method is a descriptor, so the default implementation works:
return BoundMethodWeakref(target=target, onDelete=onDelete)
else:
# no luck, use the alternative implementation:
return BoundNonDescriptorMethodWeakref(target=target, onDelete=onDelete)
return BoundNonDescriptorMethodWeakref(target=target,
onDelete=onDelete)

Loading…
Cancel
Save