summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2018-03-15 15:40:40 (GMT)
committerCharles Harris <charlesr.harris@gmail.com>2018-03-19 16:54:36 (GMT)
commit7d2f3a63577ab9c40999175f96c6571c39f60ad9 (patch)
tree5ee0464fdc6116b92923cc4396d3d53afb9b70b4
parentdce7f20e95e6bd3fc07517c0b2daf3942a34ddf7 (diff)
downloadpython-numpy-7d2f3a63577ab9c40999175f96c6571c39f60ad9.zip
python-numpy-7d2f3a63577ab9c40999175f96c6571c39f60ad9.tar.gz
python-numpy-7d2f3a63577ab9c40999175f96c6571c39f60ad9.tar.bz2
MAINT: Fix Python 3 deprecated C-API use
The PyObject_AsWriteBuffer and PyObject_AsReadBuffer functions are deprecated in Python 3. Replace them with the Py_buffer based replacements. Much of that was done prior to this patch, but some uses were missed.
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src19
-rw-r--r--numpy/core/src/multiarray/common.c16
-rw-r--r--numpy/core/src/multiarray/conversion_utils.c12
-rw-r--r--numpy/core/src/multiarray/ctors.c62
-rw-r--r--numpy/core/src/multiarray/getset.c50
-rw-r--r--numpy/core/src/multiarray/methods.c4
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src24
7 files changed, 164 insertions, 23 deletions
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index e8aa194..5e6804a 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -998,11 +998,25 @@ VOID_setitem(PyObject *op, void *input, void *vap)
* undiscerning case: It interprets any object as a buffer
* and reads as many bytes as possible, padding with 0.
*/
+#if defined(NPY_PY3K)
+ {
+ Py_buffer view;
+
+ if (PyObject_GetBuffer(op, &view, PyBUF_SIMPLE) < 0) {
+ return -1;
+ }
+ memcpy(ip, view.buf, PyArray_MIN(view.len, itemsize));
+ if (itemsize > view.len) {
+ memset(ip + view.len, 0, itemsize - view.len);
+ }
+ PyBuffer_Release(&view);
+ }
+#else
{
const void *buffer;
Py_ssize_t buflen;
- res = PyObject_AsReadBuffer(op, &buffer, &buflen);
- if (res == -1) {
+
+ if (PyObject_AsReadBuffer(op, &buffer, &buflen) < 0) {
return -1;
}
memcpy(ip, buffer, PyArray_MIN(buflen, itemsize));
@@ -1010,6 +1024,7 @@ VOID_setitem(PyObject *op, void *input, void *vap)
memset(ip + buflen, 0, itemsize - buflen);
}
}
+#endif
return 0;
}
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index 10efdc4..f191f8d 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -305,7 +305,8 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
memset(&buffer_view, 0, sizeof(Py_buffer));
if (PyObject_GetBuffer(obj, &buffer_view,
PyBUF_FORMAT|PyBUF_STRIDES) == 0 ||
- PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) {
+ PyObject_GetBuffer(obj, &buffer_view,
+ PyBUF_FORMAT|PyBUF_SIMPLE) == 0) {
PyErr_Clear();
dtype = _descriptor_from_pep3118_format(buffer_view.format);
@@ -633,8 +634,12 @@ NPY_NO_EXPORT npy_bool
_IsWriteable(PyArrayObject *ap)
{
PyObject *base=PyArray_BASE(ap);
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#else
void *dummy;
Py_ssize_t n;
+#endif
/* If we own our own data, then no-problem */
if ((base == NULL) || (PyArray_FLAGS(ap) & NPY_ARRAY_OWNDATA)) {
@@ -668,9 +673,18 @@ _IsWriteable(PyArrayObject *ap)
if (PyString_Check(base)) {
return NPY_TRUE;
}
+#if defined(NPY_PY3K)
+ if (PyObject_GetBuffer(base, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
+ PyErr_Clear();
+ return NPY_FALSE;
+ }
+ PyBuffer_Release(&view);
+#else
if (PyObject_AsWriteBuffer(base, &dummy, &n) < 0) {
+ PyErr_Clear();
return NPY_FALSE;
}
+#endif
return NPY_TRUE;
}
diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c
index 2bb1cbf..b398342 100644
--- a/numpy/core/src/multiarray/conversion_utils.c
+++ b/numpy/core/src/multiarray/conversion_utils.c
@@ -165,10 +165,12 @@ PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
}
#if defined(NPY_PY3K)
- if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE) != 0) {
+ if (PyObject_GetBuffer(obj, &view,
+ PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE|PyBUF_SIMPLE) != 0) {
PyErr_Clear();
buf->flags &= ~NPY_ARRAY_WRITEABLE;
- if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS) != 0) {
+ if (PyObject_GetBuffer(obj, &view,
+ PyBUF_ANY_CONTIGUOUS|PyBUF_SIMPLE) != 0) {
return NPY_FAIL;
}
}
@@ -177,8 +179,10 @@ PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *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.
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
*/
PyBuffer_Release(&view);
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 3d6b161..0eba077 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -729,13 +729,16 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
/* PEP 3118 buffer interface */
if (PyObject_CheckBuffer(obj) == 1) {
memset(&buffer_view, 0, sizeof(Py_buffer));
- if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 ||
- PyObject_GetBuffer(obj, &buffer_view, PyBUF_ND) == 0) {
+ if (PyObject_GetBuffer(obj, &buffer_view,
+ PyBUF_STRIDES|PyBUF_SIMPLE) == 0 ||
+ PyObject_GetBuffer(obj, &buffer_view,
+ PyBUF_ND|PyBUF_SIMPLE) == 0) {
int nd = buffer_view.ndim;
+
if (nd < *maxndim) {
*maxndim = nd;
}
- for (i=0; i<*maxndim; i++) {
+ for (i = 0; i < *maxndim; i++) {
d[i] = buffer_view.shape[i];
}
PyBuffer_Release(&buffer_view);
@@ -756,6 +759,7 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
e = PyArray_LookupSpecial_OnInstance(obj, "__array_struct__");
if (e != NULL) {
int nd = -1;
+
if (NpyCapsule_Check(e)) {
PyArrayInterface *inter;
inter = (PyArrayInterface *)NpyCapsule_AsVoidPtr(e);
@@ -2187,7 +2191,11 @@ PyArray_FromInterface(PyObject *origin)
PyArrayObject *ret;
PyArray_Descr *dtype = NULL;
char *data = NULL;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#else
Py_ssize_t buffer_len;
+#endif
int res, i, n;
npy_intp dims[NPY_MAXDIMS], strides[NPY_MAXDIMS];
int dataflags = NPY_ARRAY_BEHAVED;
@@ -2217,7 +2225,7 @@ PyArray_FromInterface(PyObject *origin)
if (PyUnicode_Check(attr)) {
PyObject *tmp = PyUnicode_AsASCIIString(attr);
if (tmp == NULL) {
- goto fail;
+ goto fail;
}
attr = tmp;
}
@@ -2251,7 +2259,7 @@ PyArray_FromInterface(PyObject *origin)
dtype = new_dtype;
}
}
-
+
#if defined(NPY_PY3K)
Py_DECREF(attr); /* Pairs with the unicode handling above */
#endif
@@ -2335,6 +2343,25 @@ PyArray_FromInterface(PyObject *origin)
else {
base = origin;
}
+#if defined(NPY_PY3K)
+ if (PyObject_GetBuffer(base, &view,
+ PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
+ PyErr_Clear();
+ if (PyObject_GetBuffer(base, &view,
+ PyBUF_SIMPLE) < 0) {
+ goto fail;
+ }
+ dataflags &= ~NPY_ARRAY_WRITEABLE;
+ }
+ data = (char *)view.buf;
+ /*
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
+ */
+ PyBuffer_Release(&view);
+#else
res = PyObject_AsWriteBuffer(base, (void **)&data, &buffer_len);
if (res < 0) {
PyErr_Clear();
@@ -2345,6 +2372,7 @@ PyArray_FromInterface(PyObject *origin)
}
dataflags &= ~NPY_ARRAY_WRITEABLE;
}
+#endif
/* Get offset number from interface specification */
attr = PyDict_GetItemString(origin, "offset");
if (attr) {
@@ -3480,6 +3508,9 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
{
PyArrayObject *ret;
char *data;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#endif
Py_ssize_t ts;
npy_intp s, n;
int itemsize;
@@ -3519,6 +3550,26 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
Py_INCREF(buf);
}
+#if defined(NPY_PY3K)
+ if (PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
+ writeable = 0;
+ PyErr_Clear();
+ if (PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE) < 0) {
+ Py_DECREF(buf);
+ Py_DECREF(type);
+ return NULL;
+ }
+ }
+ data = (char *)view.buf;
+ ts = view.len;
+ /*
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
+ */
+ PyBuffer_Release(&view);
+#else
if (PyObject_AsWriteBuffer(buf, (void *)&data, &ts) == -1) {
writeable = 0;
PyErr_Clear();
@@ -3528,6 +3579,7 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
return NULL;
}
}
+#endif
if ((offset < 0) || (offset > ts)) {
PyErr_Format(PyExc_ValueError,
diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c
index 825363f..86e6e7a 100644
--- a/numpy/core/src/multiarray/getset.c
+++ b/numpy/core/src/multiarray/getset.c
@@ -106,8 +106,12 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
npy_intp offset = 0;
npy_intp lower_offset = 0;
npy_intp upper_offset = 0;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#else
Py_ssize_t buf_len;
char *buf;
+#endif
if (obj == NULL) {
PyErr_SetString(PyExc_AttributeError,
@@ -132,12 +136,21 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
* Get the available memory through the buffer interface on
* PyArray_BASE(new) or if that fails from the current new
*/
- if (PyArray_BASE(new) && PyObject_AsReadBuffer(PyArray_BASE(new),
- (const void **)&buf,
- &buf_len) >= 0) {
+#if defined(NPY_PY3K)
+ if (PyArray_BASE(new) &&
+ PyObject_GetBuffer(PyArray_BASE(new), &view, PyBUF_SIMPLE) >= 0) {
+ offset = PyArray_BYTES(self) - (char *)view.buf;
+ numbytes = view.len + offset;
+ PyBuffer_Release(&view);
+ }
+#else
+ if (PyArray_BASE(new) &&
+ PyObject_AsReadBuffer(PyArray_BASE(new), (const void **)&buf,
+ &buf_len) >= 0) {
offset = PyArray_BYTES(self) - buf;
numbytes = buf_len + offset;
}
+#endif
else {
PyErr_Clear();
offset_bounds_from_strides(PyArray_ITEMSIZE(new), PyArray_NDIM(new),
@@ -328,6 +341,9 @@ array_data_set(PyArrayObject *self, PyObject *op)
void *buf;
Py_ssize_t buf_len;
int writeable=1;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#endif
/* 2016-19-02, 1.12 */
int ret = DEPRECATE("Assigning the 'data' attribute is an "
@@ -342,18 +358,38 @@ array_data_set(PyArrayObject *self, PyObject *op)
"Cannot delete array data");
return -1;
}
+#if defined(NPY_PY3K)
+ if (PyObject_GetBuffer(op, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
+ writeable = 0;
+ PyErr_Clear();
+ if (PyObject_GetBuffer(op, &view, PyBUF_SIMPLE) < 0) {
+ return -1;
+ }
+ }
+ buf = view.buf;
+ buf_len = view.len;
+ /*
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
+ */
+ PyBuffer_Release(&view);
+#else
if (PyObject_AsWriteBuffer(op, &buf, &buf_len) < 0) {
+ PyErr_Clear();
writeable = 0;
if (PyObject_AsReadBuffer(op, (const void **)&buf, &buf_len) < 0) {
+ PyErr_Clear();
PyErr_SetString(PyExc_AttributeError,
- "object does not have single-segment " \
- "buffer interface");
+ "object does not have single-segment buffer interface");
return -1;
}
}
+#endif
if (!PyArray_ISONESEGMENT(self)) {
- PyErr_SetString(PyExc_AttributeError, "cannot set single-" \
- "segment buffer for discontiguous array");
+ PyErr_SetString(PyExc_AttributeError,
+ "cannot set single-segment buffer for discontiguous array");
return -1;
}
if (PyArray_NBYTES(self) > buf_len) {
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c
index cd88ab7..004af8a 100644
--- a/numpy/core/src/multiarray/methods.c
+++ b/numpy/core/src/multiarray/methods.c
@@ -2305,7 +2305,7 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds)
}
else {
PyErr_SetString(PyExc_ValueError,
- "cannot set aligned flag of mis-"\
+ "cannot set aligned flag of mis-"
"aligned array to True");
return NULL;
}
@@ -2315,7 +2315,7 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds)
if (PyObject_IsTrue(uic)) {
fa->flags = flagback;
PyErr_SetString(PyExc_ValueError,
- "cannot set WRITEBACKIFCOPY " \
+ "cannot set WRITEBACKIFCOPY "
"flag to True");
return NULL;
}
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index ee83206..9ea26e5 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -1842,6 +1842,9 @@ static PyObject *
gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args))
{
PyObject *ret = NULL, *obj = NULL, *mod = NULL;
+#if defined(NPY_PY3K)
+ Py_buffer view;
+#endif
const char *buffer;
Py_ssize_t buflen;
@@ -1850,18 +1853,35 @@ gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args))
if (ret == NULL) {
return NULL;
}
+
#if defined(NPY_PY3K)
if (PyArray_IsScalar(self, Unicode)) {
/* Unicode on Python 3 does not expose the buffer interface */
buffer = PyUnicode_AS_DATA(self);
buflen = PyUnicode_GET_DATA_SIZE(self);
}
- else
-#endif
+ else if (PyObject_GetBuffer(self, &view, PyBUF_SIMPLE) >= 0) {
+ buffer = view.buf;
+ buflen = view.len;
+ /*
+ * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
+ * PyObject_AsReadBuffer that this code replaces release the buffer. It is
+ * up to the object that supplies the buffer to guarantee that the buffer
+ * sticks around after the release.
+ */
+ PyBuffer_Release(&view);
+ }
+ else {
+ Py_DECREF(ret);
+ return NULL;
+ }
+#else
if (PyObject_AsReadBuffer(self, (const void **)&buffer, &buflen)<0) {
Py_DECREF(ret);
return NULL;
}
+#endif
+
mod = PyImport_ImportModule("numpy.core.multiarray");
if (mod == NULL) {
return NULL;