diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/buffer.c | 23 | ||||
-rw-r--r-- | numpy/lib/tests/test_stride_tricks.py | 29 |
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) |