summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorSebastian Berg <sebastian@sipsolutions.net>2021-06-29 13:06:20 -0500
committerSebastian Berg <sebastian@sipsolutions.net>2021-06-29 13:07:57 -0500
commitc434db2f8934c60bc8e41f71962f94d06d2adc3e (patch)
treeaf598e54c2a74d001a8c754722d16b9b8dd01d30 /numpy/core
parent2f0ed6acea1308c89e6c814b1317d96362370703 (diff)
downloadnumpy-c434db2f8934c60bc8e41f71962f94d06d2adc3e.tar.gz
BUG: Fix NULL special case in object-to-any cast code
Apparently `np.empty_like` is an easy way to create NULL filled object arrays. In general, it is not typical, which explains how this case could have managed to not be found by our tests or downstream tests. Closes gh-19373
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/src/multiarray/dtype_transfer.c4
-rw-r--r--numpy/core/tests/test_casting_unittests.py17
2 files changed, 19 insertions, 2 deletions
diff --git a/numpy/core/src/multiarray/dtype_transfer.c b/numpy/core/src/multiarray/dtype_transfer.c
index aa8cc84ff..50db627ea 100644
--- a/numpy/core/src/multiarray/dtype_transfer.c
+++ b/numpy/core/src/multiarray/dtype_transfer.c
@@ -322,11 +322,11 @@ strided_to_strided_object_to_any(
while (N > 0) {
memcpy(&src_ref, src, sizeof(src_ref));
- if (PyArray_Pack(data->descr, dst, src_ref) < 0) {
+ if (PyArray_Pack(data->descr, dst, src_ref ? src_ref : Py_None) < 0) {
return -1;
}
- if (data->move_references) {
+ if (data->move_references && src_ref != NULL) {
Py_DECREF(src_ref);
memset(src, 0, sizeof(src_ref));
}
diff --git a/numpy/core/tests/test_casting_unittests.py b/numpy/core/tests/test_casting_unittests.py
index 1c465fea1..8398b3cad 100644
--- a/numpy/core/tests/test_casting_unittests.py
+++ b/numpy/core/tests/test_casting_unittests.py
@@ -657,3 +657,20 @@ class TestCasting:
expected = casting == "unsafe"
assert np.can_cast("V4", dtype, casting=casting) == expected
assert np.can_cast(dtype, "V4", casting=casting) == expected
+
+ @pytest.mark.parametrize("dtype", np.typecodes["All"])
+ def test_object_casts_NULL_None_equivalence(self, dtype):
+ # None to <other> casts may succeed or fail, but a NULL'ed array must
+ # behave the same as one filled with None's.
+ arr_normal = np.array([None] * 5)
+ arr_NULLs = np.empty_like([None] * 5)
+ # If the check fails (maybe it should) the test would lose its purpose:
+ assert arr_NULLs.tobytes() == b"\x00" * arr_NULLs.nbytes
+
+ try:
+ expected = arr_normal.astype(dtype)
+ except TypeError:
+ with pytest.raises(TypeError):
+ arr_NULLs.astype(dtype)
+ else:
+ assert_array_equal(expected, arr_NULLs.astype(dtype))