Skip to content

Commit

Permalink
Merge pull request numpy#10740 from charris/add-python-3.7-tests
Browse files Browse the repository at this point in the history
MAINT, TST: Fixes for Python 3.7
  • Loading branch information
charris authored Mar 19, 2018
2 parents b7a2b69 + d9c53d7 commit 646452b
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 37 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ python:
- 3.4
- 3.5
- 3.6
- 3.7-dev
matrix:
include:
- python: 3.6
Expand Down
19 changes: 17 additions & 2 deletions numpy/core/src/multiarray/arraytypes.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -998,18 +998,33 @@ 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));
if (itemsize > buflen) {
memset(ip + buflen, 0, itemsize - buflen);
}
}
#endif
return 0;
}

Expand Down
16 changes: 15 additions & 1 deletion numpy/core/src/multiarray/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 4 additions & 0 deletions numpy/core/src/multiarray/compiled_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1402,7 +1402,11 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
{
PyObject *obj;
PyObject *str;
#if (PY_VERSION_HEX >= 0x030700A2)
const char *docstr;
#else
char *docstr;
#endif
static char *msg = "already has a docstring";
PyObject *tp_dict = PyArrayDescr_Type.tp_dict;
PyObject *myobj;
Expand Down
12 changes: 8 additions & 4 deletions numpy/core/src/multiarray/conversion_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand All @@ -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);

Expand Down
62 changes: 57 additions & 5 deletions numpy/core/src/multiarray/ctors.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -3528,6 +3579,7 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
return NULL;
}
}
#endif

if ((offset < 0) || (offset > ts)) {
PyErr_Format(PyExc_ValueError,
Expand Down
50 changes: 43 additions & 7 deletions numpy/core/src/multiarray/getset.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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),
Expand Down Expand Up @@ -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 "
Expand All @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions numpy/core/src/multiarray/methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
Loading

0 comments on commit 646452b

Please sign in to comment.