summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/common/ucsnarrow.c1
-rw-r--r--numpy/core/src/common/ucsnarrow.h2
-rw-r--r--numpy/core/src/multiarray/array_coercion.c9
-rw-r--r--numpy/core/src/multiarray/common.h12
-rw-r--r--numpy/core/src/multiarray/ctors.c68
-rw-r--r--numpy/core/src/multiarray/ctors.h9
-rw-r--r--numpy/core/src/multiarray/descriptor.h12
-rw-r--r--numpy/core/src/multiarray/iterators.c2
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c107
-rw-r--r--numpy/core/src/multiarray/scalarapi.c1
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src1
-rw-r--r--numpy/core/src/multiarray/shape.c1
-rw-r--r--numpy/core/src/umath/reduction.c1
-rw-r--r--numpy/core/tests/test_custom_dtypes.py6
-rw-r--r--numpy/core/tests/test_multiarray.py11
15 files changed, 173 insertions, 70 deletions
diff --git a/numpy/core/src/common/ucsnarrow.c b/numpy/core/src/common/ucsnarrow.c
index 4bea4beee..adf441a12 100644
--- a/numpy/core/src/common/ucsnarrow.c
+++ b/numpy/core/src/common/ucsnarrow.c
@@ -10,6 +10,7 @@
#include "npy_config.h"
#include "npy_pycompat.h"
+#include "common.h"
#include "ctors.h"
/*
diff --git a/numpy/core/src/common/ucsnarrow.h b/numpy/core/src/common/ucsnarrow.h
index 6fe157199..4b17a2809 100644
--- a/numpy/core/src/common/ucsnarrow.h
+++ b/numpy/core/src/common/ucsnarrow.h
@@ -2,6 +2,6 @@
#define NUMPY_CORE_SRC_COMMON_NPY_UCSNARROW_H_
NPY_NO_EXPORT PyUnicodeObject *
-PyUnicode_FromUCS4(char *src, Py_ssize_t size, int swap, int align);
+PyUnicode_FromUCS4(char const *src, Py_ssize_t size, int swap, int align);
#endif /* NUMPY_CORE_SRC_COMMON_NPY_UCSNARROW_H_ */
diff --git a/numpy/core/src/multiarray/array_coercion.c b/numpy/core/src/multiarray/array_coercion.c
index d6bee1a7b..d55a5752b 100644
--- a/numpy/core/src/multiarray/array_coercion.c
+++ b/numpy/core/src/multiarray/array_coercion.c
@@ -878,7 +878,8 @@ find_descriptor_from_array(
* means that legacy behavior is used: The dtype instances "S0", "U0", and
* "V0" are converted to mean the DType classes instead.
* When dtype != NULL, this path is ignored, and the function does nothing
- * unless descr == NULL.
+ * unless descr == NULL. If both descr and dtype are null, it returns the
+ * descriptor for the array.
*
* This function is identical to normal casting using only the dtype, however,
* it supports inspecting the elements when the array has object dtype
@@ -927,7 +928,7 @@ PyArray_AdaptDescriptorToArray(
/* This is an object array but contained no elements, use default */
new_descr = NPY_DT_CALL_default_descr(dtype);
}
- Py_DECREF(dtype);
+ Py_XDECREF(dtype);
return new_descr;
}
@@ -1280,7 +1281,9 @@ PyArray_DiscoverDTypeAndShape(
}
if (requested_descr != NULL) {
- assert(fixed_DType == NPY_DTYPE(requested_descr));
+ if (fixed_DType != NULL) {
+ assert(fixed_DType == NPY_DTYPE(requested_descr));
+ }
/* The output descriptor must be the input. */
Py_INCREF(requested_descr);
*out_descr = requested_descr;
diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h
index 4e067b22c..506bf4fef 100644
--- a/numpy/core/src/multiarray/common.h
+++ b/numpy/core/src/multiarray/common.h
@@ -360,4 +360,16 @@ new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out,
*/
#define NPY_ITER_REDUCTION_AXIS(axis) (axis + (1 << (NPY_BITSOF_INT - 2)))
+/*
+ * In some API calls we wish to allow users to pass a DType class or a
+ * dtype instances with different meanings.
+ * This struct is mainly used for the argument parsing in
+ * `PyArray_DTypeOrDescrConverter`.
+ */
+typedef struct {
+ PyArray_DTypeMeta *dtype;
+ PyArray_Descr *descr;
+} npy_dtype_info;
+
+
#endif /* NUMPY_CORE_SRC_MULTIARRAY_COMMON_H_ */
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 38af60427..d5b599812 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -1605,6 +1605,31 @@ NPY_NO_EXPORT PyObject *
PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
int max_depth, int flags, PyObject *context)
{
+ npy_dtype_info dt_info = {NULL, NULL};
+
+ int res = PyArray_ExtractDTypeAndDescriptor(
+ newtype, &dt_info.descr, &dt_info.dtype);
+
+ if (res < 0) {
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
+ return NULL;
+ }
+
+ PyObject* ret = _PyArray_FromAny(op, newtype, dt_info, min_depth,
+ max_depth, flags, context);
+
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
+ return ret;
+}
+
+// private version updated to accept npy_dtype_info
+
+NPY_NO_EXPORT PyObject *
+_PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, npy_dtype_info dt_info,
+ int min_depth, int max_depth, int flags, PyObject *context)
+{
/*
* This is the main code to make a NumPy array from a Python
* Object. It is called from many different places.
@@ -1620,26 +1645,18 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
return NULL;
}
- PyArray_Descr *fixed_descriptor;
- PyArray_DTypeMeta *fixed_DType;
- if (PyArray_ExtractDTypeAndDescriptor(newtype,
- &fixed_descriptor, &fixed_DType) < 0) {
- Py_XDECREF(newtype);
- return NULL;
- }
+ // steal reference
Py_XDECREF(newtype);
ndim = PyArray_DiscoverDTypeAndShape(op,
- NPY_MAXDIMS, dims, &cache, fixed_DType, fixed_descriptor, &dtype,
+ NPY_MAXDIMS, dims, &cache, dt_info.dtype, dt_info.descr, &dtype,
flags & NPY_ARRAY_ENSURENOCOPY);
- Py_XDECREF(fixed_descriptor);
- Py_XDECREF(fixed_DType);
if (ndim < 0) {
return NULL;
}
- if (NPY_UNLIKELY(fixed_descriptor != NULL && PyDataType_HASSUBARRAY(dtype))) {
+ if (NPY_UNLIKELY(dt_info.descr != NULL && PyDataType_HASSUBARRAY(dtype))) {
/*
* When a subarray dtype was passed in, its dimensions are appended
* to the array dimension (causing a dimension mismatch).
@@ -1909,6 +1926,32 @@ NPY_NO_EXPORT PyObject *
PyArray_CheckFromAny(PyObject *op, PyArray_Descr *descr, int min_depth,
int max_depth, int requires, PyObject *context)
{
+ npy_dtype_info dt_info = {NULL, NULL};
+
+ int res = PyArray_ExtractDTypeAndDescriptor(
+ descr, &dt_info.descr, &dt_info.dtype);
+
+ if (res < 0) {
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
+ return NULL;
+ }
+
+ PyObject* ret = _PyArray_CheckFromAny(op, descr, dt_info, min_depth,
+ max_depth, requires, context);
+
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
+ return ret;
+}
+
+// private version updated to accept npy_dtype_info
+
+NPY_NO_EXPORT PyObject *
+_PyArray_CheckFromAny(PyObject *op, PyArray_Descr *descr,
+ npy_dtype_info dt_info, int min_depth,
+ int max_depth, int requires, PyObject *context)
+{
PyObject *obj;
if (requires & NPY_ARRAY_NOTSWAPPED) {
if (!descr && PyArray_Check(op) &&
@@ -1926,7 +1969,8 @@ PyArray_CheckFromAny(PyObject *op, PyArray_Descr *descr, int min_depth,
}
}
- obj = PyArray_FromAny(op, descr, min_depth, max_depth, requires, context);
+ obj = _PyArray_FromAny(op, descr, dt_info, min_depth, max_depth, requires,
+ context);
if (obj == NULL) {
return NULL;
}
diff --git a/numpy/core/src/multiarray/ctors.h b/numpy/core/src/multiarray/ctors.h
index 98160b1cc..2b8ab0e0e 100644
--- a/numpy/core/src/multiarray/ctors.h
+++ b/numpy/core/src/multiarray/ctors.h
@@ -36,10 +36,19 @@ _array_from_array_like(PyObject *op,
int never_copy);
NPY_NO_EXPORT PyObject *
+_PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, npy_dtype_info dt_info,
+ int min_depth, int max_depth, int flags, PyObject *context);
+
+NPY_NO_EXPORT PyObject *
PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
int max_depth, int flags, PyObject *context);
NPY_NO_EXPORT PyObject *
+_PyArray_CheckFromAny(PyObject *op, PyArray_Descr *descr,
+ npy_dtype_info dt_info, int min_depth,
+ int max_depth, int requires, PyObject *context);
+
+NPY_NO_EXPORT PyObject *
PyArray_CheckFromAny(PyObject *op, PyArray_Descr *descr, int min_depth,
int max_depth, int requires, PyObject *context);
diff --git a/numpy/core/src/multiarray/descriptor.h b/numpy/core/src/multiarray/descriptor.h
index b14edc3aa..9f7d2a2fd 100644
--- a/numpy/core/src/multiarray/descriptor.h
+++ b/numpy/core/src/multiarray/descriptor.h
@@ -2,18 +2,6 @@
#define NUMPY_CORE_SRC_MULTIARRAY_DESCRIPTOR_H_
-/*
- * In some API calls we wish to allow users to pass a DType class or a
- * dtype instances with different meanings.
- * This struct is mainly used for the argument parsing in
- * `PyArray_DTypeOrDescrConverter`.
- */
-typedef struct {
- PyArray_DTypeMeta *dtype;
- PyArray_Descr *descr;
-} npy_dtype_info;
-
-
NPY_NO_EXPORT int
PyArray_DTypeOrDescrConverterOptional(PyObject *, npy_dtype_info *dt_info);
diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c
index 4e6418bf9..8a4027bfc 100644
--- a/numpy/core/src/multiarray/iterators.c
+++ b/numpy/core/src/multiarray/iterators.c
@@ -14,8 +14,8 @@
#include "arrayobject.h"
#include "iterators.h"
-#include "ctors.h"
#include "common.h"
+#include "ctors.h"
#include "conversion_utils.h"
#include "array_coercion.h"
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index e85f8affa..e4b8cb8df 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -1637,8 +1637,8 @@ _prepend_ones(PyArrayObject *arr, int nd, int ndmin, NPY_ORDER order)
static inline PyObject *
_array_fromobject_generic(
- PyObject *op, PyArray_Descr *type, _PyArray_CopyMode copy, NPY_ORDER order,
- npy_bool subok, int ndmin)
+ PyObject *op, npy_dtype_info dt_info, _PyArray_CopyMode copy,
+ NPY_ORDER order, npy_bool subok, int ndmin)
{
PyArrayObject *oparr = NULL, *ret = NULL;
PyArray_Descr *oldtype = NULL;
@@ -1653,7 +1653,9 @@ _array_fromobject_generic(
/* fast exit if simple call */
if (PyArray_CheckExact(op) || (subok && PyArray_Check(op))) {
oparr = (PyArrayObject *)op;
- if (type == NULL) {
+ PyArray_Descr* dtype = PyArray_AdaptDescriptorToArray(
+ oparr, dt_info.dtype, dt_info.descr);
+ if (dtype == NULL) {
if (copy != NPY_COPY_ALWAYS && STRIDING_OK(oparr, order)) {
ret = oparr;
Py_INCREF(ret);
@@ -1671,9 +1673,9 @@ _array_fromobject_generic(
}
/* One more chance for faster exit if user specified the dtype. */
oldtype = PyArray_DESCR(oparr);
- if (PyArray_EquivTypes(oldtype, type)) {
+ if (PyArray_EquivTypes(oldtype, dtype)) {
if (copy != NPY_COPY_ALWAYS && STRIDING_OK(oparr, order)) {
- if (oldtype == type) {
+ if (oldtype == dtype) {
Py_INCREF(op);
ret = oparr;
}
@@ -1681,10 +1683,10 @@ _array_fromobject_generic(
/* Create a new PyArrayObject from the caller's
* PyArray_Descr. Use the reference `op` as the base
* object. */
- Py_INCREF(type);
+ Py_INCREF(dtype);
ret = (PyArrayObject *)PyArray_NewFromDescrAndBase(
Py_TYPE(op),
- type,
+ dtype,
PyArray_NDIM(oparr),
PyArray_DIMS(oparr),
PyArray_STRIDES(oparr),
@@ -1694,24 +1696,31 @@ _array_fromobject_generic(
op
);
}
+ Py_DECREF(dtype);
goto finish;
}
else {
if (copy == NPY_COPY_NEVER) {
PyErr_SetString(PyExc_ValueError,
"Unable to avoid copy while creating a new array.");
+ Py_DECREF(dtype);
return NULL;
}
ret = (PyArrayObject *)PyArray_NewCopy(oparr, order);
- if (oldtype == type || ret == NULL) {
+ if (oldtype == dtype || ret == NULL) {
+ Py_DECREF(dtype);
goto finish;
}
Py_INCREF(oldtype);
Py_DECREF(PyArray_DESCR(ret));
+ Py_DECREF(dtype);
((PyArrayObject_fields *)ret)->descr = oldtype;
goto finish;
}
}
+ else {
+ Py_DECREF(dtype);
+ }
}
if (copy == NPY_COPY_ALWAYS) {
@@ -1734,9 +1743,10 @@ _array_fromobject_generic(
}
flags |= NPY_ARRAY_FORCECAST;
- Py_XINCREF(type);
- ret = (PyArrayObject *)PyArray_CheckFromAny(op, type,
- 0, 0, flags, NULL);
+
+ Py_XINCREF(dt_info.descr);
+ ret = (PyArrayObject *)_PyArray_CheckFromAny(op, dt_info.descr, dt_info,
+ 0, 0, flags, NULL);
finish:
if (ret == NULL) {
@@ -1765,7 +1775,7 @@ array_array(PyObject *NPY_UNUSED(ignored),
npy_bool subok = NPY_FALSE;
_PyArray_CopyMode copy = NPY_COPY_ALWAYS;
int ndmin = 0;
- PyArray_Descr *type = NULL;
+ npy_dtype_info dt_info = {NULL, NULL};
NPY_ORDER order = NPY_KEEPORDER;
PyObject *like = Py_None;
NPY_PREPARE_ARGPARSER;
@@ -1773,21 +1783,23 @@ array_array(PyObject *NPY_UNUSED(ignored),
if (len_args != 1 || (kwnames != NULL)) {
if (npy_parse_arguments("array", args, len_args, kwnames,
"object", NULL, &op,
- "|dtype", &PyArray_DescrConverter2, &type,
+ "|dtype", &PyArray_DTypeOrDescrConverterOptional, &dt_info,
"$copy", &PyArray_CopyConverter, &copy,
"$order", &PyArray_OrderConverter, &order,
"$subok", &PyArray_BoolConverter, &subok,
"$ndmin", &PyArray_PythonPyIntFromInt, &ndmin,
"$like", NULL, &like,
NULL, NULL, NULL) < 0) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return NULL;
}
if (like != Py_None) {
PyObject *deferred = array_implement_c_array_function_creation(
"array", like, NULL, NULL, args, len_args, kwnames);
if (deferred != Py_NotImplemented) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return deferred;
}
}
@@ -1798,8 +1810,9 @@ array_array(PyObject *NPY_UNUSED(ignored),
}
PyObject *res = _array_fromobject_generic(
- op, type, copy, order, subok, ndmin);
- Py_XDECREF(type);
+ op, dt_info, copy, order, subok, ndmin);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return res;
}
@@ -1808,7 +1821,7 @@ array_asarray(PyObject *NPY_UNUSED(ignored),
PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames)
{
PyObject *op;
- PyArray_Descr *type = NULL;
+ npy_dtype_info dt_info = {NULL, NULL};
NPY_ORDER order = NPY_KEEPORDER;
PyObject *like = Py_None;
NPY_PREPARE_ARGPARSER;
@@ -1816,18 +1829,20 @@ array_asarray(PyObject *NPY_UNUSED(ignored),
if (len_args != 1 || (kwnames != NULL)) {
if (npy_parse_arguments("asarray", args, len_args, kwnames,
"a", NULL, &op,
- "|dtype", &PyArray_DescrConverter2, &type,
+ "|dtype", &PyArray_DTypeOrDescrConverterOptional, &dt_info,
"|order", &PyArray_OrderConverter, &order,
"$like", NULL, &like,
NULL, NULL, NULL) < 0) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return NULL;
}
if (like != Py_None) {
PyObject *deferred = array_implement_c_array_function_creation(
"asarray", like, NULL, NULL, args, len_args, kwnames);
if (deferred != Py_NotImplemented) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return deferred;
}
}
@@ -1837,8 +1852,9 @@ array_asarray(PyObject *NPY_UNUSED(ignored),
}
PyObject *res = _array_fromobject_generic(
- op, type, NPY_FALSE, order, NPY_FALSE, 0);
- Py_XDECREF(type);
+ op, dt_info, NPY_FALSE, order, NPY_FALSE, 0);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return res;
}
@@ -1847,7 +1863,7 @@ array_asanyarray(PyObject *NPY_UNUSED(ignored),
PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames)
{
PyObject *op;
- PyArray_Descr *type = NULL;
+ npy_dtype_info dt_info = {NULL, NULL};
NPY_ORDER order = NPY_KEEPORDER;
PyObject *like = Py_None;
NPY_PREPARE_ARGPARSER;
@@ -1855,18 +1871,20 @@ array_asanyarray(PyObject *NPY_UNUSED(ignored),
if (len_args != 1 || (kwnames != NULL)) {
if (npy_parse_arguments("asanyarray", args, len_args, kwnames,
"a", NULL, &op,
- "|dtype", &PyArray_DescrConverter2, &type,
+ "|dtype", &PyArray_DTypeOrDescrConverterOptional, &dt_info,
"|order", &PyArray_OrderConverter, &order,
"$like", NULL, &like,
NULL, NULL, NULL) < 0) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return NULL;
}
if (like != Py_None) {
PyObject *deferred = array_implement_c_array_function_creation(
"asanyarray", like, NULL, NULL, args, len_args, kwnames);
if (deferred != Py_NotImplemented) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return deferred;
}
}
@@ -1876,8 +1894,9 @@ array_asanyarray(PyObject *NPY_UNUSED(ignored),
}
PyObject *res = _array_fromobject_generic(
- op, type, NPY_FALSE, order, NPY_TRUE, 0);
- Py_XDECREF(type);
+ op, dt_info, NPY_FALSE, order, NPY_TRUE, 0);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return res;
}
@@ -1887,24 +1906,26 @@ array_ascontiguousarray(PyObject *NPY_UNUSED(ignored),
PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames)
{
PyObject *op;
- PyArray_Descr *type = NULL;
+ npy_dtype_info dt_info = {NULL, NULL};
PyObject *like = Py_None;
NPY_PREPARE_ARGPARSER;
if (len_args != 1 || (kwnames != NULL)) {
if (npy_parse_arguments("ascontiguousarray", args, len_args, kwnames,
"a", NULL, &op,
- "|dtype", &PyArray_DescrConverter2, &type,
+ "|dtype", &PyArray_DTypeOrDescrConverterOptional, &dt_info,
"$like", NULL, &like,
NULL, NULL, NULL) < 0) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return NULL;
}
if (like != Py_None) {
PyObject *deferred = array_implement_c_array_function_creation(
"ascontiguousarray", like, NULL, NULL, args, len_args, kwnames);
if (deferred != Py_NotImplemented) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return deferred;
}
}
@@ -1914,8 +1935,9 @@ array_ascontiguousarray(PyObject *NPY_UNUSED(ignored),
}
PyObject *res = _array_fromobject_generic(
- op, type, NPY_FALSE, NPY_CORDER, NPY_FALSE, 1);
- Py_XDECREF(type);
+ op, dt_info, NPY_FALSE, NPY_CORDER, NPY_FALSE, 1);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return res;
}
@@ -1925,24 +1947,26 @@ array_asfortranarray(PyObject *NPY_UNUSED(ignored),
PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames)
{
PyObject *op;
- PyArray_Descr *type = NULL;
+ npy_dtype_info dt_info = {NULL, NULL};
PyObject *like = Py_None;
NPY_PREPARE_ARGPARSER;
if (len_args != 1 || (kwnames != NULL)) {
if (npy_parse_arguments("asfortranarray", args, len_args, kwnames,
"a", NULL, &op,
- "|dtype", &PyArray_DescrConverter2, &type,
+ "|dtype", &PyArray_DTypeOrDescrConverterOptional, &dt_info,
"$like", NULL, &like,
NULL, NULL, NULL) < 0) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return NULL;
}
if (like != Py_None) {
PyObject *deferred = array_implement_c_array_function_creation(
"asfortranarray", like, NULL, NULL, args, len_args, kwnames);
if (deferred != Py_NotImplemented) {
- Py_XDECREF(type);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return deferred;
}
}
@@ -1952,8 +1976,9 @@ array_asfortranarray(PyObject *NPY_UNUSED(ignored),
}
PyObject *res = _array_fromobject_generic(
- op, type, NPY_FALSE, NPY_FORTRANORDER, NPY_FALSE, 1);
- Py_XDECREF(type);
+ op, dt_info, NPY_FALSE, NPY_FORTRANORDER, NPY_FALSE, 1);
+ Py_XDECREF(dt_info.descr);
+ Py_XDECREF(dt_info.dtype);
return res;
}
diff --git a/numpy/core/src/multiarray/scalarapi.c b/numpy/core/src/multiarray/scalarapi.c
index 40f1da2c4..62479eabb 100644
--- a/numpy/core/src/multiarray/scalarapi.c
+++ b/numpy/core/src/multiarray/scalarapi.c
@@ -14,6 +14,7 @@
#include "npy_pycompat.h"
+#include "common.h"
#include "ctors.h"
#include "descriptor.h"
#include "scalartypes.h"
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index 17163ef09..51822276e 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -17,6 +17,7 @@
#include "npy_config.h"
#include "mapping.h"
+#include "common.h"
#include "ctors.h"
#include "usertypes.h"
#include "numpyos.h"
diff --git a/numpy/core/src/multiarray/shape.c b/numpy/core/src/multiarray/shape.c
index 25af43bbc..1ae314bad 100644
--- a/numpy/core/src/multiarray/shape.c
+++ b/numpy/core/src/multiarray/shape.c
@@ -14,6 +14,7 @@
#include "npy_pycompat.h"
+#include "common.h"
#include "ctors.h"
#include "shape.h"
diff --git a/numpy/core/src/umath/reduction.c b/numpy/core/src/umath/reduction.c
index 9416e9a29..188039e1a 100644
--- a/numpy/core/src/umath/reduction.c
+++ b/numpy/core/src/umath/reduction.c
@@ -20,6 +20,7 @@
#include "array_assign.h"
#include "array_coercion.h"
#include "array_method.h"
+#include "common.h"
#include "ctors.h"
#include "numpy/ufuncobject.h"
diff --git a/numpy/core/tests/test_custom_dtypes.py b/numpy/core/tests/test_custom_dtypes.py
index 1a34c6fa3..da6a4bd50 100644
--- a/numpy/core/tests/test_custom_dtypes.py
+++ b/numpy/core/tests/test_custom_dtypes.py
@@ -229,6 +229,12 @@ class TestSFloat:
expected = arr.astype(SF(1.)) # above will have discovered 1. scaling
assert_array_equal(res.view(np.float64), expected.view(np.float64))
+ def test_creation_class(self):
+ arr1 = np.array([1., 2., 3.], dtype=SF)
+ assert arr1.dtype == SF(1.)
+ arr2 = np.array([1., 2., 3.], dtype=SF(1.))
+ assert_array_equal(arr1.view(np.float64), arr2.view(np.float64))
+
def test_type_pickle():
# can't actually unpickle, but we can pickle (if in namespace)
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index ac4bd42d3..94f6ef7ad 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1194,6 +1194,17 @@ class TestCreation:
expected = expected * (arr.nbytes // len(expected))
assert arr.tobytes() == expected
+ @pytest.mark.parametrize("func", [
+ np.array, np.asarray, np.asanyarray, np.ascontiguousarray,
+ np.asfortranarray])
+ def test_creation_from_dtypemeta(self, func):
+ dtype = np.dtype('i')
+ arr1 = func([1, 2, 3], dtype=dtype)
+ arr2 = func([1, 2, 3], dtype=type(dtype))
+ assert_array_equal(arr1, arr2)
+ assert arr2.dtype == dtype
+
+
class TestStructured:
def test_subarray_field_access(self):
a = np.zeros((3, 5), dtype=[('a', ('i4', (2, 2)))])