[Zope-dev] Beyond Acquisition
jalon@dev.in.nuxeo.com
jalon@dev.in.nuxeo.com
Fri, 19 Apr 2002 17:32:21 +0000 (UTC)
In article <6ae0cu8p0j6a7grmcdneeujvtlbpju26e1@4ax.com>,
Toby Dickenson <tdickenson@geminidataloggers.com> wrote:
>On Fri, 19 Apr 2002 15:28:52 +0000 (UTC), jalon@dev.in.nuxeo.com ()
>wrote:
>
>>It seems there is no way to get the real 'b' attribute from a, i.e. the
>>B instance set at the line "a.b = B()"
>
>Thats exactly right. your __of__ method means that *any* time you try
>to take a B object out of an A, you get a C object instead of a B.
>
>try a.__dict__['b']
That's not a good solution since the b attribute can be defined in the
classes of a...
With some tries, I think I got the solution:
_nodefault = []
def getrealattr(obj, name, default = _nodefault):
try:
return obj.__dict__[name]
except KeyError: pass
objclass = obj.__class__
try:
attr = getattr(objclass, name)
if hasattr(attr, '__of__'):
# a trick from extension class:
# whenever you get a class attribute,
# you will get a Python Method
# im_func get the function if it is a
# method and the real object if not
return attr.im_func
return attr
except AttributeError:
if default is _nodefault: raise
return default
if __name__ == '__main__':
# Tests
from Acquisition import Implicit
class C(Implicit):
def __init__(self, name):
self.name = name
class B(C):
def __of__(self, parent):
return C(self.name + ' (in object %s)' % parent.name).__of__(parent)
class A(C):
b = B('b in the class')
a = C('a')
b = B('b')
a.b = b
print 'a.b = %s' % a.b.name
print 'real a.b = %s' % getrealattr(a, 'b').name
a = A('a')
print 'a.b = %s' % a.b.name
print 'real a.b = %s' % getrealattr(a, 'b').name
print getrealattr(a, 'c', None)
--
Julien Jalon
http://www.nuxeo.com/