transparent proxy object
Irmen de Jong
irmen at -NOSPAM-REMOVETHIS-xs4all.nl
Wed Feb 26 17:41:09 EST 2003
Alex A. Naanou wrote:
> Task:
> "transparently" intercept/cache all calls to the object, all its
> attributes and sub-objects while maintaining full object
> functionality.
>
> The Answer:
> here is the answer I came up with, though it fits the task
> semanticly and I like how it works in concept, the application is
> rather time-critical thus this code does not fit the job...
> does any one have an idea how to implement something with the same
> semantics but more efficiently (I'm intrested in a pure Python
> solution, not a C/C++ extention type)?? ...Thanks.
>
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
-----
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):
return 1 # method
except:
pass
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):
print "init from test"
self.attribute = 42
def method(self, arg):
print "method in test, arg=",arg
return "result from test method!!!"
def setAttribute(self, value):
self.attribute=value
object = Test()
proxy = DynamicProxy(object)
print "Calling method:"
print proxy.method("the arguments")
print "Printing attribute:"
print proxy.attribute
print "Setting attribute with method"
proxy.setAttribute(99)
print "Printing attribute:"
print proxy.attribute
print "Setting attribute directly"
proxy.attribute=555
print "Printing attribute:"
print proxy.attribute
print "Printing original attribute:"
print object.attribute
More information about the Python-list
mailing list