summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorSebastian Berg <sebastian@sipsolutions.net>2022-11-07 23:42:32 +0100
committerGitHub <noreply@github.com>2022-11-07 14:42:32 -0800
commit10908c5fd147572c9ea02cef0c0d5eae6892e4cb (patch)
tree861eba0392c5fd08a7f955872702c7f19740bdc3 /numpy
parent93991066060a2f7384ecc7992e145a56899d81b0 (diff)
downloadnumpy-10908c5fd147572c9ea02cef0c0d5eae6892e4cb.tar.gz
DEP: Expire deprecation to ignore bad dtype= in logical ufuncs (#22541)
* DEP: Expire deprecation to ignore bad dtype= in logical ufuncs Basically only `bool` and `object dtype make sense, but they did not work correctly. The dtype argument was rather ignored often. The offending behavior was deprecated in 1.20 and is now removed. Co-authored-by: Sebastian Berg <sebastianb@nvidia.com> Co-authored-by: Charles Harris <charlesr.harris@gmail.com>
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/umath/dispatching.c16
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.c50
-rw-r--r--numpy/core/tests/test_deprecations.py25
-rw-r--r--numpy/core/tests/test_umath.py19
4 files changed, 23 insertions, 87 deletions
diff --git a/numpy/core/src/umath/dispatching.c b/numpy/core/src/umath/dispatching.c
index 79de6c3c8..077d56f33 100644
--- a/numpy/core/src/umath/dispatching.c
+++ b/numpy/core/src/umath/dispatching.c
@@ -667,12 +667,9 @@ legacy_promote_using_legacy_type_resolver(PyUFuncObject *ufunc,
Py_DECREF(out_descrs[i]);
}
/*
- * The PyUFunc_SimpleBinaryComparisonTypeResolver has a deprecation
- * warning (ignoring `dtype=`) and cannot be cached.
- * All datetime ones *should* have a warning, but currently don't,
- * but ignore all signature passing also. So they can also
- * not be cached, and they mutate the signature which of course is wrong,
- * but not doing it would confuse the code later.
+ * datetime legacy resolvers ignore the signature, which should be
+ * warn/raise (when used). In such cases, the signature is (incorrectly)
+ * mutated, and caching is not possible.
*/
for (int i = 0; i < nargs; i++) {
if (signature[i] != NULL && signature[i] != operation_DTypes[i]) {
@@ -1042,13 +1039,6 @@ default_ufunc_promoter(PyUFuncObject *ufunc,
PyArray_DTypeMeta *op_dtypes[], PyArray_DTypeMeta *signature[],
PyArray_DTypeMeta *new_op_dtypes[])
{
- if (ufunc->type_resolver == &PyUFunc_SimpleBinaryComparisonTypeResolver
- && signature[0] == NULL && signature[1] == NULL
- && signature[2] != NULL && signature[2]->type_num != NPY_BOOL) {
- /* bail out, this is _only_ to give future/deprecation warning! */
- return -1;
- }
-
/* If nin < 2 promotion is a no-op, so it should not be registered */
assert(ufunc->nin > 1);
if (op_dtypes[0] == NULL) {
diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c
index 94338e031..855ad3913 100644
--- a/numpy/core/src/umath/ufunc_type_resolution.c
+++ b/numpy/core/src/umath/ufunc_type_resolution.c
@@ -382,53 +382,9 @@ PyUFunc_SimpleBinaryComparisonTypeResolver(PyUFuncObject *ufunc,
}
}
else {
- PyArray_Descr *descr;
- /*
- * DEPRECATED 2021-03, NumPy 1.20
- *
- * If the type tuple was originally a single element (probably),
- * issue a deprecation warning, but otherwise accept it. Since the
- * result dtype is always boolean, this is not actually valid unless it
- * is `object` (but if there is an object input we already deferred).
- *
- * TODO: Once this deprecation is gone, the special case for
- * `PyUFunc_SimpleBinaryComparisonTypeResolver` in dispatching.c
- * can be removed.
- */
- if (PyTuple_Check(type_tup) && PyTuple_GET_SIZE(type_tup) == 3 &&
- PyTuple_GET_ITEM(type_tup, 0) == Py_None &&
- PyTuple_GET_ITEM(type_tup, 1) == Py_None &&
- PyArray_DescrCheck(PyTuple_GET_ITEM(type_tup, 2))) {
- descr = (PyArray_Descr *)PyTuple_GET_ITEM(type_tup, 2);
- if (descr->type_num == NPY_OBJECT) {
- if (DEPRECATE_FUTUREWARNING(
- "using `dtype=object` (or equivalent signature) will "
- "return object arrays in the future also when the "
- "inputs do not already have `object` dtype.") < 0) {
- return -1;
- }
- }
- else if (descr->type_num != NPY_BOOL) {
- if (DEPRECATE(
- "using `dtype=` in comparisons is only useful for "
- "`dtype=object` (and will do nothing for bool). "
- "This operation will fail in the future.") < 0) {
- return -1;
- }
- }
- }
- else {
- /* Usually a failure, but let the default version handle it */
- return PyUFunc_DefaultTypeResolver(ufunc, casting,
- operands, type_tup, out_dtypes);
- }
-
- out_dtypes[0] = NPY_DT_CALL_ensure_canonical(descr);
- if (out_dtypes[0] == NULL) {
- return -1;
- }
- out_dtypes[1] = out_dtypes[0];
- Py_INCREF(out_dtypes[1]);
+ /* Usually a failure, but let the default version handle it */
+ return PyUFunc_DefaultTypeResolver(ufunc, casting,
+ operands, type_tup, out_dtypes);
}
/* Output type is always boolean */
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index e09ec27b9..b808ffc8d 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -1000,31 +1000,6 @@ class TestSingleElementSignature(_DeprecationTestCase):
self.assert_deprecated(lambda: np.add(1, 2, sig=(np.dtype("l"),)))
-class TestComparisonBadDType(_DeprecationTestCase):
- # Deprecated 2021-04-01, NumPy 1.21
- message = r"using `dtype=` in comparisons is only useful for"
-
- def test_deprecated(self):
- self.assert_deprecated(lambda: np.equal(1, 1, dtype=np.int64))
- # Not an error only for the transition
- self.assert_deprecated(lambda: np.equal(1, 1, sig=(None, None, "l")))
-
- def test_not_deprecated(self):
- np.equal(True, False, dtype=bool)
- np.equal(3, 5, dtype=bool, casting="unsafe")
- np.equal([None], [4], dtype=object)
-
-class TestComparisonBadObjectDType(_DeprecationTestCase):
- # Deprecated 2021-04-01, NumPy 1.21 (different branch of the above one)
- message = r"using `dtype=object` \(or equivalent signature\) will"
- warning_cls = FutureWarning
-
- def test_deprecated(self):
- self.assert_deprecated(lambda: np.equal(1, 1, dtype=object))
- self.assert_deprecated(
- lambda: np.equal(1, 1, sig=(None, None, object)))
-
-
class TestCtypesGetter(_DeprecationTestCase):
# Deprecated 2021-05-18, Numpy 1.21.0
warning_cls = DeprecationWarning
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index e2e95ec69..d98eca792 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -338,6 +338,21 @@ class TestComparisons:
assert_equal(np.equal.reduce(a, dtype=bool), True)
assert_raises(TypeError, np.equal.reduce, a)
+ def test_object_dtype(self):
+ assert np.equal(1, [1], dtype=object).dtype == object
+ assert np.equal(1, [1], signature=(None, None, "O")).dtype == object
+
+ def test_object_nonbool_dtype_error(self):
+ # bool output dtype is fine of course:
+ assert np.equal(1, [1], dtype=bool).dtype == bool
+
+ # but the following are examples do not have a loop:
+ with pytest.raises(TypeError, match="No loop matching"):
+ np.equal(1, 1, dtype=np.int64)
+
+ with pytest.raises(TypeError, match="No loop matching"):
+ np.equal(1, 1, sig=(None, None, "l"))
+
class TestAdd:
def test_reduce_alignment(self):
@@ -1095,7 +1110,7 @@ class TestPower:
assert_raises(ValueError, np.power, a, minusone)
assert_raises(ValueError, np.power, one, b)
assert_raises(ValueError, np.power, one, minusone)
-
+
def test_float_to_inf_power(self):
for dt in [np.float32, np.float64]:
a = np.array([1, 1, 2, 2, -2, -2, np.inf, -np.inf], dt)
@@ -1348,7 +1363,7 @@ class TestSpecialFloats:
yf = np.array(y, dtype=dt)
assert_equal(np.sin(yf), xf)
assert_equal(np.cos(yf), xf)
-
+
with np.errstate(invalid='raise'):
for callable in [np.sin, np.cos]: