summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/_internal.py3
-rw-r--r--numpy/core/src/multiarray/descriptor.c29
-rw-r--r--numpy/core/src/umath/ufunc_object.c10
-rw-r--r--numpy/lib/tests/test_arrayterator.py4
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()