diff options
author | Sebastian Berg <sebastian@sipsolutions.net> | 2020-10-07 23:04:17 -0500 |
---|---|---|
committer | Sebastian Berg <sebastian@sipsolutions.net> | 2020-10-07 23:11:12 -0500 |
commit | 980d52eeaf0498f49dfef61f2a6cba6b78100d83 (patch) | |
tree | 5a5dadc19a78c5c0d5396e85374bf831b0fa4d48 | |
parent | 382758355998951cea2b9f6ad1fb83e7dc4c3a02 (diff) | |
download | numpy-980d52eeaf0498f49dfef61f2a6cba6b78100d83.tar.gz |
BUG: Accept legacy user-dtypes if not isinstance(dtype.type, np.generic)
These are now accepted (as a no-op) in `_PyArray_MapPyTypeToDType`
retaining previous behaviour (as lookup for a registered user-type
was only done if the instance check suceeded.
Retain the check for future user DTypes, as it sould be a conscience
choice to relax this requirement.
-rw-r--r-- | numpy/core/src/multiarray/array_coercion.c | 36 | ||||
-rw-r--r-- | numpy/core/tests/test_dtype.py | 4 |
2 files changed, 23 insertions, 17 deletions
diff --git a/numpy/core/src/multiarray/array_coercion.c b/numpy/core/src/multiarray/array_coercion.c index 64a06d58b..4831dfca6 100644 --- a/numpy/core/src/multiarray/array_coercion.c +++ b/numpy/core/src/multiarray/array_coercion.c @@ -128,7 +128,9 @@ _prime_global_pytype_to_type_dict(void) /** - * Add a new mapping from a python type to the DType class. + * Add a new mapping from a python type to the DType class. For a user + * defined legacy dtype, this function does nothing unless the pytype + * subclass from `np.generic`. * * This assumes that the DType class is guaranteed to hold on the * python type (this assumption is guaranteed). @@ -145,21 +147,29 @@ _PyArray_MapPyTypeToDType( { PyObject *Dtype_obj = (PyObject *)DType; - if (userdef) { + if (userdef && !PyObject_IsSubclass( + (PyObject *)pytype, (PyObject *)&PyGenericArrType_Type)) { /* - * It seems we did not strictly enforce this in the legacy dtype - * API, but assume that it is always true. Further, this could be - * relaxed in the future. In particular we should have a new - * superclass of ``np.generic`` in order to note enforce the array - * scalar behaviour. + * We expect that user dtypes (for now) will subclass some numpy + * scalar class to allow automatic discovery. */ - if (!PyObject_IsSubclass((PyObject *)pytype, (PyObject *)&PyGenericArrType_Type)) { - PyErr_Format(PyExc_RuntimeError, - "currently it is only possible to register a DType " - "for scalars deriving from `np.generic`, got '%S'.", - (PyObject *)pytype); - return -1; + if (DType->legacy) { + /* + * For legacy user dtypes, discovery relied on subclassing, but + * arbitrary type objects are supported, so do nothing. + */ + return 0; } + /* + * We currently enforce that user DTypes subclass from `np.generic` + * (this should become a `np.generic` base class and may be lifted + * entirely). + */ + PyErr_Format(PyExc_RuntimeError, + "currently it is only possible to register a DType " + "for scalars deriving from `np.generic`, got '%S'.", + (PyObject *)pytype); + return -1; } /* Create the global dictionary if it does not exist */ diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index 898ceebcd..45cc0b8b3 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -1355,10 +1355,6 @@ class TestUserDType: # unnecessary restriction, but one that has been around forever: assert np.dtype(mytype) == np.dtype("O") - with pytest.raises(RuntimeError): - # Registering a second time should fail - create_custom_field_dtype(blueprint, mytype, 0) - def test_custom_structured_dtype_errors(self): class mytype: pass |