diff options
author | Alexander Belopolsky <abalkin@users.noreply.github.com> | 2020-08-03 11:00:58 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-03 10:00:58 -0500 |
commit | 333e08eced6ccabd8ea6e4f6320f00187f9585c5 (patch) | |
tree | f7865fc7e2f8dba5f01f869c1b6b73615a2e3e8c | |
parent | 5b5a74043985b5cf577cd14b9a326b8eeb13c11a (diff) | |
download | numpy-333e08eced6ccabd8ea6e4f6320f00187f9585c5.tar.gz |
BUG: Set readonly flag in array interface instead of warning (gh-16350)
Set readonly flags in array interface dict and array struct
capsule returned by an array with warn_on_write flag set
instead of producing a deprecation warning.
Closes #16335
-rw-r--r-- | doc/release/upcoming_changes/16350.compatibility.rst | 8 | ||||
-rw-r--r-- | numpy/core/src/multiarray/getset.c | 19 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 17 |
3 files changed, 33 insertions, 11 deletions
diff --git a/doc/release/upcoming_changes/16350.compatibility.rst b/doc/release/upcoming_changes/16350.compatibility.rst new file mode 100644 index 000000000..67673a6b1 --- /dev/null +++ b/doc/release/upcoming_changes/16350.compatibility.rst @@ -0,0 +1,8 @@ +Writing to the result of `numpy.broadcast_arrays` will export readonly buffers +------------------------------------------------------------------------------ + +In NumPy 1.17 `numpy.broadcast_arrays` started warning when the resulting array +was written to. This warning was skipped when the array was used through the +buffer interface (e.g. ``memoryview(arr)``). The same thing will now occur for the +two protocols ``__array_interface__``, and ``__array_struct__`` returning read-only +buffers instead of giving a warning.
\ No newline at end of file diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c index 5405a25db..9066f52a8 100644 --- a/numpy/core/src/multiarray/getset.c +++ b/numpy/core/src/multiarray/getset.c @@ -244,8 +244,9 @@ array_dataptr_get(PyArrayObject *self) { return Py_BuildValue("NO", PyLong_FromVoidPtr(PyArray_DATA(self)), - (PyArray_FLAGS(self) & NPY_ARRAY_WRITEABLE ? Py_False : - Py_True)); + ((PyArray_FLAGS(self) & NPY_ARRAY_WRITEABLE) && + !(PyArray_FLAGS(self) & NPY_ARRAY_WARN_ON_WRITE)) ? + Py_False : Py_True); } static PyObject * @@ -274,10 +275,6 @@ array_interface_get(PyArrayObject *self) return NULL; } - if (array_might_be_written(self) < 0) { - Py_DECREF(dict); - return NULL; - } int ret; /* dataptr */ @@ -626,11 +623,6 @@ array_struct_get(PyArrayObject *self) PyArrayInterface *inter; PyObject *ret; - if (PyArray_ISWRITEABLE(self)) { - if (array_might_be_written(self) < 0) { - return NULL; - } - } inter = (PyArrayInterface *)PyArray_malloc(sizeof(PyArrayInterface)); if (inter==NULL) { return PyErr_NoMemory(); @@ -640,6 +632,11 @@ array_struct_get(PyArrayObject *self) inter->typekind = PyArray_DESCR(self)->kind; inter->itemsize = PyArray_DESCR(self)->elsize; inter->flags = PyArray_FLAGS(self); + if (inter->flags & NPY_ARRAY_WARN_ON_WRITE) { + /* Export a warn-on-write array as read-only */ + inter->flags = inter->flags & ~NPY_ARRAY_WARN_ON_WRITE; + inter->flags = inter->flags & ~NPY_ARRAY_WRITEABLE; + } /* reset unused flags */ inter->flags &= ~(NPY_ARRAY_WRITEBACKIFCOPY | NPY_ARRAY_UPDATEIFCOPY |NPY_ARRAY_OWNDATA); if (PyArray_ISNOTSWAPPED(self)) inter->flags |= NPY_ARRAY_NOTSWAPPED; diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index b7d4a6a92..03f10bf2d 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -207,6 +207,23 @@ class TestFlags: a[2] = 10 # only warn once assert_(len(w) == 1) + + @pytest.mark.parametrize(["flag", "flag_value", "writeable"], + [("writeable", True, True), + # Delete _warn_on_write after deprecation and simplify + # the parameterization: + ("_warn_on_write", True, False), + ("writeable", False, False)]) + def test_readonly_flag_protocols(self, flag, flag_value, writeable): + a = np.arange(10) + setattr(a.flags, flag, flag_value) + + class MyArr(): + __array_struct__ = a.__array_struct__ + + assert memoryview(a).readonly is not writeable + assert a.__array_interface__['data'][1] is not writeable + assert np.asarray(MyArr()).flags.writeable is writeable def test_otherflags(self): assert_equal(self.a.flags.carray, True) |