Skip to content

Commit

Permalink
Merge pull request numpy#15882 from eric-wieser/reject-illegal-stride…
Browse files Browse the repository at this point in the history
…s-in-ndarray.__new__

BUG: Do not ignore empty tuple of strides in ndarray.__new__
  • Loading branch information
mattip authored Mar 31, 2020
2 parents 5d8bcae + b88415e commit 642181c
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 3 deletions.
5 changes: 5 additions & 0 deletions doc/release/upcoming_changes/15882.compatibility.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The ``numpy.ndarray`` constructor no longer interprets ``strides=()`` as ``strides=None``
-----------------------------------------------------------------------------------------
The former has changed to have the expected meaning of setting
`numpy.ndarray.strides` to ``()``, while the latter continues to result in
strides being chosen automatically.
7 changes: 4 additions & 3 deletions numpy/core/src/multiarray/arrayobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ maintainer email: [email protected]
#include "arraytypes.h"
#include "scalartypes.h"
#include "arrayobject.h"
#include "conversion_utils.h"
#include "ctors.h"
#include "methods.h"
#include "descriptor.h"
Expand Down Expand Up @@ -1624,7 +1625,7 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
PyArray_Descr *descr = NULL;
int itemsize;
PyArray_Dims dims = {NULL, 0};
PyArray_Dims strides = {NULL, 0};
PyArray_Dims strides = {NULL, -1};
PyArray_Chunk buffer;
npy_longlong offset = 0;
NPY_ORDER order = NPY_CORDER;
Expand All @@ -1645,7 +1646,7 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
PyArray_BufferConverter,
&buffer,
&offset,
&PyArray_IntpConverter,
&PyArray_OptionalIntpConverter,
&strides,
&PyArray_OrderConverter,
&order)) {
Expand All @@ -1660,7 +1661,7 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)

itemsize = descr->elsize;

if (strides.ptr != NULL) {
if (strides.len != -1) {
npy_intp nb, off;
if (strides.len != dims.len) {
PyErr_SetString(PyExc_ValueError,
Expand Down
14 changes: 14 additions & 0 deletions numpy/core/src/multiarray/conversion_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,20 @@ PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq)
return NPY_SUCCEED;
}

/*
* Like PyArray_IntpConverter, but leaves `seq` untouched if `None` is passed
* rather than treating `None` as `()`.
*/
NPY_NO_EXPORT int
PyArray_OptionalIntpConverter(PyObject *obj, PyArray_Dims *seq)
{
if (obj == Py_None) {
return NPY_SUCCEED;
}

return PyArray_IntpConverter(obj, seq);
}

/*NUMPY_API
* Get buffer chunk from object
*
Expand Down
3 changes: 3 additions & 0 deletions numpy/core/src/multiarray/conversion_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
NPY_NO_EXPORT int
PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq);

NPY_NO_EXPORT int
PyArray_OptionalIntpConverter(PyObject *obj, PyArray_Dims *seq);

NPY_NO_EXPORT int
PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf);

Expand Down
6 changes: 6 additions & 0 deletions numpy/core/tests/test_multiarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,12 @@ def test_constructor(self):
y[()] = 6
assert_equal(x[()], 6)

# strides and shape must be the same length
with pytest.raises(ValueError):
np.ndarray((2,), strides=())
with pytest.raises(ValueError):
np.ndarray((), strides=(2,))

def test_output(self):
x = np.array(2)
assert_raises(ValueError, np.add, x, [1], x)
Expand Down

0 comments on commit 642181c

Please sign in to comment.