summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorMatti Picus <matti.picus@gmail.com>2019-06-06 09:26:03 +0300
committerGitHub <noreply@github.com>2019-06-06 09:26:03 +0300
commit07c625cedd18d817b0941e39b4fe6a13caf034a1 (patch)
tree162f13efc33f827db869ddd5a9c25638c8a47a92 /numpy
parentd429f0fe16c0407509b1f20d997bf94f1027f61b (diff)
parent2a1b2e5ed87a9dcf39342c394f815ccfbc93b7bd (diff)
downloadnumpy-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.py16
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.c42
-rw-r--r--numpy/core/tests/test_datetime.py2
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):