summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/multiarray/dtypemeta.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/numpy/core/src/multiarray/dtypemeta.c b/numpy/core/src/multiarray/dtypemeta.c
index b18ef0c3a..73aa79a66 100644
--- a/numpy/core/src/multiarray/dtypemeta.c
+++ b/numpy/core/src/multiarray/dtypemeta.c
@@ -141,8 +141,9 @@ dtypemeta_wrap_legacy_descriptor(PyArray_Descr *descr)
/*
* Note: we have no intention of freeing the memory again since this
* behaves identically to static type definition (see comment above).
- * This is much cleaner for the legacy API, in the new API both static
- * and heap types are possible.
+ * This is seems cleaner for the legacy API, in the new API both static
+ * and heap types are possible (some difficulty arises from the fact that
+ * these are instances of DTypeMeta and not type).
* In particular our own DTypes can be true static declarations.
* However, this function remains necessary for legacy user dtypes.
*/
@@ -154,35 +155,49 @@ dtypemeta_wrap_legacy_descriptor(PyArray_Descr *descr)
snprintf(tp_name, 100, "numpy.dtype[%s]",
descr->typeobj->tp_name);
- PyArray_DTypeMeta *dtype_class = PyDataMem_NEW(sizeof(PyArray_DTypeMeta));
+ PyArray_DTypeMeta *dtype_class = malloc(sizeof(PyArray_DTypeMeta));
if (dtype_class == NULL) {
PyDataMem_FREE(tp_name);
return -1;
}
/*
- * Initialize the struct fields similar to static code:
+ * Initialize the struct fields identically to static code by copying
+ * a prototype instances for everything except our own fields which
+ * vary between the DTypes.
+ * In particular any Object initialization must be strictly copied from
+ * the untouched prototype to avoid complexities (e.g. with PyPy).
+ * Any Type slots need to be fixed before PyType_Ready, although most
+ * will be inherited automatically there.
*/
- /* Copy in np.dtype since it shares most things */
- memcpy(dtype_class, &PyArrayDescr_Type, sizeof(PyArray_DTypeMeta));
-
- /* Fix name, base, and __new__*/
+ static PyArray_DTypeMeta prototype = {
+ {{
+ PyVarObject_HEAD_INIT(&PyArrayDTypeMeta_Type, 0)
+ .tp_name = NULL, /* set below */
+ .tp_basicsize = sizeof(PyArray_Descr),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_base = &PyArrayDescr_Type,
+ .tp_new = (newfunc)legacy_dtype_default_new
+ },},
+ .is_legacy = 1,
+ .is_abstract = 0, /* this is a concrete DType */
+ /* Further fields are not common between DTypes */
+ };
+ memcpy(dtype_class, &prototype, sizeof(PyArray_DTypeMeta));
+ /* Fix name of the Type*/
((PyTypeObject *)dtype_class)->tp_name = tp_name;
- ((PyTypeObject *)dtype_class)->tp_base = &PyArrayDescr_Type;
- ((PyTypeObject *)dtype_class)->tp_new = (newfunc)legacy_dtype_default_new;
/* Let python finish the initialization (probably unnecessary) */
if (PyType_Ready((PyTypeObject *)dtype_class) < 0) {
return -1;
}
- /* np.dtype is not a concrete DType, this one is */
- dtype_class->is_abstract = NPY_FALSE;
-
- Py_INCREF(descr); /* descr is a singleton that must survive, ensure. */
+ /*
+ * Fill DTypeMeta information that varies between DTypes, any variable
+ * type information would need to be set before PyType_Ready().
+ */
dtype_class->singleton = descr;
Py_INCREF(descr->typeobj);
dtype_class->scalar_type = descr->typeobj;
- dtype_class->is_legacy = NPY_TRUE;
dtype_class->type_num = descr->type_num;
dtype_class->type = descr->type;
dtype_class->f = descr->f;
@@ -193,7 +208,7 @@ dtypemeta_wrap_legacy_descriptor(PyArray_Descr *descr)
/* Datetimes are flexible, but were not considered previously */
dtype_class->is_flexible = NPY_TRUE;
}
- if (PyTypeNum_ISFLEXIBLE(descr->type_num)) {
+ else if (PyTypeNum_ISFLEXIBLE(descr->type_num)) {
dtype_class->is_flexible = NPY_TRUE;
dtype_class->itemsize = -1; /* itemsize is not fixed */
}