summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Berg <sebastian@sipsolutions.net>2021-02-16 17:00:08 -0600
committerSebastian Berg <sebastian@sipsolutions.net>2021-05-12 16:05:03 -0700
commit1a828f525d2737bfe93e91034603bb2f4f3414db (patch)
treeeeba156a31f5afedde5ed2a7371b22d953c8f5cb
parent6f5ad737691433b39953663c904e9d330fa38332 (diff)
downloadnumpy-1a828f525d2737bfe93e91034603bb2f4f3414db.tar.gz
DEP: Ensure the string promotion FutureWarning is raised
Promotion errors are currently ignored and instead we use `object` as dtype. This means that the FutureWarning is ignored when raised. It also means that there is no way to opt into "future" behaviour, although arguably, we may want to force `dtype=object` in any case if a promotion error occurred (or some signal at least). Closes gh-18721 Addresses gh-18425 (Does not actually fix it, but chances are we won't)
-rw-r--r--doc/release/upcoming_changes/18116.future.rst8
-rw-r--r--numpy/core/src/multiarray/array_coercion.c8
-rw-r--r--numpy/core/tests/test_deprecations.py5
-rw-r--r--numpy/core/tests/test_regression.py16
-rw-r--r--numpy/ma/tests/test_mrecords.py2
5 files changed, 20 insertions, 19 deletions
diff --git a/doc/release/upcoming_changes/18116.future.rst b/doc/release/upcoming_changes/18116.future.rst
index 1341d022f..1eb14d5f7 100644
--- a/doc/release/upcoming_changes/18116.future.rst
+++ b/doc/release/upcoming_changes/18116.future.rst
@@ -11,9 +11,8 @@ are:
a string result.
* `numpy.array` and related functions will start returning ``object``
arrays because these functions use ``object`` as a fallback when
- no common dtype can be found. (In this case setting the
- ``FutureWarning`` to be raised will unfortunately lead to the new
- behaviour)
+ no common dtype can be found. However, it may happen that future
+ releases of NumPy will generally error in these cases.
This will mainly affect code such as::
@@ -24,6 +23,7 @@ and::
np.concatenate((['string'], [0]))
in both cases adding ``dtype="U"`` or ``dtype="S"`` will give the
-previous (string) result.
+previous (string) result, while ``dtype=object`` will ensure an array with
+object dtype is returned.
Comparisons, universal functions, and casting are not affected by this.
diff --git a/numpy/core/src/multiarray/array_coercion.c b/numpy/core/src/multiarray/array_coercion.c
index ef99ae479..6b7c3888d 100644
--- a/numpy/core/src/multiarray/array_coercion.c
+++ b/numpy/core/src/multiarray/array_coercion.c
@@ -622,8 +622,12 @@ handle_promotion(PyArray_Descr **out_descr, PyArray_Descr *descr,
}
PyArray_Descr *new_descr = PyArray_PromoteTypes(descr, *out_descr);
if (NPY_UNLIKELY(new_descr == NULL)) {
- if (fixed_DType != NULL) {
- /* If a DType is fixed, promotion must not fail. */
+ if (fixed_DType != NULL || PyErr_ExceptionMatches(PyExc_FutureWarning)) {
+ /*
+ * If a DType is fixed, promotion must not fail. Do not catch
+ * FutureWarning (raised for string+numeric promotions). We could
+ * only catch TypeError here or even always raise the error.
+ */
return -1;
}
PyErr_Clear();
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index ec4112e69..ed1688374 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -1121,10 +1121,7 @@ class TestStringPromotion(_DeprecationTestCase):
self.assert_deprecated(lambda: np.concatenate((arr1, arr2), axis=0))
self.assert_deprecated(lambda: np.concatenate((arr1, arr2), axis=None))
- # coercing to an array is similar, but will fall-back to `object`
- # (when raising the FutureWarning, this already happens)
- self.assert_deprecated(lambda: np.array([arr1[0], arr2[0]]),
- exceptions=())
+ self.assert_deprecated(lambda: np.array([arr1[0], arr2[0]]))
@pytest.mark.parametrize("dtype", "?bhilqpBHILQPefdgFDG")
@pytest.mark.parametrize("string_dt", ["S", "U"])
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index d1af7f1d8..25198bba9 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -503,8 +503,8 @@ class TestRegression:
assert_equal(np.arange(4, dtype='<c8').real.max(), 3.0)
def test_object_array_from_list(self):
- # Ticket #270
- assert_(np.array([1, 'A', None]).shape == (3,))
+ # Ticket #270 (gh-868)
+ assert_(np.array([1, None, 'A']).shape == (3,))
def test_multiple_assign(self):
# Ticket #273
@@ -2052,18 +2052,18 @@ class TestRegression:
def test_string_truncation(self):
# Ticket #1990 - Data can be truncated in creation of an array from a
- # mixed sequence of numeric values and strings
+ # mixed sequence of numeric values and strings (gh-2583)
for val in [True, 1234, 123.4, complex(1, 234)]:
- for tostr in [asunicode, asbytes]:
- b = np.array([val, tostr('xx')])
+ for tostr, dtype in [(asunicode, "U"), (asbytes, "S")]:
+ b = np.array([val, tostr('xx')], dtype=dtype)
assert_equal(tostr(b[0]), tostr(val))
- b = np.array([tostr('xx'), val])
+ b = np.array([tostr('xx'), val], dtype=dtype)
assert_equal(tostr(b[1]), tostr(val))
# test also with longer strings
- b = np.array([val, tostr('xxxxxxxxxx')])
+ b = np.array([val, tostr('xxxxxxxxxx')], dtype=dtype)
assert_equal(tostr(b[0]), tostr(val))
- b = np.array([tostr('xxxxxxxxxx'), val])
+ b = np.array([tostr('xxxxxxxxxx'), val], dtype=dtype)
assert_equal(tostr(b[1]), tostr(val))
def test_string_truncation_ucs2(self):
diff --git a/numpy/ma/tests/test_mrecords.py b/numpy/ma/tests/test_mrecords.py
index c2f859273..27df519d2 100644
--- a/numpy/ma/tests/test_mrecords.py
+++ b/numpy/ma/tests/test_mrecords.py
@@ -405,7 +405,7 @@ class TestMRecordsImport:
for (f, l) in zip(('a', 'b', 'c'), (_a, _b, _c)):
assert_equal(getattr(mrec, f)._mask, l._mask)
# One record only
- _x = ma.array([1, 1.1, 'one'], mask=[1, 0, 0],)
+ _x = ma.array([1, 1.1, 'one'], mask=[1, 0, 0], dtype=object)
assert_equal_records(fromarrays(_x, dtype=mrec.dtype), mrec[0])
def test_fromrecords(self):