My tools of the trade for python programming.
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.

87 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)