diff options
author | Sebastian Berg <sebastian@sipsolutions.net> | 2021-06-29 13:06:20 -0500 |
---|---|---|
committer | Sebastian Berg <sebastian@sipsolutions.net> | 2021-06-29 13:07:57 -0500 |
commit | c434db2f8934c60bc8e41f71962f94d06d2adc3e (patch) | |
tree | af598e54c2a74d001a8c754722d16b9b8dd01d30 /numpy/core | |
parent | 2f0ed6acea1308c89e6c814b1317d96362370703 (diff) | |
download | numpy-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.c | 4 | ||||
-rw-r--r-- | numpy/core/tests/test_casting_unittests.py | 17 |
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)) |