Skip to content

Commit 0d36673

Browse files
authored
Merge pull request #24128 from charris/backport-24103
BUG: Only replace dtype temporarily if dimensions changed
2 parents f5012c7 + b36db1c commit 0d36673

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

numpy/core/src/multiarray/ctors.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,8 +1695,10 @@ PyArray_FromAny_int(PyObject *op, PyArray_Descr *in_descr,
16951695
/* Decrease the number of dimensions to the detected ones */
16961696
int out_ndim = PyArray_NDIM(ret);
16971697
PyArray_Descr *out_descr = PyArray_DESCR(ret);
1698-
((PyArrayObject_fields *)ret)->nd = ndim;
1699-
((PyArrayObject_fields *)ret)->descr = dtype;
1698+
if (out_ndim != ndim) {
1699+
((PyArrayObject_fields *)ret)->nd = ndim;
1700+
((PyArrayObject_fields *)ret)->descr = dtype;
1701+
}
17001702

17011703
int success = PyArray_AssignFromCache(ret, cache);
17021704

@@ -1929,8 +1931,10 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
19291931

19301932
int actual_ndim = PyArray_NDIM(ret);
19311933
PyArray_Descr *actual_dtype = PyArray_DESCR(ret);
1932-
((PyArrayObject_fields *)ret)->nd = PyArray_NDIM(arr);
1933-
((PyArrayObject_fields *)ret)->descr = newtype;
1934+
if (actual_ndim != PyArray_NDIM(arr)) {
1935+
((PyArrayObject_fields *)ret)->nd = PyArray_NDIM(arr);
1936+
((PyArrayObject_fields *)ret)->descr = newtype;
1937+
}
19341938

19351939
int success = PyArray_CopyInto(ret, arr);
19361940

numpy/core/src/multiarray/methods.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -936,9 +936,10 @@ array_astype(PyArrayObject *self,
936936
/* Decrease the number of dimensions removing subarray ones again */
937937
int out_ndim = PyArray_NDIM(ret);
938938
PyArray_Descr *out_descr = PyArray_DESCR(ret);
939-
((PyArrayObject_fields *)ret)->nd = PyArray_NDIM(self);
940-
((PyArrayObject_fields *)ret)->descr = dtype;
941-
939+
if (out_ndim != PyArray_NDIM(self)) {
940+
((PyArrayObject_fields *)ret)->nd = PyArray_NDIM(self);
941+
((PyArrayObject_fields *)ret)->descr = dtype;
942+
}
942943
int success = PyArray_CopyInto(ret, self);
943944

944945
Py_DECREF(dtype);

numpy/core/tests/test_array_coercion.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,3 +870,29 @@ def test_subarray_from_array_construction():
870870

871871
res = np.array(arr, dtype="(2,2)f")
872872
assert_array_equal(res, expected)
873+
874+
875+
def test_empty_string():
876+
# Empty strings are unfortunately often converted to S1 and we need to
877+
# make sure we are filling the S1 and not the (possibly) detected S0
878+
# result. This should likely just return S0 and if not maybe the decision
879+
# to return S1 should be moved.
880+
res = np.array([""] * 10, dtype="S")
881+
assert_array_equal(res, np.array("\0", "S1"))
882+
assert res.dtype == "S1"
883+
884+
arr = np.array([""] * 10, dtype=object)
885+
886+
res = arr.astype("S")
887+
assert_array_equal(res, b"")
888+
assert res.dtype == "S1"
889+
890+
res = np.array(arr, dtype="S")
891+
assert_array_equal(res, b"")
892+
# TODO: This is arguably weird/wrong, but seems old:
893+
assert res.dtype == f"S{np.dtype('O').itemsize}"
894+
895+
res = np.array([[""] * 10, arr], dtype="S")
896+
assert_array_equal(res, b"")
897+
assert res.shape == (2, 10)
898+
assert res.dtype == "S1"

0 commit comments

Comments
 (0)