diff options
Diffstat (limited to 'numpy/core')
-rw-r--r-- | numpy/core/setup.py | 4 | ||||
-rw-r--r-- | numpy/core/src/multiarray/convert_datatype.c | 23 | ||||
-rw-r--r-- | numpy/core/tests/test_casting_unittests.py | 17 |
3 files changed, 30 insertions, 14 deletions
diff --git a/numpy/core/setup.py b/numpy/core/setup.py index 08510fcc8..2b7566c0a 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -24,9 +24,9 @@ NPY_RELAXED_STRIDES_DEBUG = (os.environ.get('NPY_RELAXED_STRIDES_DEBUG', "0") != NPY_RELAXED_STRIDES_DEBUG = NPY_RELAXED_STRIDES_DEBUG and NPY_RELAXED_STRIDES_CHECKING # Set to True to use the new casting implementation as much as implemented. -# Allows running the full test suit to excercise the new machinery until +# Allows running the full test suit to exercise the new machinery until # it is used as default and the old version is eventually deleted. -NPY_USE_NEW_CASTINGIMPL = os.environ.get('NPY_USE_NEW_CASTINGIMPL', "0") != 0 +NPY_USE_NEW_CASTINGIMPL = os.environ.get('NPY_USE_NEW_CASTINGIMPL', "1") != "0" # XXX: ugly, we use a class to avoid calling twice some expensive functions in # config.h/numpyconfig.h. I don't see a better way because distutils force diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c index a9e9051af..4758302cf 100644 --- a/numpy/core/src/multiarray/convert_datatype.c +++ b/numpy/core/src/multiarray/convert_datatype.c @@ -420,12 +420,12 @@ PyArray_CanCastSafely(int fromtype, int totype) #if NPY_USE_NEW_CASTINGIMPL PyArray_DTypeMeta *from = PyArray_DTypeFromTypeNum(fromtype); if (from == NULL) { - PyErr_WriteUnraisable(Py_None); + PyErr_WriteUnraisable(NULL); return 0; } PyArray_DTypeMeta *to = PyArray_DTypeFromTypeNum(totype); if (to == NULL) { - PyErr_WriteUnraisable(Py_None); + PyErr_WriteUnraisable(NULL); return 0; } PyObject *castingimpl = PyArray_GetCastingImpl(from, to); @@ -433,7 +433,7 @@ PyArray_CanCastSafely(int fromtype, int totype) Py_DECREF(to); if (castingimpl == NULL) { - PyErr_WriteUnraisable(Py_None); + PyErr_WriteUnraisable(NULL); return 0; } else if (castingimpl == Py_None) { @@ -2489,9 +2489,9 @@ structured_to_nonstructured_resolve_descriptors( if (given_descrs[1] == NULL) { loop_descrs[1] = dtypes[1]->default_descr(dtypes[1]); /* - * Special case strings here, this is probably unnecessary and - * should be useless (i.e. it is necessary to use empty arrays to - * trigger this path.). + * Special case strings here, it should be useless (and only actually + * work for empty arrays). Possibly this should simply raise for + * all parametric DTypes. */ if (dtypes[1]->type_num == NPY_STRING) { loop_descrs[1]->elsize = given_descrs[0]->elsize; @@ -2744,7 +2744,7 @@ object_to_any_resolve_descriptors( * here is that e.g. "M8" input is considered to be the DType class, * and by allowing it here, we go back to the "M8" instance. */ - if (dtypes[1]->parametric && !dtypes[1]->legacy) { + if (dtypes[1]->parametric) { PyErr_Format(PyExc_TypeError, "casting from object to the parametric DType %S requires " "the specified output dtype instance. " @@ -2756,11 +2756,6 @@ object_to_any_resolve_descriptors( if (loop_descrs[1] == NULL) { return -1; } - if (dtypes[1]->type_num == NPY_VOID) { - /* NOTE: This appears to be behaviour as of 1.19 (void is not - * adjusted) */ - loop_descrs[1]->elsize = sizeof(PyObject *); - } } else { Py_INCREF(given_descrs[1]); @@ -2791,6 +2786,8 @@ PyArray_GetObjectToGenericCastingImpl() return PyErr_NoMemory(); } + method->nin = 1; + method->nout = 1; method->name = "object_to_any_cast"; method->flags = NPY_METH_SUPPORTS_UNALIGNED | NPY_METH_REQUIRES_PYAPI; method->casting = NPY_UNSAFE_CASTING; @@ -2845,6 +2842,8 @@ PyArray_GetGenericToObjectCastingImpl() return PyErr_NoMemory(); } + method->nin = 1; + method->nout = 1; method->name = "any_to_object_cast"; method->flags = NPY_METH_SUPPORTS_UNALIGNED | NPY_METH_REQUIRES_PYAPI; method->casting = NPY_SAFE_CASTING; diff --git a/numpy/core/tests/test_casting_unittests.py b/numpy/core/tests/test_casting_unittests.py index 2f82d718b..fec0ae7c7 100644 --- a/numpy/core/tests/test_casting_unittests.py +++ b/numpy/core/tests/test_casting_unittests.py @@ -282,3 +282,20 @@ class TestCasting: assert safety == expected_safety elif change_length > 0: assert safety == Casting.safe + + def test_void_to_string_special_case(self): + # Cover a small special case in void to string casting that could + # probably just as well be turned into an error (compare + # `test_object_to_parametric_internal_error` below). + assert np.array([], dtype="V5").astype("S").dtype.itemsize == 5 + assert np.array([], dtype="V5").astype("U").dtype.itemsize == 4 * 5 + + def test_object_to_parametric_internal_error(self): + # We reject casting from object to a parametric type, without + # figuring out the correct instance first. + object_dtype = type(np.dtype(object)) + other_dtype = type(np.dtype(str)) + cast = get_castingimpl(object_dtype, other_dtype) + with pytest.raises(TypeError, + match="casting from object to the parametric DType"): + cast._resolve_descriptors((np.dtype("O"), None)) |