summaryrefslogtreecommitdiff
path: root/numpy/core/src/multiarray/usertypes.c
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core/src/multiarray/usertypes.c')
-rw-r--r--numpy/core/src/multiarray/usertypes.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/numpy/core/src/multiarray/usertypes.c b/numpy/core/src/multiarray/usertypes.c
index a338d712d..5e36c914b 100644
--- a/numpy/core/src/multiarray/usertypes.c
+++ b/numpy/core/src/multiarray/usertypes.c
@@ -41,6 +41,7 @@ maintainer email: oliphant.travis@ieee.org
#include "scalartypes.h"
#include "array_method.h"
#include "convert_datatype.h"
+#include "dtype_traversal.h"
#include "legacy_dtype_implementation.h"
@@ -223,6 +224,8 @@ PyArray_RegisterDataType(PyArray_Descr *descr)
PyErr_SetString(PyExc_ValueError, "missing typeobject");
return -1;
}
+
+ int use_void_clearimpl = 0;
if (descr->flags & (NPY_ITEM_IS_POINTER | NPY_ITEM_REFCOUNT)) {
/*
* User dtype can't actually do reference counting, however, there
@@ -231,6 +234,8 @@ PyArray_RegisterDataType(PyArray_Descr *descr)
* so we have to support this. But such a structure must be constant
* (i.e. fixed at registration time, this is the case for `xpress`).
*/
+ use_void_clearimpl = 1;
+
if (descr->names == NULL || descr->fields == NULL ||
!PyDict_CheckExact(descr->fields)) {
PyErr_Format(PyExc_ValueError,
@@ -256,14 +261,53 @@ PyArray_RegisterDataType(PyArray_Descr *descr)
return -1;
}
+ /*
+ * Legacy user DTypes classes cannot have a name, since the user never
+ * defined one. So we create a name for them here. These DTypes are
+ * effectively static types.
+ *
+ * Note: we have no intention of freeing the memory again since this
+ * behaves identically to static type definition.
+ */
+
+ const char *scalar_name = descr->typeobj->tp_name;
+ /*
+ * We have to take only the name, and ignore the module to get
+ * a reasonable __name__, since static types are limited in this regard
+ * (this is not ideal, but not a big issue in practice).
+ * This is what Python does to print __name__ for static types.
+ */
+ const char *dot = strrchr(scalar_name, '.');
+ if (dot) {
+ scalar_name = dot + 1;
+ }
+ Py_ssize_t name_length = strlen(scalar_name) + 14;
+
+ char *name = PyMem_Malloc(name_length);
+ if (name == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ snprintf(name, name_length, "numpy.dtype[%s]", scalar_name);
+
userdescrs[NPY_NUMUSERTYPES++] = descr;
descr->type_num = typenum;
- if (dtypemeta_wrap_legacy_descriptor(descr) < 0) {
+ if (dtypemeta_wrap_legacy_descriptor(descr, name, NULL) < 0) {
descr->type_num = -1;
NPY_NUMUSERTYPES--;
+ PyMem_Free(name); /* free the name only on failure */
return -1;
}
+ if (use_void_clearimpl) {
+ /* See comment where use_void_clearimpl is set... */
+ NPY_DT_SLOTS(NPY_DTYPE(descr))->get_clear_loop = (
+ &npy_get_clear_void_and_legacy_user_dtype_loop);
+ /* Also use the void zerofill since there may be objects */
+ NPY_DT_SLOTS(NPY_DTYPE(descr))->get_clear_loop = (
+ &npy_get_zerofill_void_and_legacy_user_dtype_loop);
+ }
return typenum;
}
@@ -597,7 +641,7 @@ PyArray_AddLegacyWrapping_CastingImpl(
if (from == to) {
spec.flags = NPY_METH_REQUIRES_PYAPI | NPY_METH_SUPPORTS_UNALIGNED;
PyType_Slot slots[] = {
- {NPY_METH_get_loop, &legacy_cast_get_strided_loop},
+ {_NPY_METH_get_loop, &legacy_cast_get_strided_loop},
{NPY_METH_resolve_descriptors, &legacy_same_dtype_resolve_descriptors},
{0, NULL}};
spec.slots = slots;
@@ -606,7 +650,7 @@ PyArray_AddLegacyWrapping_CastingImpl(
else {
spec.flags = NPY_METH_REQUIRES_PYAPI;
PyType_Slot slots[] = {
- {NPY_METH_get_loop, &legacy_cast_get_strided_loop},
+ {_NPY_METH_get_loop, &legacy_cast_get_strided_loop},
{NPY_METH_resolve_descriptors, &simple_cast_resolve_descriptors},
{0, NULL}};
spec.slots = slots;