mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #5664 -- Added a Jython workaround for some assumptions in the signal
dispatch code. Thanks, Leo Soto. git-svn-id: http://code.djangoproject.com/svn/django/trunk@6586 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -1,5 +1,6 @@ | |||||||
| """Refactored "safe reference" from dispatcher.py""" | """Refactored "safe reference" from dispatcher.py""" | ||||||
| import weakref, traceback | import weakref, traceback | ||||||
|  | from django.utils.functional import curry | ||||||
|  |  | ||||||
| def safeRef(target, onDelete = None): | def safeRef(target, onDelete = None): | ||||||
|     """Return a *safe* weak reference to a callable target |     """Return a *safe* weak reference to a callable target | ||||||
| @@ -17,7 +18,7 @@ def safeRef(target, onDelete = None): | |||||||
|             # Turn a bound method into a BoundMethodWeakref instance. |             # Turn a bound method into a BoundMethodWeakref instance. | ||||||
|             # Keep track of these instances for lookup by disconnect(). |             # 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 = BoundMethodWeakref( |             reference = get_bound_method_weakref( | ||||||
|                 target=target, |                 target=target, | ||||||
|                 onDelete=onDelete |                 onDelete=onDelete | ||||||
|             ) |             ) | ||||||
| @@ -163,3 +164,75 @@ class BoundMethodWeakref(object): | |||||||
|             if function is not None: |             if function is not None: | ||||||
|                 return function.__get__(target) |                 return function.__get__(target) | ||||||
|         return None |         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: | ||||||
|  |  | ||||||
|  |     class A: pass | ||||||
|  |     def foo(self): return "foo" | ||||||
|  |     A.bar = foo | ||||||
|  |  | ||||||
|  |     But this shouldn't be a common use case. So, on platforms where methods | ||||||
|  |     aren't descriptors (such as Jython) this implementation has the advantage | ||||||
|  |     of working in the most cases. | ||||||
|  |     """ | ||||||
|  |     def __init__(self, target, onDelete=None): | ||||||
|  |         """Return a weak-reference-like instance for a bound method | ||||||
|  |  | ||||||
|  |         target -- the instance-method target for the weak | ||||||
|  |             reference, must have im_self and im_func attributes | ||||||
|  |             and be reconstructable via: | ||||||
|  |                 target.im_func.__get__( target.im_self ) | ||||||
|  |             which is true of built-in instance methods. | ||||||
|  |         onDelete -- optional callback which will be called | ||||||
|  |             when this weak reference ceases to be valid | ||||||
|  |             (i.e. either the object or the function is garbage | ||||||
|  |             collected).  Should take a single argument, | ||||||
|  |             which will be passed a pointer to this object. | ||||||
|  |         """ | ||||||
|  |         assert getattr(target.im_self, target.__name__) == target, \ | ||||||
|  |                ("method %s isn't available as the attribute %s of %s" % | ||||||
|  |                 (target, target.__name__, target.im_self)) | ||||||
|  |         super(BoundNonDescriptorMethodWeakref, self).__init__(target, onDelete) | ||||||
|  |  | ||||||
|  |     def __call__(self): | ||||||
|  |         """Return a strong reference to the bound method | ||||||
|  |  | ||||||
|  |         If the target cannot be retrieved, then will | ||||||
|  |         return None, otherwise returns a bound instance | ||||||
|  |         method for our object and function. | ||||||
|  |  | ||||||
|  |         Note: | ||||||
|  |             You may call this method any number of times, | ||||||
|  |             as it does not invalidate the reference. | ||||||
|  |         """ | ||||||
|  |         target = self.weakSelf() | ||||||
|  |         if target is not None: | ||||||
|  |             function = self.weakFunc() | ||||||
|  |             if function is not None: | ||||||
|  |                 # Using curry() would be another option, but it erases the | ||||||
|  |                 # "signature" of the function. That is, after a function is | ||||||
|  |                 # curried, the inspect module can't be used to determine how | ||||||
|  |                 # many arguments the function expects, nor what keyword | ||||||
|  |                 # arguments it supports, and pydispatcher needs this | ||||||
|  |                 # information. | ||||||
|  |                 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""" | ||||||
|  |     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) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user