diff options
author | Matti Picus <matti.picus@gmail.com> | 2019-06-06 09:26:03 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-06 09:26:03 +0300 |
commit | 07c625cedd18d817b0941e39b4fe6a13caf034a1 (patch) | |
tree | 162f13efc33f827db869ddd5a9c25638c8a47a92 /numpy | |
parent | d429f0fe16c0407509b1f20d997bf94f1027f61b (diff) | |
parent | 2a1b2e5ed87a9dcf39342c394f815ccfbc93b7bd (diff) | |
download | numpy-07c625cedd18d817b0941e39b4fe6a13caf034a1.tar.gz |
Merge pull request #13721 from eric-wieser/more_ufunc_exception_cleanup
MAINT,BUG: More ufunc exception cleanup
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/_exceptions.py | 16 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_type_resolution.c | 42 | ||||
-rw-r--r-- | numpy/core/tests/test_datetime.py | 2 |
3 files changed, 43 insertions, 17 deletions
diff --git a/numpy/core/_exceptions.py b/numpy/core/_exceptions.py index 1dcea6255..a1af7a78d 100644 --- a/numpy/core/_exceptions.py +++ b/numpy/core/_exceptions.py @@ -37,6 +37,22 @@ class UFuncTypeError(TypeError): @_display_as_base +class _UFuncBinaryResolutionError(UFuncTypeError): + """ Thrown when a binary resolution fails """ + def __init__(self, ufunc, dtypes): + super().__init__(ufunc) + self.dtypes = tuple(dtypes) + assert len(self.dtypes) == 2 + + def __str__(self): + return ( + "ufunc {!r} cannot use operands with types {!r} and {!r}" + ).format( + self.ufunc.__name__, *self.dtypes + ) + + +@_display_as_base class _UFuncNoLoopError(UFuncTypeError): """ Thrown when a ufunc loop cannot be found """ def __init__(self, ufunc, dtypes): diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c index 96591ba80..58f915c6e 100644 --- a/numpy/core/src/umath/ufunc_type_resolution.c +++ b/numpy/core/src/umath/ufunc_type_resolution.c @@ -74,18 +74,28 @@ npy_casting_to_string(NPY_CASTING casting) */ static int raise_binary_type_reso_error(PyUFuncObject *ufunc, PyArrayObject **operands) { - PyObject *errmsg; - const char *ufunc_name = ufunc_get_name_cstr(ufunc); - errmsg = PyUString_FromFormat("ufunc %s cannot use operands " - "with types ", ufunc_name); - PyUString_ConcatAndDel(&errmsg, - PyObject_Repr((PyObject *)PyArray_DESCR(operands[0]))); - PyUString_ConcatAndDel(&errmsg, - PyUString_FromString(" and ")); - PyUString_ConcatAndDel(&errmsg, - PyObject_Repr((PyObject *)PyArray_DESCR(operands[1]))); - PyErr_SetObject(PyExc_TypeError, errmsg); - Py_DECREF(errmsg); + static PyObject *exc_type = NULL; + PyObject *exc_value; + + npy_cache_import( + "numpy.core._exceptions", "_UFuncBinaryResolutionError", + &exc_type); + if (exc_type == NULL) { + return -1; + } + + /* produce an error object */ + exc_value = Py_BuildValue( + "O(OO)", ufunc, + (PyObject *)PyArray_DESCR(operands[0]), + (PyObject *)PyArray_DESCR(operands[1]) + ); + if (exc_value == NULL){ + return -1; + } + PyErr_SetObject(exc_type, exc_value); + Py_DECREF(exc_value); + return -1; } @@ -94,7 +104,7 @@ raise_binary_type_reso_error(PyUFuncObject *ufunc, PyArrayObject **operands) { */ static int raise_no_loop_found_error( - PyUFuncObject *ufunc, PyArray_Descr **dtypes, npy_intp n_dtypes) + PyUFuncObject *ufunc, PyArray_Descr **dtypes) { static PyObject *exc_type = NULL; PyObject *exc_value; @@ -109,11 +119,11 @@ raise_no_loop_found_error( } /* convert dtypes to a tuple */ - dtypes_tup = PyTuple_New(n_dtypes); + dtypes_tup = PyTuple_New(ufunc->nargs); if (dtypes_tup == NULL) { return -1; } - for (i = 0; i < n_dtypes; ++i) { + for (i = 0; i < ufunc->nargs; ++i) { Py_INCREF(dtypes[i]); PyTuple_SET_ITEM(dtypes_tup, i, (PyObject *)dtypes[i]); } @@ -1472,7 +1482,7 @@ PyUFunc_DefaultLegacyInnerLoopSelector(PyUFuncObject *ufunc, types += nargs; } - return raise_no_loop_found_error(ufunc, dtypes, nargs); + return raise_no_loop_found_error(ufunc, dtypes); } typedef struct { diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index f48bfdf9b..f99c0f72b 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -1825,7 +1825,7 @@ class TestDateTime(object): # NOTE: some of the operations may be supported # in the future with assert_raises_regex(TypeError, - "remainder cannot use operands with types"): + "'remainder' cannot use operands with types"): val1 % val2 def test_timedelta_arange_no_dtype(self): |