summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Belopolsky <abalkin@users.noreply.github.com>2020-08-03 11:00:58 -0400
committerGitHub <noreply@github.com>2020-08-03 10:00:58 -0500
commit333e08eced6ccabd8ea6e4f6320f00187f9585c5 (patch)
treef7865fc7e2f8dba5f01f869c1b6b73615a2e3e8c
parent5b5a74043985b5cf577cd14b9a326b8eeb13c11a (diff)
downloadnumpy-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.rst8
-rw-r--r--numpy/core/src/multiarray/getset.c19
-rw-r--r--numpy/core/tests/test_multiarray.py17
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)