You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.4 KiB
86 lines
2.4 KiB
# -*- python -*-
|
|
#
|
|
# $Id: im_weakref.py,v 1.2 2011-09-07 15:04:15 wirawan Exp $
|
|
#
|
|
# wpylib.py.im_weakref
|
|
# Created: 20110607
|
|
# Wirawan Purwanto
|
|
#
|
|
# Advanced hack tools for python: weakref proxy class for instance-method.
|
|
#
|
|
|
|
"""
|
|
wpylib.py.im_weakref
|
|
|
|
Complement of weakref's weak reference for an instance method
|
|
(whether bound or unbound).
|
|
|
|
Original-source: Linux Screen Reader project
|
|
Copied-from: http://mindtrove.info/python-weak-references/
|
|
Date: 20110607
|
|
"""
|
|
|
|
import weakref, new
|
|
|
|
class im_ref(object):
|
|
'''
|
|
Our own proxy object which enables weak references to bound and unbound
|
|
methods and arbitrary callables. Pulls information about the function,
|
|
class, and instance out of a bound method. Stores a weak reference to the
|
|
instance to support garbage collection.
|
|
|
|
@organization: IBM Corporation
|
|
@copyright: Copyright (c) 2005, 2006 IBM Corporation
|
|
@license: The BSD License
|
|
'''
|
|
def __init__(self, cb):
|
|
try:
|
|
try:
|
|
self.inst = weakref.ref(cb.im_self)
|
|
except TypeError:
|
|
self.inst = None
|
|
self.func = cb.im_func
|
|
self.klass = cb.im_class
|
|
except AttributeError:
|
|
self.inst = None
|
|
self.func = cb.im_func
|
|
self.klass = None
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
'''
|
|
Proxy for a call to the weak referenced object. Take arbitrary params to
|
|
pass to the callable.
|
|
|
|
@raise ReferenceError: When the weak reference refers to a dead object
|
|
'''
|
|
if self.inst is not None and self.inst() is None:
|
|
raise ReferenceError, "Original object (of type %s) is already dead." % (self.klass)
|
|
elif self.inst is not None:
|
|
# build a new instance method with a strong reference to the instance
|
|
mtd = new.instancemethod(self.func, self.inst(), self.klass)
|
|
else:
|
|
# not a bound method, just return the func
|
|
mtd = self.func
|
|
# invoke the callable and return the result
|
|
return mtd(*args, **kwargs)
|
|
|
|
def __eq__(self, other):
|
|
'''
|
|
Compare the held function and instance with that held by another proxy.
|
|
|
|
@param other: Another proxy object
|
|
@type other: L{Proxy}
|
|
@return: Whether this func/inst pair is equal to the one in the other
|
|
proxy object or not
|
|
@rtype: boolean
|
|
'''
|
|
try:
|
|
return self.func == other.func and self.inst() == other.inst()
|
|
except Exception:
|
|
return False
|
|
|
|
def __ne__(self, other):
|
|
'''
|
|
Inverse of __eq__.
|
|
'''
|
|
return not self.__eq__(other)
|
|
|