This recipe allows for calling an unlimited chain of nonexistent attributes - every call is forwarded to a default method with attribute chain as argument.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class MagicObject:
def __call__(self,*args,**kwargs):
return MagicObject.__dict__['_stop'](self,self.n,*args,**kwargs)
def __getattr__(self,name):
if name in ('__str__','__repr__'): return lambda:'instance of %s at %s' % (str(self.__class__),id(self))
if not self.__dict__.has_key('n'):self.n=[]
self.n.append(name)
return self
def _stop(self,n,*args,**kwargs):
self.n=[]
return self.default(n,*args,**kwargs)
def default(self,n,*args,**kwargs):
return 'stop',n,args,kwargs
#############################################################333
>>c=MagicObject()
>>x=c.beubeb.zzzzz(1,2,3,a='bbb')
>>print x
('stop', ['beubeb', 'zzzzz'], (1, 2, 3), {'a': 'bbb'})
|
I needed this to proxy XMLRPC calls - I wanted to have a local object which I could call as it was a remote object on the server, no matter how deep the attribute chain on the remote object is. I think it can be useful in many other situations, whenever you want to fake or proxy a more complicated object.
This recipe extends the __getattr__ method, so that you can call object.attr.subattr.method() and it all goes to the 'default' method, with a list of attributes in the chain as the first argument.
It works only for method calls - what I don't know is how to handle requests for nonexistent attributes. I just return self - maybe somebody smarter will come up with a solution how to pass them to the handler.
Give this a try if you want to capture requests for non-extant attributes or function calls:
class MagicObject2(MagicObject):
Notice the difference between this and whatever the original object might return:
You may find it easier to interpret the following when it comes time to make sense of what happened with this object at runtime:
{'beubeb': {'zzzzz': ((1, 2, 3), {'a': 'bbb'})}}
You would have to work from the inside outwards when making sense of this stuff but if you need this functionality it would make sense to use it.
Perhaps a few more lines of code might be requires to turn the MagicObject2 into something usable but you probably get the gist of where this is going from what I have posted above.
For more you can look at http://www.pypi.info <-- Might see something useful !