diff options
author | Marten van Kerkwijk <mhvk@astro.utoronto.ca> | 2022-01-07 10:24:49 -0500 |
---|---|---|
committer | Marten van Kerkwijk <mhvk@astro.utoronto.ca> | 2022-01-08 17:44:29 -0500 |
commit | b375f4eace5636d87fb6e09de23e8b2cb5259a1e (patch) | |
tree | d9b089b5f01d94f65da917e7b05bcf27d0173497 /numpy | |
parent | f4a3e07877eb258f69a7d65d8a3b7e8d96e1aacd (diff) | |
download | numpy-b375f4eace5636d87fb6e09de23e8b2cb5259a1e.tar.gz |
ENH: Let ndarray.__array_finalize__ be callable.
This helps subclasses, who can now do super() in their own
implementation.
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/_add_newdocs.py | 16 | ||||
-rw-r--r-- | numpy/core/src/multiarray/getset.c | 13 | ||||
-rw-r--r-- | numpy/core/src/multiarray/methods.c | 14 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 10 | ||||
-rw-r--r-- | numpy/ma/tests/test_subclassing.py | 5 |
5 files changed, 33 insertions, 25 deletions
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index a8d73af3f..219383e1e 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -2265,10 +2265,6 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('__array_interface__', """Array protocol: Python side.""")) -add_newdoc('numpy.core.multiarray', 'ndarray', ('__array_finalize__', - """None.""")) - - add_newdoc('numpy.core.multiarray', 'ndarray', ('__array_priority__', """Array priority.""")) @@ -2278,12 +2274,12 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('__array_struct__', add_newdoc('numpy.core.multiarray', 'ndarray', ('__dlpack__', """a.__dlpack__(*, stream=None) - + DLPack Protocol: Part of the Array API.""")) add_newdoc('numpy.core.multiarray', 'ndarray', ('__dlpack_device__', """a.__dlpack_device__() - + DLPack Protocol: Part of the Array API.""")) add_newdoc('numpy.core.multiarray', 'ndarray', ('base', @@ -2811,6 +2807,14 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('__array__', """)) +add_newdoc('numpy.core.multiarray', 'ndarray', ('__array_finalize__', + """a.__array_finalize__(obj, /) + + Present so subclasses can call super. Does nothing. + + """)) + + add_newdoc('numpy.core.multiarray', 'ndarray', ('__array_prepare__', """a.__array_prepare__(array[, context], /) diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c index ac6465acd..a4f972ba4 100644 --- a/numpy/core/src/multiarray/getset.c +++ b/numpy/core/src/multiarray/getset.c @@ -926,15 +926,6 @@ array_transpose_get(PyArrayObject *self, void *NPY_UNUSED(ignored)) return PyArray_Transpose(self, NULL); } -/* If this is None, no function call is made - --- default sub-class behavior -*/ -static PyObject * -array_finalize_get(PyArrayObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored)) -{ - Py_RETURN_NONE; -} - NPY_NO_EXPORT PyGetSetDef array_getsetlist[] = { {"ndim", (getter)array_ndim_get, @@ -1008,10 +999,6 @@ NPY_NO_EXPORT PyGetSetDef array_getsetlist[] = { (getter)array_priority_get, NULL, NULL, NULL}, - {"__array_finalize__", - (getter)array_finalize_get, - NULL, - NULL, NULL}, {NULL, NULL, NULL, NULL, NULL}, /* Sentinel */ }; diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index 8dd7c112f..33f78dff2 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -859,7 +859,7 @@ array_astype(PyArrayObject *self, * and it's not a subtype if subok is False, then we * can skip the copy. */ - if (forcecopy != NPY_COPY_ALWAYS && + if (forcecopy != NPY_COPY_ALWAYS && (order == NPY_KEEPORDER || (order == NPY_ANYORDER && (PyArray_IS_C_CONTIGUOUS(self) || @@ -881,7 +881,7 @@ array_astype(PyArrayObject *self, Py_DECREF(dtype); return NULL; } - + if (!PyArray_CanCastArrayTo(self, dtype, casting)) { PyErr_Clear(); npy_set_invalid_cast_error( @@ -926,6 +926,13 @@ array_astype(PyArrayObject *self, static PyObject * +array_finalizearray(PyArrayObject *self, PyObject *obj) +{ + Py_RETURN_NONE; +} + + +static PyObject * array_wraparray(PyArrayObject *self, PyObject *args) { PyArrayObject *arr; @@ -2777,6 +2784,9 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = { {"__array_prepare__", (PyCFunction)array_preparearray, METH_VARARGS, NULL}, + {"__array_finalize__", + (PyCFunction)array_finalizearray, + METH_O, NULL}, {"__array_wrap__", (PyCFunction)array_wraparray, METH_VARARGS, NULL}, diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 2529705d5..d8a8c4da4 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -8997,6 +8997,14 @@ class TestArrayFinalize: break_cycles() assert_(obj_ref() is None, "no references should remain") + def test_can_use_super(self): + class SuperFinalize(np.ndarray): + def __array_finalize__(self, obj): + self.saved_result = super().__array_finalize__(obj) + + a = np.array(1).view(SuperFinalize) + assert_(a.saved_result is None) + def test_orderconverter_with_nonASCII_unicode_ordering(): # gh-7475 @@ -9201,7 +9209,7 @@ class TestViewDtype: # x is non-contiguous x = np.arange(10, dtype='<i4')[::2] with pytest.raises(ValueError, - match='the last axis must be contiguous'): + match='the last axis must be contiguous'): x.view('<i2') expected = [[0, 0], [2, 0], [4, 0], [6, 0], [8, 0]] assert_array_equal(x[:, np.newaxis].view('<i2'), expected) diff --git a/numpy/ma/tests/test_subclassing.py b/numpy/ma/tests/test_subclassing.py index 83a9b2f51..3491cef7f 100644 --- a/numpy/ma/tests/test_subclassing.py +++ b/numpy/ma/tests/test_subclassing.py @@ -28,8 +28,7 @@ class SubArray(np.ndarray): return x def __array_finalize__(self, obj): - if callable(getattr(super(), '__array_finalize__', None)): - super().__array_finalize__(obj) + super().__array_finalize__(obj) self.info = getattr(obj, 'info', {}).copy() return @@ -315,7 +314,7 @@ class TestSubclassing: assert_startswith(repr(mx), 'masked_array') xsub = SubArray(x) mxsub = masked_array(xsub, mask=[True, False, True, False, False]) - assert_startswith(repr(mxsub), + assert_startswith(repr(mxsub), f'masked_{SubArray.__name__}(data=[--, 1, --, 3, 4]') def test_subclass_str(self): |