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