summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorMatti Picus <matti.picus@gmail.com>2019-05-30 23:44:43 +0300
committerSebastian Berg <sebastian@sipsolutions.net>2019-05-30 13:44:43 -0700
commitba53a63ee9be7a7bad7685b051a0ef984caa321e (patch)
tree4393f757c23150e9dc270a5e954798997b4b9f80 /numpy
parent9c44a2dc63d5e63b7d36c57a8bea84c3d117130e (diff)
downloadnumpy-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.c44
-rw-r--r--numpy/core/tests/test_regression.py20
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])