diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c index a0e479ba9e43..1f56f942c1d4 100644 --- a/numpy/core/src/multiarray/conversion_utils.c +++ b/numpy/core/src/multiarray/conversion_utils.c @@ -146,7 +146,11 @@ PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq) NPY_NO_EXPORT int PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf) { +#if defined(NPY_PY3K) + Py_buffer view; +#else Py_ssize_t buflen; +#endif buf->ptr = NULL; buf->flags = NPY_ARRAY_BEHAVED; @@ -154,22 +158,41 @@ PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf) if (obj == Py_None) { return NPY_SUCCEED; } - if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) { + +#if defined(NPY_PY3K) + if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE) != 0) { PyErr_Clear(); buf->flags &= ~NPY_ARRAY_WRITEABLE; - if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr), - &buflen) < 0) { + if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS) != 0) { return NPY_FAIL; } } - buf->len = (npy_intp) buflen; + + buf->ptr = view.buf; + buf->len = (npy_intp) view.len; + + /* + * XXX: PyObject_AsWriteBuffer does also this, but it is unsafe, as there is + * no strict guarantee that the buffer sticks around after being released. + */ + PyBuffer_Release(&view); /* Point to the base of the buffer object if present */ -#if defined(NPY_PY3K) if (PyMemoryView_Check(obj)) { buf->base = PyMemoryView_GET_BASE(obj); } #else + if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) { + PyErr_Clear(); + buf->flags &= ~NPY_ARRAY_WRITEABLE; + if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr), + &buflen) < 0) { + return NPY_FAIL; + } + } + buf->len = (npy_intp) buflen; + + /* Point to the base of the buffer object if present */ if (PyBuffer_Check(obj)) { buf->base = ((PyArray_Chunk *)obj)->base; } diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 86b424ebca76..11abff00fd65 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -1912,6 +1912,13 @@ def test_copymodule_preserves_f_contiguity(self): assert_(c.flags.fortran) assert_(c.flags.f_contiguous) + def test_fortran_order_buffer(self): + import numpy as np + a = np.array([['Hello', 'Foob']], dtype='