diff options
author | Matti Picus <matti.picus@gmail.com> | 2019-05-30 23:44:43 +0300 |
---|---|---|
committer | Sebastian Berg <sebastian@sipsolutions.net> | 2019-05-30 13:44:43 -0700 |
commit | ba53a63ee9be7a7bad7685b051a0ef984caa321e (patch) | |
tree | 4393f757c23150e9dc270a5e954798997b4b9f80 /numpy | |
parent | 9c44a2dc63d5e63b7d36c57a8bea84c3d117130e (diff) | |
download | numpy-ba53a63ee9be7a7bad7685b051a0ef984caa321e.tar.gz |
BUG: regression for array([pandas.DataFrame()]) (#13663)
Fixup of gh-13399 to avoid a regression with pandas. The actual output after this is the same as
before, but incorrect with respect to the output shape. However, it seems a bit larger and an issue
to look at after the 1.17 release.
* BUG: test, fix regression for array([pandas.DataFrame()])
* BUG: refactor to make sure tmp is DECREFfed
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/ctors.c | 44 | ||||
-rw-r--r-- | numpy/core/tests/test_regression.py | 20 |
2 files changed, 44 insertions, 20 deletions
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 8e09de1c8..4b524c365 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -439,7 +439,6 @@ static int setArrayFromSequence(PyArrayObject *a, PyObject *s, int dim, PyArrayObject * dst) { - PyObject *tmp; Py_ssize_t i, slen; int res = -1; @@ -447,11 +446,6 @@ setArrayFromSequence(PyArrayObject *a, PyObject *s, if (dst == NULL) dst = a; - /* - * This code is to ensure that the sequence access below will - * return a lower-dimensional sequence. - */ - /* INCREF on entry DECREF on exit */ Py_INCREF(s); @@ -477,32 +471,42 @@ setArrayFromSequence(PyArrayObject *a, PyObject *s, return 0; } + /* + * This code is to ensure that the sequence access below will + * return a lower-dimensional sequence. + */ + if (dim > PyArray_NDIM(a)) { PyErr_Format(PyExc_ValueError, "setArrayFromSequence: sequence/array dimensions mismatch."); goto fail; } - tmp = _array_from_array_like(s, /*dtype*/NULL, /*writeable*/0, /*context*/NULL); - if (tmp == NULL) { + slen = PySequence_Length(s); + if (slen < 0) { goto fail; } - else if (tmp != Py_NotImplemented) { - if (PyArray_CopyInto(dst, (PyArrayObject *)tmp) < 0) { + if (slen > 0) { + /* gh-13659: try __array__ before using s as a sequence */ + PyObject *tmp = _array_from_array_like(s, /*dtype*/NULL, /*writeable*/0, + /*context*/NULL); + if (tmp == NULL) { goto fail; } - - Py_DECREF(s); - return 0; - } - else { - Py_DECREF(Py_NotImplemented); + else if (tmp == Py_NotImplemented) { + Py_DECREF(tmp); + } + else { + int r = PyArray_CopyInto(dst, (PyArrayObject *)tmp); + Py_DECREF(tmp); + if (r < 0) { + goto fail; + } + Py_DECREF(s); + return 0; + } } - slen = PySequence_Length(s); - if (slen < 0) { - goto fail; - } /* * Either the dimensions match, or the sequence has length 1 and can * be broadcast to the destination. diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 4e48c82b7..e564ae300 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -2454,3 +2454,23 @@ class TestRegression(object): __array_interface__ = {} np.array([T()]) + + def test_2d__array__shape(self): + class T(object): + def __array__(self): + return np.ndarray(shape=(0,0)) + + # Make sure __array__ is used instead of Sequence methods. + def __iter__(self): + return iter([]) + + def __getitem__(self, idx): + raise AssertionError("__getitem__ was called") + + def __len__(self): + return 0 + + + t = T() + #gh-13659, would raise in broadcasting [x=t for x in result] + np.array([t]) |