Skip to content

Commit

Permalink
BUG: Keep ignoring most errors during array-protocol lookup
Browse files Browse the repository at this point in the history
Closes (the later point) in numpygh-17965 and reverts parts of
numpygh-17817.
Shapely did rely on being able to raise a NotImplementedError
which then got ignored in the attribute lookup.
Arguably, this should probably just raise an AttributeError to
achieve that behaviour, but it means we can't just rip the band-aid
off here.

Since 1.20 is practically released, just reverting most of the change
(leaving only recursion and memory error which are both arguably
pretty fatal).
Ignoring most errors should be deprecated (and I am happy to do so),
but it is not important enough for 1.20 or very important in itself.

Closes numpygh-17965
  • Loading branch information
seberg authored and charris committed Jan 21, 2021
1 parent 9a84109 commit dff151e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
19 changes: 17 additions & 2 deletions numpy/core/src/multiarray/ctors.c
Expand Up @@ -2124,7 +2124,16 @@ PyArray_FromInterface(PyObject *origin)

if (iface == NULL) {
if (PyErr_Occurred()) {
return NULL;
if (PyErr_ExceptionMatches(PyExc_RecursionError) ||
PyErr_ExceptionMatches(PyExc_MemoryError)) {
/* RecursionError and MemoryError are considered fatal */
return NULL;
}
/*
* This probably be deprecated, but at least shapely raised
* a NotImplementedError expecting it to be cleared (gh-17965)
*/
PyErr_Clear();
}
return Py_NotImplemented;
}
Expand Down Expand Up @@ -2392,7 +2401,13 @@ PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context)
array_meth = PyArray_LookupSpecial_OnInstance(op, "__array__");
if (array_meth == NULL) {
if (PyErr_Occurred()) {
return NULL;
if (PyErr_ExceptionMatches(PyExc_RecursionError) ||
PyErr_ExceptionMatches(PyExc_MemoryError)) {
/* RecursionError and MemoryError are considered fatal */
return NULL;
}
/* This probably be deprecated. */
PyErr_Clear();
}
return Py_NotImplemented;
}
Expand Down
12 changes: 7 additions & 5 deletions numpy/core/tests/test_array_coercion.py
Expand Up @@ -702,17 +702,19 @@ def test_too_large_array_error_paths(self):

@pytest.mark.parametrize("attribute",
["__array_interface__", "__array__", "__array_struct__"])
def test_bad_array_like_attributes(self, attribute):
# Check that errors during attribute retrieval are raised unless
# they are Attribute errors.
@pytest.mark.parametrize("error", [RecursionError, MemoryError])
def test_bad_array_like_attributes(self, attribute, error):
# RecursionError and MemoryError are considered fatal. All errors
# (except AttributeError) should probably be raised in the future,
# but shapely made use of it, so it will require a deprecation.

class BadInterface:
def __getattr__(self, attr):
if attr == attribute:
raise RuntimeError
raise error
super().__getattr__(attr)

with pytest.raises(RuntimeError):
with pytest.raises(error):
np.array(BadInterface())

@pytest.mark.parametrize("error", [RecursionError, MemoryError])
Expand Down

0 comments on commit dff151e

Please sign in to comment.