transparent proxy object
Alex A. Naanou
alex_nanou at pochtamt.ru
Thu Feb 27 04:59:55 EST 2003
Irmen de Jong <irmen at -NOSPAM-REMOVETHIS-xs4all.nl> wrote:
...
> What about the code below?
> I snipped it from Pyro and stripped it a bit.
> Didn't do any comparison with your code, although yours
> looks a lot more complex than this one...
>
> Irmen de Jong
>
The code you posted works quite fine, while we stay within a one level
attribute reference (i.e. "Class.Attribute" not
"Class.Attribute_L1.Attribute_L2"... etc.), the goal was to intercept
references of any depth....
here is a slightly modified version of your code to demonstrate the
effect...
---cut---
m_queue = []
a_queue = []
class DynamicProxy:
def __init__(self, proxiedObject):
# first set the list of 'local' attrs for __setattr__
self.__dict__["_local_attrs"] = ("_local_attrs", "_name",
"_proxiedObject" )
self._proxiedObject=proxiedObject
self._name=[]
def _r_ga(self, attr, value=0):
if value: self._name.append("_r_ga")
else: self._name.append("_r_ha")
return self.__invokeOriginal__(attr)
def findattr(self, attr):
return self._r_ga(attr)
def __setattr__(self, attr, value):
if attr in self.__dict__["_local_attrs"]:
self.__dict__[attr]=value
else:
result = self.findattr(attr)
if result==2: # attribute
self._name.append("_r_sa")
return self.__invokeOriginal__(attr,value)
else:
raise AttributeError('not an attribute')
def __getattr__(self, attr):
# allows it to be safely pickeled
if attr != "__getinitargs__":
result=self.findattr(attr)
if result==1: # method
self._name.append(attr)
return self.__invokeOriginal__
elif result:
return self._r_ga(attr, 1)
raise AttributeError()
def __invokeOriginal__(self, *vargs, **kargs):
methodName=self._name.pop()
if methodName=="_r_ha":
try:
attr = getattr(self._proxiedObject ,vargs[0])
if type(attr) in (UnboundMethodType, MethodType,
BuiltinMethodType):
###
global m_queue
m_queue += [vargs[0]]
return 1 # method
except:
pass
###
global a_queue
a_queue += [vargs[0]]
return 2 # attribute
elif methodName=="_r_ga":
return getattr(self._proxiedObject, vargs[0])
elif methodName=="_r_sa":
return setattr(self._proxiedObject, vargs[0], vargs[1])
method = getattr(self._proxiedObject, methodName )
return apply(method, vargs, kargs)
# test
class Test:
def __init__(self, n=0):
print "init from test"
self.attribute = 42
if n == 0:
self.nestedClass = Test(1)
def method(self, arg):
print "method in test, arg =",arg
return "result from test method!!!"
def setAttribute(self, value):
self.attribute=value
def __call__(self):
print 'call of test'
return 'result call of test...'
object = Test()
proxy = DynamicProxy(object)
###
print "============================="
print 'running call of proxied object'
print proxy()
print
print 'getting attribute of a nested class'
print proxy.nestedClass.attribute
print
print 'calling method of a nested class'
print proxy.nestedClass.setAttribute(99999)
print "============================="
print '\n\nmethod queue: ', m_queue
print '\nattribute queue:', a_queue
---uncut---
More information about the Python-list
mailing list