I found this recipe to create a proxy class. I've used it to wrap a custom object and would like to overload certain properties and also attach new attributes to the proxy. However, when I call any method on the proxy (from within the proxy class), I end up being delegated to the wrappee which is not what I want.
Is there any way of accessing or storing a reference to the proxy?
Here's some code (untested) to demonstrate the problem.
class MyObject(object):
@property
def value(self):
return 42
class MyObjectProxy(Proxy): # see the link above
def __getattribute__(self, attr):
# the problem is that `self` refers to the proxied
# object and thus this throws an AttributeError. How
# can I reference MyObjectProxy.another_value()?
if attr == 'value': return self.another_value() # return method or attribute, doesn't matter (same effect)
return super(MyObjectProxy, self).__getattribute__(attr)
def another_value(self):
return 21
o = MyObject()
p = MyObjectProxy(o)
print o.value
print p.value
In a sense my problem is that the proxy works too good, hiding all its own methods/attributes and posing itself as the proxied object (which is what it should do)...
Update
Based on the comments below, I changed __getattribute__
to this:
def __getattribute__(self, attr):
try:
return object.__getattribute__(self, attr)
except AttributeError:
return super(MyObjectProxy, self).__getattribute__(attr)
This seems to do the trick for now, but it would be better to add this directly to the Proxy
class.
The reason that your code goes wrong is the loop in __getattribute__
. You want to override __getattribute__
so you can reach certain properties in the proxy class itself. But let's see.
When you call p.value
the __getattribute__
is called. Then it comes here if attr == 'value': return self.another_value()
. Here we need to call another_value
so we enter __getattribute__
again.
This time we comes here return super(MyObjectProxy, self).__getattribute__(attr)
. We call the Proxy
's __getattribute__
, and it tries to fetch another_value
in Myobject
. So the exceptions occur.
You can see from the traceback that we finally goes to return super(MyObjectProxy, self).__getattribute__(attr)
that should not go to.
Traceback (most recent call last):
File "proxytest.py", line 22, in <module>
print p.value
File "proxytest.py", line 13, in __getattribute__
if attr == 'value': return self.another_value() # return method or attribute, doesn't matter (same effect)
File "proxytest.py", line 14, in __getattribute__
return super(MyObjectProxy, self).__getattribute__(attr)
File "/home/hugh/m/tspace/proxy.py", line 10, in __getattribute__
return getattr(object.__getattribute__(self, "_obj"), name)
AttributeError: 'MyObject' object has no attribute 'another_value'
edit:
Change the line of code if attr == 'value': return self.another_value()
to if attr == 'value': return object.__getattribute__(self, 'another_value')()
.