diff options
author | Sebastian Berg <sebastian@sipsolutions.net> | 2020-01-10 11:51:26 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-10 11:51:26 -0600 |
commit | c4d5e12879c19c2655b5620fa1c18242b14d5141 (patch) | |
tree | 4ebf3d3f002302f87b217035fbaa39dd12ff18e7 /numpy | |
parent | 624d34cbda2f8f7614733743f028c0dd6a5c9952 (diff) | |
parent | 74df40540001011fc0cad5c2a1a14947cba037f8 (diff) | |
download | numpy-c4d5e12879c19c2655b5620fa1c18242b14d5141.tar.gz |
Merge pull request #15300 from eric-wieser/tidy-dtype-ctors-try_convert
MAINT: Refactor dtype conversion functions to be more similar
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/descriptor.c | 124 | ||||
-rw-r--r-- | numpy/core/src/multiarray/descriptor.h | 4 | ||||
-rw-r--r-- | numpy/core/src/multiarray/scalarapi.c | 15 |
3 files changed, 76 insertions, 67 deletions
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c index 2ab090e74..efa53696b 100644 --- a/numpy/core/src/multiarray/descriptor.c +++ b/numpy/core/src/multiarray/descriptor.c @@ -49,7 +49,7 @@ _report_generic_error(void) { } static PyArray_Descr * -_use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag); +_try_convert_from_inherit_tuple(PyArray_Descr *type, PyObject *newobj); static PyArray_Descr * _convert_from_any(PyObject *obj, int align); @@ -65,12 +65,22 @@ _arraydescr_run_converter(PyObject *arg, int align) return type; } +/* + * This function creates a dtype object when the object is a ctypes subclass. + * + * Returns `Py_NotImplemented` if the type is not a ctypes subclass. + */ static PyArray_Descr * -_arraydescr_from_ctypes_type(PyTypeObject *type) +_try_convert_from_ctypes_type(PyTypeObject *type) { PyObject *_numpy_dtype_ctypes; PyObject *res; + if (!npy_ctypes_check(type)) { + Py_INCREF(Py_NotImplemented); + return (PyArray_Descr *)Py_NotImplemented; + } + /* Call the python function of the same name. */ _numpy_dtype_ctypes = PyImport_ImportModule("numpy.core._dtype_ctypes"); if (_numpy_dtype_ctypes == NULL) { @@ -95,25 +105,21 @@ _arraydescr_from_ctypes_type(PyTypeObject *type) return (PyArray_Descr *)res; } +static PyArray_Descr * +_convert_from_any(PyObject *obj, int align); + /* * This function creates a dtype object when the object has a "dtype" attribute, * and it can be converted to a dtype object. * - * Returns a new reference to a dtype object, or NULL - * if this is not possible. - * When the return value is true, the dtype attribute should have been used - * and parsed. Currently the only failure mode for a 1 return is a - * RecursionError and the descriptor is set to NULL. - * When the return value is false, no error will be set. + * Returns `Py_NotImplemented` if this is not possible. + * Currently the only failure mode for a NULL return is a RecursionError. */ -int -_arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr) +static PyArray_Descr * +_try_convert_from_dtype_attr(PyObject *obj) { - PyObject *dtypedescr; - int ret; - /* For arbitrary objects that have a "dtype" attribute */ - dtypedescr = PyObject_GetAttrString(obj, "dtype"); + PyObject *dtypedescr = PyObject_GetAttrString(obj, "dtype"); if (dtypedescr == NULL) { /* * This can be reached due to recursion limit being hit while fetching @@ -126,10 +132,11 @@ _arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr) " while trying to convert the given data type from its " "`.dtype` attribute.") != 0) { Py_DECREF(dtypedescr); - return 1; + return NULL; } - ret = PyArray_DescrConverter(dtypedescr, newdescr); + PyArray_Descr *newdescr; + int ret = PyArray_DescrConverter(dtypedescr, &newdescr); Py_DECREF(dtypedescr); Py_LeaveRecursiveCall(); @@ -137,15 +144,23 @@ _arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr) goto fail; } - return 1; + return newdescr; fail: /* Ignore all but recursion errors, to give ctypes a full try. */ if (!PyErr_ExceptionMatches(PyExc_RecursionError)) { PyErr_Clear(); - return 0; + Py_INCREF(Py_NotImplemented); + return (PyArray_Descr *)Py_NotImplemented; } - return 1; + return NULL; +} + +/* Expose to another file with a prefixed name */ +NPY_NO_EXPORT PyArray_Descr * +_arraydescr_try_convert_from_dtype_attr(PyObject *obj) +{ + return _try_convert_from_dtype_attr(obj); } /* @@ -257,16 +272,14 @@ _convert_from_tuple(PyObject *obj, int align) } PyObject *val = PyTuple_GET_ITEM(obj,1); /* try to interpret next item as a type */ - int errflag; - PyArray_Descr *res = _use_inherit(type, val, &errflag); - if (res || errflag) { + PyArray_Descr *res = _try_convert_from_inherit_tuple(type, val); + if ((PyObject *)res != Py_NotImplemented) { Py_DECREF(type); return res; } - PyErr_Clear(); + Py_DECREF(res); /* - * We get here if res was NULL but errflag wasn't set - * --- i.e. the conversion to a data-descr failed in _use_inherit + * We get here if _try_convert_from_inherit_tuple failed without crashing */ if (PyDataType_ISUNSIZED(type)) { /* interpret next item as a typesize */ @@ -757,7 +770,7 @@ _is_tuple_of_integers(PyObject *obj) } /* - * helper function for _use_inherit to disallow dtypes of the form + * helper function for _try_convert_from_inherit_tuple to disallow dtypes of the form * (old_dtype, new_dtype) where either of the dtypes contains python * objects - these dtypes are not useful and can be a source of segfaults, * when an attempt is made to interpret a python object as a different dtype @@ -818,20 +831,24 @@ fail: * a['real'] and a['imag'] to an int32 array. * * leave type reference alone + * + * Returns `Py_NotImplemented` if the second tuple item is not + * appropriate. */ static PyArray_Descr * -_use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag) +_try_convert_from_inherit_tuple(PyArray_Descr *type, PyObject *newobj) { PyArray_Descr *new; PyArray_Descr *conv; - *errflag = 0; if (PyArray_IsScalar(newobj, Integer) || _is_tuple_of_integers(newobj) || !PyArray_DescrConverter(newobj, &conv)) { - return NULL; + /* PyArray_DescrConverter may have set an exception, which we ignore */ + PyErr_Clear(); + Py_INCREF(Py_NotImplemented); + return (PyArray_Descr *)Py_NotImplemented; } - *errflag = 1; new = PyArray_DescrNew(type); if (new == NULL) { goto fail; @@ -866,7 +883,6 @@ _use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag) } new->flags = conv->flags; Py_DECREF(conv); - *errflag = 0; return new; fail: @@ -982,7 +998,7 @@ validate_object_field_overlap(PyArray_Descr *dtype) * then it will be checked for conformity and used directly. */ static PyArray_Descr * -_use_fields_dict(PyObject *obj, int align) +_convert_from_field_dict(PyObject *obj, int align) { PyObject *_numpy_internal; PyArray_Descr *res; @@ -1015,7 +1031,7 @@ _convert_from_dict(PyObject *obj, int align) Py_DECREF(fields); /* XXX should check this is a KeyError */ PyErr_Clear(); - return _use_fields_dict(obj, align); + return _convert_from_field_dict(obj, align); } PyObject *descrs = PyMapping_GetItemString(obj, "formats"); if (descrs == NULL) { @@ -1023,7 +1039,7 @@ _convert_from_dict(PyObject *obj, int align) /* XXX should check this is a KeyError */ PyErr_Clear(); Py_DECREF(names); - return _use_fields_dict(obj, align); + return _convert_from_field_dict(obj, align); } int n = PyObject_Length(names); PyObject *offsets = PyMapping_GetItemString(obj, "offsets"); @@ -1364,25 +1380,22 @@ _convert_from_type(PyObject *obj) { return PyArray_DescrFromType(NPY_VOID); } else { - PyArray_Descr *at = NULL; - if (_arraydescr_from_dtype_attr(obj, &at)) { - /* - * Using dtype attribute, *at may be NULL if a - * RecursionError occurred. - */ - if (at == NULL) { - return NULL; - } - return at; + PyArray_Descr *ret = _try_convert_from_dtype_attr(obj); + if ((PyObject *)ret != Py_NotImplemented) { + return ret; } + Py_DECREF(ret); + /* - * Note: this comes after _arraydescr_from_dtype_attr because the ctypes + * Note: this comes after _try_convert_from_dtype_attr because the ctypes * type might override the dtype if numpy does not otherwise * support it. */ - if (npy_ctypes_check(typ)) { - return _arraydescr_from_ctypes_type(typ); + ret = _try_convert_from_ctypes_type(typ); + if ((PyObject *)ret != Py_NotImplemented) { + return ret; } + Py_DECREF(ret); /* All other classes are treated as object */ return PyArray_DescrFromType(NPY_OBJECT); @@ -1445,22 +1458,21 @@ _convert_from_any(PyObject *obj, int align) return NULL; } else { - PyArray_Descr *ret; - if (_arraydescr_from_dtype_attr(obj, &ret)) { - /* - * Using dtype attribute, ret may be NULL if a - * RecursionError occurred. - */ + PyArray_Descr *ret = _try_convert_from_dtype_attr(obj); + if ((PyObject *)ret != Py_NotImplemented) { return ret; } + Py_DECREF(ret); /* - * Note: this comes after _arraydescr_from_dtype_attr because the ctypes + * Note: this comes after _try_convert_from_dtype_attr because the ctypes * type might override the dtype if numpy does not otherwise * support it. */ - if (npy_ctypes_check(Py_TYPE(obj))) { - return _arraydescr_from_ctypes_type(Py_TYPE(obj)); + ret = _try_convert_from_ctypes_type(Py_TYPE(obj)); + if ((PyObject *)ret != Py_NotImplemented) { + return ret; } + Py_DECREF(ret); _report_generic_error(); return NULL; } diff --git a/numpy/core/src/multiarray/descriptor.h b/numpy/core/src/multiarray/descriptor.h index fe7dc6f9b..fc9e0895b 100644 --- a/numpy/core/src/multiarray/descriptor.h +++ b/numpy/core/src/multiarray/descriptor.h @@ -7,8 +7,8 @@ NPY_NO_EXPORT PyObject *arraydescr_protocol_descr_get(PyArray_Descr *self); NPY_NO_EXPORT PyObject * array_set_typeDict(PyObject *NPY_UNUSED(ignored), PyObject *args); -int -_arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr); +NPY_NO_EXPORT PyArray_Descr * +_arraydescr_try_convert_from_dtype_attr(PyObject *obj); NPY_NO_EXPORT int diff --git a/numpy/core/src/multiarray/scalarapi.c b/numpy/core/src/multiarray/scalarapi.c index 3e5e01e01..3a66df454 100644 --- a/numpy/core/src/multiarray/scalarapi.c +++ b/numpy/core/src/multiarray/scalarapi.c @@ -425,14 +425,10 @@ PyArray_ScalarFromObject(PyObject *object) NPY_NO_EXPORT PyArray_Descr * PyArray_DescrFromTypeObject(PyObject *type) { - int typenum; - PyArray_Descr *new, *conv = NULL; - /* if it's a builtin type, then use the typenumber */ - typenum = _typenum_fromtypeobj(type,1); + int typenum = _typenum_fromtypeobj(type,1); if (typenum != NPY_NOTYPE) { - new = PyArray_DescrFromType(typenum); - return new; + return PyArray_DescrFromType(typenum); } /* Check the generic types */ @@ -470,11 +466,12 @@ PyArray_DescrFromTypeObject(PyObject *type) /* Do special thing for VOID sub-types */ if (PyType_IsSubtype((PyTypeObject *)type, &PyVoidArrType_Type)) { - new = PyArray_DescrNewFromType(NPY_VOID); + PyArray_Descr *new = PyArray_DescrNewFromType(NPY_VOID); if (new == NULL) { return NULL; } - if (_arraydescr_from_dtype_attr(type, &conv)) { + PyArray_Descr *conv = _arraydescr_try_convert_from_dtype_attr(type); + if ((PyObject *)conv != Py_NotImplemented) { if (conv == NULL) { Py_DECREF(new); return NULL; @@ -486,8 +483,8 @@ PyArray_DescrFromTypeObject(PyObject *type) new->elsize = conv->elsize; new->subarray = conv->subarray; conv->subarray = NULL; - Py_DECREF(conv); } + Py_DECREF(conv); Py_XDECREF(new->typeobj); new->typeobj = (PyTypeObject *)type; Py_INCREF(type); |