`getattr(pyvips.Image, anything)` returns `True` when it should raise `AttributeError`
See original GitHub issueI’m working on making it more convenient to work with pyvips images with numpy. Numpy offers a way for foreign objects to be interpreted as arrays: a class need only define the __array__
method, whereupon np.array(im)
will call this. This is how Pillow does it, for example.
The problem is that if I define this __array__
method on pyvips.Image
, it never gets called because numpy has some complex behavior where it looks for the most efficient ways to turn something into an array (without copying, e.g.), so it first looks up __array_struct__
to attempt C-struct access and then falls back to trying other things (see The Array Interface). Ok, no problem except that the way pyvips is setup, when numpy goes looking for __array_struct__
, it can’t see that it doesn’t exist because of this behavior:
import pyvips
print(hasattr(pyvips.Image, 'doesntexist'))
# True # (wat)
So I guess somehow due to the way it interfaces with libvips, pyvips is deferring method resolution until it’s actually called, but by then it’s too late for numpy to figure out that it should have used __array__
instead.
im = pyvips.Image.black(4, 4)
ai = im.__array_interface__ # The bug is here. Should raise AttributeError immediately but doesn't.
print('Ready to call')
ai() # the **call** is what raises, but not AttributeError
# Ready to call
# Error: no such operation __array_interface__
# VipsOperation: class "__array_interface__" not found
I think this is a bug insofar as it violates the usual semantics of how to deal with presence of methods, etc. As the Python documentation says, hasattr
… is implemented by calling getattr(object, name) and seeing whether it raises an AttributeError or not.
If you have any ideas on how to fix this, I’m happy to give it a try, though the various ways that pyvips interfaces with libvips is sort of “here be dragons” territory for me so I doubt I’d be very useful.
Thanks in advance!
Issue Analytics
- State:
- Created a year ago
- Comments:6 (6 by maintainers)
Top GitHub Comments
Yes, that sounds extremely useful!
I added
toarray()
a short while ago, but it’s terrible. A bettertoarray()
method would be great too.Ok, #316 adds functionality to go to/from numpy and array-like things, and also provides an efficient implementation of what is now called
.tolist()
to turn single-band images of any type into lists of lists. Thanks for the help in getting this in!