summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/buffer.c23
-rw-r--r--numpy/lib/tests/test_stride_tricks.py29
2 files changed, 37 insertions, 15 deletions
diff --git a/numpy/core/src/multiarray/buffer.c b/numpy/core/src/multiarray/buffer.c
index d8ad80266..b729027ad 100644
--- a/numpy/core/src/multiarray/buffer.c
+++ b/numpy/core/src/multiarray/buffer.c
@@ -771,17 +771,6 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
goto fail;
}
}
- /*
- * If a read-only buffer is requested on a read-write array, we return a
- * read-write buffer, which is dubious behavior. But that's why this call
- * is guarded by PyArray_ISWRITEABLE rather than (flags &
- * PyBUF_WRITEABLE).
- */
- if (PyArray_ISWRITEABLE(self)) {
- if (array_might_be_written(self) < 0) {
- goto fail;
- }
- }
if (view == NULL) {
PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
@@ -797,7 +786,17 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
view->buf = PyArray_DATA(self);
view->suboffsets = NULL;
view->itemsize = PyArray_ITEMSIZE(self);
- view->readonly = !PyArray_ISWRITEABLE(self);
+ /*
+ * If a read-only buffer is requested on a read-write array, we return a
+ * read-write buffer as per buffer protocol.
+ * We set a requested buffer to readonly also if the array will be readonly
+ * after a deprecation. This jumps the deprecation, but avoiding the
+ * warning is not convenient here. A warning is given if a writeable
+ * buffer is requested since `PyArray_FailUnlessWriteable` is called above
+ * (and clears the `NPY_ARRAY_WARN_ON_WRITE` flag).
+ */
+ view->readonly = (!PyArray_ISWRITEABLE(self) ||
+ PyArray_CHKFLAGS(self, NPY_ARRAY_WARN_ON_WRITE));
view->internal = NULL;
view->len = PyArray_NBYTES(self);
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
diff --git a/numpy/lib/tests/test_stride_tricks.py b/numpy/lib/tests/test_stride_tricks.py
index 955fb914c..85fcceedc 100644
--- a/numpy/lib/tests/test_stride_tricks.py
+++ b/numpy/lib/tests/test_stride_tricks.py
@@ -417,17 +417,21 @@ def test_writeable():
# but the result of broadcast_arrays needs to be writeable, to
# preserve backwards compatibility
- for results in [broadcast_arrays(original),
- broadcast_arrays(0, original)]:
+ for is_broadcast, results in [(False, broadcast_arrays(original,)),
+ (True, broadcast_arrays(0, original))]:
for result in results:
# This will change to False in a future version
- if any([s == 0 for s in result.strides]):
+ if is_broadcast:
with assert_warns(FutureWarning):
assert_equal(result.flags.writeable, True)
with assert_warns(DeprecationWarning):
result[:] = 0
# Warning not emitted, writing to the array resets it
assert_equal(result.flags.writeable, True)
+ else:
+ # No warning:
+ assert_equal(result.flags.writeable, True)
+
for results in [broadcast_arrays(original),
broadcast_arrays(0, original)]:
for result in results:
@@ -451,6 +455,25 @@ def test_writeable():
assert_(first.shape == second.shape)
+def test_writeable_memoryview():
+ # The result of broadcast_arrays exports as a non-writeable memoryview
+ # because otherwise there is no good way to opt in to the new behaviour
+ # (i.e. you would need to set writeable to False explicitly).
+ # See gh-13929.
+ original = np.array([1, 2, 3])
+
+ for is_broadcast, results in [(False, broadcast_arrays(original,)),
+ (True, broadcast_arrays(0, original))]:
+ for result in results:
+ # This will change to False in a future version
+ if is_broadcast:
+ # memoryview(result, writable=True) will give warning but cannot
+ # be tested using the python API.
+ assert memoryview(result).readonly
+ else:
+ assert not memoryview(result).readonly
+
+
def test_reference_types():
input_array = np.array('a', dtype=object)
expected = np.array(['a'] * 3, dtype=object)