wrapt icon indicating copy to clipboard operation
wrapt copied to clipboard

Error on ObjectProxy are silently skipped

Open schlichtanders opened this issue 8 years ago • 8 comments

Dear all,

I really really love this package. There is one drawback which I want to share:

from wrapt import ObjectProxy

class A(ObjectProxy):
    @property
    def error(self):
        raise ValueError("look here")

a = A(67)
a.error

will give the following error

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-563983c3078f> in <module>()
      1 a = A(67)
----> 2 a.error

AttributeError: 'int' object has no attribute 'error'

which in many many cases is practically useless, as we call this error method/property because we know we are using the proxy.

Hence I would suggest to change the error behaviour such that the ObjectProxy Error is correctly raised up to global scope.

Environment:

  • Windows 10 64bit
  • python 3.6
  • wrapt 1.10.10

schlichtanders avatar May 04 '17 13:05 schlichtanders

I just looked into the implementation of ObjectProxy, but couldn't find any hint why this is happening the behaviour suggests as if __getattribute__ is overwritten, however it isn't according to the code...

schlichtanders avatar May 04 '17 13:05 schlichtanders

After some initial tests it seems like the following already solves the issue, however I don't know why:

class ObjectProxyRaisingErrors(ObjectProxy):
    def __getattribute__(self, name):
        return object.__getattribute__(self, name)

with which now

class A(ObjectProxyRaisingErrors):
    @property
    def error(self):
        raise ValueError("look here")
        
a = A(67)
a.error

will raise

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-42-563983c3078f> in <module>()
      1 a = A(67)
----> 2 a.error

<ipython-input-41-99a140beebe4> in __getattribute__(self, name)
      2 
      3     def __getattribute__(self, name):
----> 4         return object.__getattribute__(self, name)
      5 
      6 class A(ObjectProxyRaisingErrors):

<ipython-input-41-99a140beebe4> in error(self)
      8     @property
      9     def error(self):
---> 10         raise ValueError("look here")
     11 
     12 

ValueError: look here

which is ok. As far as I can see all the other ObjectProxy functionality is preserved.

schlichtanders avatar May 04 '17 13:05 schlichtanders

Will have to look at it when have time.

Overriding __getattribute__() in the proxy object in wrapt itself is not practical as it dramatically affects performance doing that.

Have you tried this with older Python versions?

GrahamDumpleton avatar May 04 '17 22:05 GrahamDumpleton

The error() wrapper function is actually being called, so somewhere in the implementation of the attribute lookup mechanism of Python, it is interpreting any exception raised in the property method as being an inability to lookup the attribute, rather than an error from the property method. It also only occurs when the C implementation of the wrapper class in wrapt is used. Doesn't occur when the pure Python implementation is used. Will need to dig further.

GrahamDumpleton avatar May 05 '17 00:05 GrahamDumpleton

Thanks for joining this thread. I only have Python 3.6 and in fact when looking at the python code of ObjectProxy it looked as if it should have worked.

How can I use the python version of ObjectProxy instead of the C implementation? I haven't known that there are these two options.

schlichtanders avatar May 05 '17 07:05 schlichtanders

Run:

pip uninstall wrapt
WRAPT_EXTENSIONS=false pip install wrapt

IOW, when installing the module set the environment variable WRAPT_EXTENSIONS to false.

GrahamDumpleton avatar May 05 '17 08:05 GrahamDumpleton

thanks a lot!

schlichtanders avatar May 05 '17 09:05 schlichtanders

I think this difference with the C extension compared to pure Python implementation may finally be addressed by change going into version 1.15.0. The change was quite simple so looks like I might have really screwed up somewhere along the way as far as not understanding something properly and then going with a wrong assumption for so long. :-(

GrahamDumpleton avatar Jan 11 '23 23:01 GrahamDumpleton