diff options
-rw-r--r-- | numpy/core/_internal.py | 3 | ||||
-rw-r--r-- | numpy/core/src/multiarray/descriptor.c | 29 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 10 | ||||
-rw-r--r-- | numpy/lib/tests/test_arrayterator.py | 4 |
4 files changed, 37 insertions, 9 deletions
diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py index 87b41e517..b89c94d9b 100644 --- a/numpy/core/_internal.py +++ b/numpy/core/_internal.py @@ -87,7 +87,8 @@ def _array_descr(descriptor): return descriptor.str else: new = descriptor.metadata.copy() - del new[METADATA_DTSTR] + # Eliminate any key related to internal implementation + _ = new.pop(METADATA_DTSTR, None) return (descriptor.str, new) else: return (_array_descr(subdtype[0]), subdtype[1]) diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c index c112c8711..909af2243 100644 --- a/numpy/core/src/multiarray/descriptor.c +++ b/numpy/core/src/multiarray/descriptor.c @@ -1789,6 +1789,7 @@ arraydescr_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *kwds PyArray_Descr *descr, *conv; Bool align = FALSE; Bool copy = FALSE; + Bool copied = FALSE; static char *kwlist[] = {"dtype", "align", "copy", "metadata", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O&O&O!", @@ -1816,10 +1817,25 @@ arraydescr_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *kwds descr = PyArray_DescrNew(conv); Py_DECREF(conv); conv = descr; + copied = TRUE; } if ((ometadata != NULL)) { - if ((conv->metadata != NULL)) { + /* We need to be sure to make a new copy of the data-type and any + underlying dictionary */ + if (!copied) { + descr = PyArray_DescrNew(conv); + Py_DECREF(conv); + conv = descr; + } + if ((conv->metadata != NULL)) { + /* Make a copy of the metadata before merging with ometadata + so that this data-type descriptor has it's own copy + */ + odescr = conv->metadata; /* Save a reference */ + conv->metadata = PyDict_Copy(odescr); + Py_DECREF(odescr); /* Decrement the old reference */ + /* Update conv->metadata with anything new in metadata keyword, but do not over-write anything already there */ @@ -1829,8 +1845,8 @@ arraydescr_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *kwds } } else { - Py_INCREF(ometadata); - conv->metadata = ometadata; + /* Make a copy of the input dictionary */ + conv->metadata = PyDict_Copy(ometadata); } } return (PyObject *)conv; @@ -2032,6 +2048,7 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args) &alignment, &dtypeflags, &metadata)) { return NULL; } + break; case 8: if (!PyArg_ParseTuple(args, "(icOOOiii)", &version, &endian, &subarray, &names, &fields, &elsize, @@ -2144,7 +2161,7 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args) } Py_XDECREF(self->metadata); - if (PyDataType_ISDATETIME(self) && (metadata != NULL)) { + if (PyDataType_ISDATETIME(self) && (metadata != Py_None) && (metadata != NULL)) { PyObject *cobj; self->metadata = PyTuple_GET_ITEM(metadata, 0); Py_INCREF(self->metadata); @@ -2153,6 +2170,10 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args) Py_DECREF(cobj); } else { + /* We have a borrowed reference to metadata so no need + to alter reference count + */ + if (metadata == Py_None) metadata = NULL; self->metadata = metadata; Py_XINCREF(metadata); } diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index 7070843a6..97fcc8124 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -1118,11 +1118,10 @@ construct_arrays(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps, } /* We don't do strings */ -/* if (flexible && !object) { - loop->notimplemented = 1; - return nargs; + if (flexible && !object) { + loop->notimplemented = 1; + return nargs; } -*/ /* * If everything is a scalar, or scalars mixed with arrays of @@ -3309,6 +3308,9 @@ ufunc_generic_call(PyUFuncObject *self, PyObject *args, PyObject *kwds) * PyErr_SetString(PyExc_TypeError,""); * return NULL; */ + /* This is expected by at least the ndarray rich_comparisons + to allow for additional handling for strings. + */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } diff --git a/numpy/lib/tests/test_arrayterator.py b/numpy/lib/tests/test_arrayterator.py index 421569651..c600d45eb 100644 --- a/numpy/lib/tests/test_arrayterator.py +++ b/numpy/lib/tests/test_arrayterator.py @@ -41,3 +41,7 @@ def test(): # Check that all elements are iterated correctly assert list(c.flat) == list(d.flat) + +if __name__ == '__main__': + from numpy.testing import run_module_suite + run_module_suite() |