Skip to content

Commit

Permalink
Merge pull request numpy#21231 from seberg/array-prio
Browse files Browse the repository at this point in the history
BUG: Catch error if array-priority is not float compatible
  • Loading branch information
mattip authored Mar 24, 2022
2 parents c9689ca + e8e2ea0 commit 2c89e15
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
8 changes: 7 additions & 1 deletion numpy/core/src/multiarray/multiarraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,18 @@ PyArray_GetPriority(PyObject *obj, double default_)
ret = PyArray_LookupSpecial_OnInstance(obj, "__array_priority__");
if (ret == NULL) {
if (PyErr_Occurred()) {
PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
/* TODO[gh-14801]: propagate crashes during attribute access? */
PyErr_Clear();
}
return default_;
}

priority = PyFloat_AsDouble(ret);
if (error_converting(priority)) {
/* TODO[gh-14801]: propagate crashes for bad priority? */
PyErr_Clear();
return default_;
}
Py_DECREF(ret);
return priority;
}
Expand Down
26 changes: 26 additions & 0 deletions numpy/core/tests/test_multiarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -3694,6 +3694,32 @@ def first_out_arg(result):
check(make_obj(np.ndarray, array_ufunc=None), True, False, False,
check_scalar=False)

@pytest.mark.parametrize("priority", [None, "runtime error"])
def test_ufunc_binop_bad_array_priority(self, priority):
# Mainly checks that this does not crash. The second array has a lower
# priority than -1 ("error value"). If the __radd__ actually exists,
# bad things can happen (I think via the scalar paths).
# In principle both of these can probably just be errors in the future.
class BadPriority:
@property
def __array_priority__(self):
if priority == "runtime error":
raise RuntimeError("RuntimeError in __array_priority__!")
return priority

def __radd__(self, other):
return "result"

class LowPriority(np.ndarray):
__array_priority__ = -1000

# Priority failure uses the same as scalars (smaller -1000). So the
# LowPriority wins with 'result' for each element (inner operation).
res = np.arange(3).view(LowPriority) + BadPriority()
assert res.shape == (3,)
assert res[0] == 'result'


def test_ufunc_override_normalize_signature(self):
# gh-5674
class SomeClass:
Expand Down

0 comments on commit 2c89e15

Please sign in to comment.