__getattribute__ and methods proxying

Thomas Jollans thomas at jollans.com
Sat Jun 12 16:42:07 EDT 2010


On 06/12/2010 09:59 PM, Giampaolo Rodolà wrote:
> 2010/6/12 David Zaslavsky <diazona at ellipsix.net>:
>> Hi,
>>
>> The problem is that when you make this call:
>>> proc.cmdline()
>> there are really two steps involved. First you are accessing proc.cmdline,
>> then you are calling it. You could think of it as this:
>>  func = proc.cmdline
>>  func()
>> __getattribute__ is able to modify how the first step works, but not the
>> second. And it is the second step where the OSError gets raised.
>>
>> You could get around this by returning a wrapper function from
>> __getattribute__, something like this I think:
>>
>>     def __getattribute__(self, name):
>>         f = object.__getattribute__(self, name)
>>         # here you should really check whether it's a function
>>         def wrapper(self, *args, **kwargs)
>>             print "here 1!"
>>             try:
>>                 f(*args, **kwargs)
>>             except OSError, err:
>>                 print "here 2!"
>>                 if err.errno == errno.ESRCH:
>>                     raise NoSuchProcess
>>                 if err.errno == errno.EPERM:
>>                     raise AccessDenied
>>        return wrapper
>>
>> That way "func" gets set to the wrapper function, which will handle your
>> exception as you want.
>>
>> :) David
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
> 
> Clear, thanks.
> Isn't there a prettier/common way to do this?
> A __methodcall__(self, method_obj) special method or something? Has
> something like that ever been proposed for inclusion?

There is no such thing as a method call in Python. There is attribute
access, and there is calling objects. You could, of course, create a
__methodcall__ method. That might look something like this:


class with_methodcall_trick(object):
    def __methodcall__(self, method, *args, **kwa):
        raise NotImplementedError("__methodcall__ must be overriden")

    def __getattribute__(self, name):
        obj = super(with_methodcall_trick, self).__getattribute__(name)
        if callable(obj):
            wrapper = functools.partial(self.__methodcall__, obj)
            functools.update_wrapper(wrapper, obj)
            return wrapper
        else:
            return wrapped



More information about the Python-list mailing list