Skip to content

Commit

Permalink
Merge pull request numpy#18999 from seberg/raise-futurewarning-string…
Browse files Browse the repository at this point in the history
…-promotion

DEP: Ensure the string promotion FutureWarning is raised
  • Loading branch information
mattip authored May 16, 2021
2 parents 4caf8e7 + 1a828f5 commit 7b4a60f
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 19 deletions.
8 changes: 4 additions & 4 deletions doc/release/upcoming_changes/18116.future.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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::

Expand All @@ -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.
8 changes: 6 additions & 2 deletions numpy/core/src/multiarray/array_coercion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 1 addition & 4 deletions numpy/core/tests/test_deprecations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1121,10 +1121,7 @@ def test_deprecated(self, dtype, string_dt):
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"])
Expand Down
16 changes: 8 additions & 8 deletions numpy/core/tests/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,8 @@ def test_swap_real(self):
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
Expand Down Expand Up @@ -2052,18 +2052,18 @@ def test_search_sorted_invalid_arguments(self):

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):
Expand Down
2 changes: 1 addition & 1 deletion numpy/ma/tests/test_mrecords.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ def test_fromarrays(self):
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):
Expand Down

0 comments on commit 7b4a60f

Please sign in to comment.