diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/array_coercion.c | 47 | ||||
-rw-r--r-- | numpy/core/tests/test_array_coercion.py | 18 | ||||
-rw-r--r-- | numpy/core/tests/test_deprecations.py | 86 |
3 files changed, 13 insertions, 138 deletions
diff --git a/numpy/core/src/multiarray/array_coercion.c b/numpy/core/src/multiarray/array_coercion.c index d55a5752b..ba9118052 100644 --- a/numpy/core/src/multiarray/array_coercion.c +++ b/numpy/core/src/multiarray/array_coercion.c @@ -1025,53 +1025,6 @@ PyArray_DiscoverDTypeAndShape_Recursive( Py_DECREF(arr); arr = NULL; } - else if (curr_dims > 0 && curr_dims != max_dims) { - /* - * Deprecated 2020-12-09, NumPy 1.20 - * - * See https://github.com/numpy/numpy/issues/17965 - * Shapely had objects which are not sequences but did export - * the array-interface (and so are arguably array-like). - * Previously numpy would not use array-like information during - * shape discovery, so that it ended up acting as if this was - * an (unknown) scalar but with the specified dtype. - * Thus we ignore "scalars" here, as the value stored in the - * array should be acceptable. - */ - if (PyArray_NDIM(arr) > 0 && NPY_UNLIKELY(!PySequence_Check(obj))) { - if (PyErr_WarnFormat(PyExc_FutureWarning, 1, - "The input object of type '%s' is an array-like " - "implementing one of the corresponding protocols " - "(`__array__`, `__array_interface__` or " - "`__array_struct__`); but not a sequence (or 0-D). " - "In the future, this object will be coerced as if it " - "was first converted using `np.array(obj)`. " - "To retain the old behaviour, you have to either " - "modify the type '%s', or assign to an empty array " - "created with `np.empty(correct_shape, dtype=object)`.", - Py_TYPE(obj)->tp_name, Py_TYPE(obj)->tp_name) < 0) { - Py_DECREF(arr); - return -1; - } - /* - * Strangely enough, even though we threw away the result here, - * we did use it during descriptor discovery, so promote it: - */ - if (update_shape(curr_dims, &max_dims, out_shape, - 0, NULL, NPY_FALSE, flags) < 0) { - *flags |= FOUND_RAGGED_ARRAY; - Py_DECREF(arr); - return max_dims; - } - if (!(*flags & DESCRIPTOR_WAS_SET) && handle_promotion( - out_descr, PyArray_DESCR(arr), fixed_DType, flags) < 0) { - Py_DECREF(arr); - return -1; - } - Py_DECREF(arr); - return max_dims; - } - } } if (arr != NULL) { /* diff --git a/numpy/core/tests/test_array_coercion.py b/numpy/core/tests/test_array_coercion.py index aeddac585..baca076ae 100644 --- a/numpy/core/tests/test_array_coercion.py +++ b/numpy/core/tests/test_array_coercion.py @@ -39,9 +39,9 @@ def arraylikes(): yield subclass class _SequenceLike(): - # We are giving a warning that array-like's were also expected to be - # sequence-like in `np.array([array_like])`. This can be removed - # when the deprecation expired (started NumPy 1.20). + # Older NumPy versions, sometimes cared whether a protocol array was + # also _SequenceLike. This shouldn't matter, but keep it for now + # for __array__ and not the others. def __len__(self): raise TypeError @@ -62,7 +62,7 @@ def arraylikes(): yield param(memoryview, id="memoryview") # Array-interface - class ArrayInterface(_SequenceLike): + class ArrayInterface: def __init__(self, a): self.a = a # need to hold on to keep interface valid self.__array_interface__ = a.__array_interface__ @@ -70,7 +70,7 @@ def arraylikes(): yield param(ArrayInterface, id="__array_interface__") # Array-Struct - class ArrayStruct(_SequenceLike): + class ArrayStruct: def __init__(self, a): self.a = a # need to hold on to keep struct valid self.__array_struct__ = a.__array_struct__ @@ -654,6 +654,14 @@ class TestArrayLikes: res = np.array([obj], dtype=object) assert res[0] is obj + @pytest.mark.parametrize("arraylike", arraylikes()) + @pytest.mark.parametrize("arr", [np.array(0.), np.arange(4)]) + def test_object_assignment_special_case(self, arraylike, arr): + obj = arraylike(arr) + empty = np.arange(1, dtype=object) + empty[:] = [obj] + assert empty[0] is obj + def test_0d_generic_special_case(self): class ArraySubclass(np.ndarray): def __float__(self): diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index e47a24995..0449b3257 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -580,92 +580,6 @@ class TestDeprecateSubarrayDTypeDuringArrayCoercion(_DeprecationTestCase): self.assert_deprecated(check) -class TestFutureWarningArrayLikeNotIterable(_DeprecationTestCase): - # Deprecated 2020-12-09, NumPy 1.20 - warning_cls = FutureWarning - message = "The input object of type.*but not a sequence" - - @pytest.mark.parametrize("protocol", - ["__array__", "__array_interface__", "__array_struct__"]) - def test_deprecated(self, protocol): - """Test that these objects give a warning since they are not 0-D, - not coerced at the top level `np.array(obj)`, but nested, and do - *not* define the sequence protocol. - - NOTE: Tests for the versions including __len__ and __getitem__ exist - in `test_array_coercion.py` and they can be modified or amended - when this deprecation expired. - """ - blueprint = np.arange(10) - MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol)}) - self.assert_deprecated(lambda: np.array([MyArr()], dtype=object)) - - @pytest.mark.parametrize("protocol", - ["__array__", "__array_interface__", "__array_struct__"]) - def test_0d_not_deprecated(self, protocol): - # 0-D always worked (albeit it would use __float__ or similar for the - # conversion, which may not happen anymore) - blueprint = np.array(1.) - MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol)}) - myarr = MyArr() - - self.assert_not_deprecated(lambda: np.array([myarr], dtype=object)) - res = np.array([myarr], dtype=object) - expected = np.empty(1, dtype=object) - expected[0] = myarr - assert_array_equal(res, expected) - - @pytest.mark.parametrize("protocol", - ["__array__", "__array_interface__", "__array_struct__"]) - def test_unnested_not_deprecated(self, protocol): - blueprint = np.arange(10) - MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol)}) - myarr = MyArr() - - self.assert_not_deprecated(lambda: np.array(myarr)) - res = np.array(myarr) - assert_array_equal(res, blueprint) - - @pytest.mark.parametrize("protocol", - ["__array__", "__array_interface__", "__array_struct__"]) - def test_strange_dtype_handling(self, protocol): - """The old code would actually use the dtype from the array, but - then end up not using the array (for dimension discovery) - """ - blueprint = np.arange(10).astype("f4") - MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol), - "__float__": lambda _: 0.5}) - myarr = MyArr() - - # Make sure we warn (and capture the FutureWarning) - with pytest.warns(FutureWarning, match=self.message): - res = np.array([[myarr]]) - - assert res.shape == (1, 1) - assert res.dtype == "f4" - assert res[0, 0] == 0.5 - - @pytest.mark.parametrize("protocol", - ["__array__", "__array_interface__", "__array_struct__"]) - def test_assignment_not_deprecated(self, protocol): - # If the result is dtype=object we do not unpack a nested array or - # array-like, if it is nested at exactly the right depth. - # NOTE: We actually do still call __array__, etc. but ignore the result - # in the end. For `dtype=object` we could optimize that away. - blueprint = np.arange(10).astype("f4") - MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol), - "__float__": lambda _: 0.5}) - myarr = MyArr() - - res = np.empty(3, dtype=object) - def set(): - res[:] = [myarr, myarr, myarr] - self.assert_not_deprecated(set) - assert res[0] is myarr - assert res[1] is myarr - assert res[2] is myarr - - class TestDeprecatedUnpickleObjectScalar(_DeprecationTestCase): # Deprecated 2020-11-24, NumPy 1.20 """ |