Permit anyone to add methods to a class in a library without having to change the name of the class by subclassing. This is like having a plugins directory. Also, given a normal function, treat it as a method of an arbitrary class (i.e. mimic a bound method).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | """This mixin supports autoloading of "friend" methods."""
__docformat__ = "restructuredtext"
from Curry import Curry
class HasFriends:
"""This mixin supports autoloading of "friend" methods.
That means if you have a class like ``aquarium.widget.FormUtil``, and you
try to call a function ``fooBar`` on that class, ``FormUtil`` (assuming it
mixes in this class) will automatically import
``aquarium.widget.formutil.fooBar`` (notice that the ``FormUtil`` class is
automatically associated with the ``formutil`` package) and return the
``fooBar`` function. ``fooBar`` will behave as if it were actually a
method inside ``FormUtil``. ``fooBar`` should be implemented as a normal
method that just happens to receive a ``FormUtil`` instance named ``self``
as its first argument.
"""
def __getattr__(self, attr):
"""Return the desired friend method.
Note, these methods will be cached in ``self._friendCache``.
"""
if not self.__dict__.has_key("_friendCache"):
self._friendCache = {}
cache = self._friendCache
if not cache.has_key(attr):
pieces = self.__module__.split(".")
pieces[-1] = pieces[-1].lower()
pieces.append(attr)
moduleName = ".".join(pieces)
try:
module = __import__(moduleName, {}, {}, [attr])
except:
raise (AttributeError, """\
%s instance has no attribute '%s', and HasFriends failed too""" %
(self.__class__.__name__, attr))
f = getattr(module, attr)
curry = Curry(f, self)
cache[attr] = curry
return cache[attr]
|
Note that this comes from the Aquarium Web application framework, but any references to Aquarium can easily be removed.
Tags: oop