NPY_NO_EXPORT int PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, PyArray_Descr **out_dtype, int string_type) { int i, size; PyArray_Descr *dtype = NULL; PyObject *ip; Py_buffer buffer_view; /* Check if it's an ndarray */ if (PyArray_Check(obj)) { dtype = PyArray_DESCR((PyArrayObject *)obj); Py_INCREF(dtype); goto promote_types; } /* See if it's a python None */ if (obj == Py_None) { dtype = PyArray_DescrFromType(NPY_OBJECT); if (dtype == NULL) { goto fail; } Py_INCREF(dtype); goto promote_types; } /* Check if it's a NumPy scalar */ else if (PyArray_IsScalar(obj, Generic)) { if (!string_type) { dtype = PyArray_DescrFromScalar(obj); if (dtype == NULL) { goto fail; } } else { int itemsize; PyObject *temp; if (string_type == NPY_STRING) { if ((temp = PyObject_Str(obj)) == NULL) { return -1; } #if defined(NPY_PY3K) #if PY_VERSION_HEX >= 0x03030000 itemsize = PyUnicode_GetLength(temp); #else itemsize = PyUnicode_GET_SIZE(temp); #endif #else itemsize = PyString_GET_SIZE(temp); #endif } else if (string_type == NPY_UNICODE) { #if defined(NPY_PY3K) if ((temp = PyObject_Str(obj)) == NULL) { #else if ((temp = PyObject_Unicode(obj)) == NULL) { #endif return -1; } itemsize = PyUnicode_GET_DATA_SIZE(temp); #ifndef Py_UNICODE_WIDE itemsize <<= 1; #endif } else { goto fail; } Py_DECREF(temp); if (*out_dtype != NULL && (*out_dtype)->type_num == string_type && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(string_type); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; } goto promote_types; } /* Check if it's a Python scalar */ dtype = _array_find_python_scalar_type(obj); if (dtype != NULL) { if (string_type) { int itemsize; PyObject *temp; if (string_type == NPY_STRING) { if ((temp = PyObject_Str(obj)) == NULL) { return -1; } #if defined(NPY_PY3K) #if PY_VERSION_HEX >= 0x03030000 itemsize = PyUnicode_GetLength(temp); #else itemsize = PyUnicode_GET_SIZE(temp); #endif #else itemsize = PyString_GET_SIZE(temp); #endif } else if (string_type == NPY_UNICODE) { #if defined(NPY_PY3K) if ((temp = PyObject_Str(obj)) == NULL) { #else if ((temp = PyObject_Unicode(obj)) == NULL) { #endif return -1; } itemsize = PyUnicode_GET_DATA_SIZE(temp); #ifndef Py_UNICODE_WIDE itemsize <<= 1; #endif } else { goto fail; } Py_DECREF(temp); if (*out_dtype != NULL && (*out_dtype)->type_num == string_type && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(string_type); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; } goto promote_types; } /* Check if it's an ASCII string */ if (PyBytes_Check(obj)) { int itemsize = PyString_GET_SIZE(obj); /* If it's already a big enough string, don't bother type promoting */ if (*out_dtype != NULL && (*out_dtype)->type_num == NPY_STRING && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(NPY_STRING); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; goto promote_types; } /* Check if it's a Unicode string */ if (PyUnicode_Check(obj)) { int itemsize = PyUnicode_GET_DATA_SIZE(obj); #ifndef Py_UNICODE_WIDE itemsize <<= 1; #endif /* * If it's already a big enough unicode object, * don't bother type promoting */ if (*out_dtype != NULL && (*out_dtype)->type_num == NPY_UNICODE && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(NPY_UNICODE); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; goto promote_types; } /* PEP 3118 buffer interface */ if (PyObject_CheckBuffer(obj) == 1) { memset(&buffer_view, 0, sizeof(Py_buffer)); if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT|PyBUF_STRIDES) == 0 || PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) { PyErr_Clear(); dtype = _descriptor_from_pep3118_format(buffer_view.format); PyBuffer_Release(&buffer_view); if (dtype) { goto promote_types; } } else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 || PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) { PyErr_Clear(); dtype = PyArray_DescrNewFromType(NPY_VOID); dtype->elsize = buffer_view.itemsize; PyBuffer_Release(&buffer_view); goto promote_types; } else { PyErr_Clear(); } } /* The array interface */ ip = PyArray_GetAttrString_SuppressException(obj, "__array_interface__"); if (ip != NULL) { if (PyDict_Check(ip)) { PyObject *typestr; #if defined(NPY_PY3K) PyObject *tmp = NULL; #endif typestr = PyDict_GetItemString(ip, "typestr"); #if defined(NPY_PY3K) /* Allow unicode type strings */ if (PyUnicode_Check(typestr)) { tmp = PyUnicode_AsASCIIString(typestr); typestr = tmp; } #endif if (typestr && PyBytes_Check(typestr)) { dtype =_array_typedescr_fromstr(PyBytes_AS_STRING(typestr)); #if defined(NPY_PY3K) if (tmp == typestr) { Py_DECREF(tmp); } #endif Py_DECREF(ip); if (dtype == NULL) { goto fail; } goto promote_types; } } Py_DECREF(ip); } /* The array struct interface */ ip = PyArray_GetAttrString_SuppressException(obj, "__array_struct__"); if (ip != NULL) { PyArrayInterface *inter; char buf[40]; if (NpyCapsule_Check(ip)) { inter = (PyArrayInterface *)NpyCapsule_AsVoidPtr(ip); if (inter->two == 2) { PyOS_snprintf(buf, sizeof(buf), "|%c%d", inter->typekind, inter->itemsize); dtype = _array_typedescr_fromstr(buf); Py_DECREF(ip); if (dtype == NULL) { goto fail; } goto promote_types; } } Py_DECREF(ip); } /* The old buffer interface */ #if !defined(NPY_PY3K) if (PyBuffer_Check(obj)) { dtype = PyArray_DescrNewFromType(NPY_VOID); if (dtype == NULL) { goto fail; } dtype->elsize = Py_TYPE(obj)->tp_as_sequence->sq_length(obj); PyErr_Clear(); goto promote_types; } #endif /* The __array__ attribute */ ip = PyArray_GetAttrString_SuppressException(obj, "__array__"); if (ip != NULL) { Py_DECREF(ip); ip = PyObject_CallMethod(obj, "__array__", NULL); if(ip && PyArray_Check(ip)) { dtype = PyArray_DESCR((PyArrayObject *)ip); Py_INCREF(dtype); Py_DECREF(ip); goto promote_types; } Py_XDECREF(ip); if (PyErr_Occurred()) { goto fail; } } /* Not exactly sure what this is about... */ #if !defined(NPY_PY3K) if (PyInstance_Check(obj)) { dtype = _use_default_type(obj); if (dtype == NULL) { goto fail; } else { goto promote_types; } } #endif /* * If we reached the maximum recursion depth without hitting one * of the above cases, the output dtype should be OBJECT */ if (maxdims == 0 || !PySequence_Check(obj)) { if (*out_dtype == NULL || (*out_dtype)->type_num != NPY_OBJECT) { Py_XDECREF(*out_dtype); *out_dtype = PyArray_DescrFromType(NPY_OBJECT); if (*out_dtype == NULL) { return -1; } } return 0; } /* Recursive case */ size = PySequence_Size(obj); if (size < 0) { goto fail; } /* Recursive call for each sequence item */ for (i = 0; i < size; ++i) { int res; ip = PySequence_GetItem(obj, i); if (ip == NULL) { goto fail; } res = PyArray_DTypeFromObjectHelper(ip, maxdims - 1, out_dtype, string_type); if (res < 0) { Py_DECREF(ip); goto fail; } else if (res > 0) { Py_DECREF(ip); return res; } Py_DECREF(ip); } return 0; promote_types: /* Set 'out_dtype' if it's NULL */ if (*out_dtype == NULL) { if (!string_type && dtype->type_num == NPY_STRING) { Py_DECREF(dtype); return RETRY_WITH_STRING; } if (!string_type && dtype->type_num == NPY_UNICODE) { Py_DECREF(dtype); return RETRY_WITH_UNICODE; } *out_dtype = dtype; return 0; } /* Do type promotion with 'out_dtype' */ else { PyArray_Descr *res_dtype = PyArray_PromoteTypes(dtype, *out_dtype); Py_DECREF(dtype); if (res_dtype == NULL) { return -1; } if (!string_type && res_dtype->type_num == NPY_UNICODE && (*out_dtype)->type_num != NPY_UNICODE) { Py_DECREF(res_dtype); return RETRY_WITH_UNICODE; } if (!string_type && res_dtype->type_num == NPY_STRING && (*out_dtype)->type_num != NPY_STRING) { Py_DECREF(res_dtype); return RETRY_WITH_STRING; } Py_DECREF(*out_dtype); *out_dtype = res_dtype; return 0; } fail: Py_XDECREF(*out_dtype); *out_dtype = NULL; return -1; } #undef RETRY_WITH_STRING #undef RETRY_WITH_UNICODE /* new reference */ NPY_NO_EXPORT PyArray_Descr * _array_typedescr_fromstr(char *c_str) { PyArray_Descr *descr = NULL; PyObject *stringobj = PyString_FromString(c_str); if (stringobj == NULL) { return NULL; } if (PyArray_DescrConverter(stringobj, &descr) != NPY_SUCCEED) { Py_DECREF(stringobj); return NULL; } Py_DECREF(stringobj); return descr; } NPY_NO_EXPORT char * index2ptr(PyArrayObject *mp, npy_intp i) { npy_intp dim0; if (PyArray_NDIM(mp) == 0) { PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed"); return NULL; } dim0 = PyArray_DIMS(mp)[0]; if (check_and_adjust_index(&i, dim0, 0) < 0) return NULL; if (i == 0) { return PyArray_DATA(mp); } return PyArray_BYTES(mp)+i*PyArray_STRIDES(mp)[0]; }
/*NUMPY_API * Clip */ NPY_NO_EXPORT PyObject * PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *out) { PyArray_FastClipFunc *func; int outgood = 0, ingood = 0; PyArrayObject *maxa = NULL; PyArrayObject *mina = NULL; PyArrayObject *newout = NULL, *newin = NULL; PyArray_Descr *indescr = NULL, *newdescr = NULL; char *max_data, *min_data; PyObject *zero; /* Treat None the same as NULL */ if (min == Py_None) { min = NULL; } if (max == Py_None) { max = NULL; } if ((max == NULL) && (min == NULL)) { PyErr_SetString(PyExc_ValueError, "array_clip: must set either max or min"); return NULL; } func = PyArray_DESCR(self)->f->fastclip; if (func == NULL || (min != NULL && !PyArray_CheckAnyScalar(min)) || (max != NULL && !PyArray_CheckAnyScalar(max)) || PyArray_ISBYTESWAPPED(self) || (out && PyArray_ISBYTESWAPPED(out))) { return _slow_array_clip(self, min, max, out); } /* Use the fast scalar clip function */ /* First we need to figure out the correct type */ if (min != NULL) { indescr = PyArray_DescrFromObject(min, NULL); if (indescr == NULL) { goto fail; } } if (max != NULL) { newdescr = PyArray_DescrFromObject(max, indescr); Py_XDECREF(indescr); indescr = NULL; if (newdescr == NULL) { goto fail; } } else { /* Steal the reference */ newdescr = indescr; indescr = NULL; } /* * Use the scalar descriptor only if it is of a bigger * KIND than the input array (and then find the * type that matches both). */ if (PyArray_ScalarKind(newdescr->type_num, NULL) > PyArray_ScalarKind(PyArray_DESCR(self)->type_num, NULL)) { indescr = PyArray_PromoteTypes(newdescr, PyArray_DESCR(self)); if (indescr == NULL) { goto fail; } func = indescr->f->fastclip; if (func == NULL) { Py_DECREF(indescr); return _slow_array_clip(self, min, max, out); } } else { indescr = PyArray_DESCR(self); Py_INCREF(indescr); } Py_DECREF(newdescr); newdescr = NULL; if (!PyDataType_ISNOTSWAPPED(indescr)) { PyArray_Descr *descr2; descr2 = PyArray_DescrNewByteorder(indescr, '='); Py_DECREF(indescr); indescr = NULL; if (descr2 == NULL) { goto fail; } indescr = descr2; } /* Convert max to an array */ if (max != NULL) { Py_INCREF(indescr); maxa = (PyArrayObject *)PyArray_FromAny(max, indescr, 0, 0, NPY_ARRAY_DEFAULT, NULL); if (maxa == NULL) { goto fail; } } /* * If we are unsigned, then make sure min is not < 0 * This is to match the behavior of _slow_array_clip * * We allow min and max to go beyond the limits * for other data-types in which case they * are interpreted as their modular counterparts. */ if (min != NULL) { if (PyArray_ISUNSIGNED(self)) { int cmp; zero = PyInt_FromLong(0); cmp = PyObject_RichCompareBool(min, zero, Py_LT); if (cmp == -1) { Py_DECREF(zero); goto fail; } if (cmp == 1) { min = zero; } else { Py_DECREF(zero); Py_INCREF(min); } } else { Py_INCREF(min); } /* Convert min to an array */ Py_INCREF(indescr); mina = (PyArrayObject *)PyArray_FromAny(min, indescr, 0, 0, NPY_ARRAY_DEFAULT, NULL); Py_DECREF(min); if (mina == NULL) { goto fail; } } /* * Check to see if input is single-segment, aligned, * and in native byteorder */ if (PyArray_ISONESEGMENT(self) && PyArray_CHKFLAGS(self, NPY_ARRAY_ALIGNED) && PyArray_ISNOTSWAPPED(self) && (PyArray_DESCR(self) == indescr)) { ingood = 1; } if (!ingood) { int flags; if (PyArray_ISFORTRAN(self)) { flags = NPY_ARRAY_FARRAY; } else { flags = NPY_ARRAY_CARRAY; } Py_INCREF(indescr); newin = (PyArrayObject *)PyArray_FromArray(self, indescr, flags); if (newin == NULL) { goto fail; } } else { newin = self; Py_INCREF(newin); } /* * At this point, newin is a single-segment, aligned, and correct * byte-order array of the correct type * * if ingood == 0, then it is a copy, otherwise, * it is the original input. */ /* * If we have already made a copy of the data, then use * that as the output array */ if (out == NULL && !ingood) { out = newin; } /* * Now, we know newin is a usable array for fastclip, * we need to make sure the output array is available * and usable */ if (out == NULL) { Py_INCREF(indescr); out = (PyArrayObject*)PyArray_NewFromDescr(Py_TYPE(self), indescr, PyArray_NDIM(self), PyArray_DIMS(self), NULL, NULL, PyArray_ISFORTRAN(self), (PyObject *)self); if (out == NULL) { goto fail; } outgood = 1; } else Py_INCREF(out); /* Input is good at this point */ if (out == newin) { outgood = 1; } /* make sure the shape of the output array is the same */ if (!PyArray_SAMESHAPE(newin, out)) { PyErr_SetString(PyExc_ValueError, "clip: Output array must have the" "same shape as the input."); goto fail; } if (!outgood && PyArray_EQUIVALENTLY_ITERABLE( self, out, PyArray_TRIVIALLY_ITERABLE_OP_READ, PyArray_TRIVIALLY_ITERABLE_OP_NOREAD) && PyArray_CHKFLAGS(out, NPY_ARRAY_ALIGNED) && PyArray_ISNOTSWAPPED(out) && PyArray_EquivTypes(PyArray_DESCR(out), indescr)) { outgood = 1; } /* * Do we still not have a suitable output array? * Create one, now. No matter why the array is not suitable a copy has * to be made. This may be just to avoid memory overlap though. */ if (!outgood) { int oflags; if (PyArray_ISFORTRAN(self)) { oflags = NPY_ARRAY_FARRAY; } else { oflags = NPY_ARRAY_CARRAY; } oflags |= (NPY_ARRAY_WRITEBACKIFCOPY | NPY_ARRAY_FORCECAST | NPY_ARRAY_ENSURECOPY); Py_INCREF(indescr); newout = (PyArrayObject*)PyArray_FromArray(out, indescr, oflags); if (newout == NULL) { goto fail; } } else { newout = out; Py_INCREF(newout); } /* Now we can call the fast-clip function */ min_data = max_data = NULL; if (mina != NULL) { min_data = PyArray_DATA(mina); } if (maxa != NULL) { max_data = PyArray_DATA(maxa); } func(PyArray_DATA(newin), PyArray_SIZE(newin), min_data, max_data, PyArray_DATA(newout)); /* Clean up temporary variables */ Py_XDECREF(indescr); Py_XDECREF(newdescr); Py_XDECREF(mina); Py_XDECREF(maxa); Py_DECREF(newin); /* Copy back into out if out was not already a nice array. */ PyArray_ResolveWritebackIfCopy(newout); Py_DECREF(newout); return (PyObject *)out; fail: Py_XDECREF(indescr); Py_XDECREF(newdescr); Py_XDECREF(maxa); Py_XDECREF(mina); Py_XDECREF(newin); PyArray_DiscardWritebackIfCopy(newout); Py_XDECREF(newout); return NULL; }
NPY_NO_EXPORT int PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, PyArray_Descr **out_dtype, int string_type) { int i, size; PyArray_Descr *dtype = NULL; PyObject *ip; Py_buffer buffer_view; /* types for sequence handling */ PyObject ** objects; PyObject * seq; PyTypeObject * common_type; /* Check if it's an ndarray */ if (PyArray_Check(obj)) { dtype = PyArray_DESCR((PyArrayObject *)obj); Py_INCREF(dtype); goto promote_types; } /* See if it's a python None */ if (obj == Py_None) { dtype = PyArray_DescrFromType(NPY_OBJECT); if (dtype == NULL) { goto fail; } Py_INCREF(dtype); goto promote_types; } /* Check if it's a NumPy scalar */ else if (PyArray_IsScalar(obj, Generic)) { if (!string_type) { dtype = PyArray_DescrFromScalar(obj); if (dtype == NULL) { goto fail; } } else { int itemsize; PyObject *temp; if (string_type == NPY_STRING) { if ((temp = PyObject_Str(obj)) == NULL) { return -1; } #if defined(NPY_PY3K) #if PY_VERSION_HEX >= 0x03030000 itemsize = PyUnicode_GetLength(temp); #else itemsize = PyUnicode_GET_SIZE(temp); #endif #else itemsize = PyString_GET_SIZE(temp); #endif } else if (string_type == NPY_UNICODE) { #if defined(NPY_PY3K) if ((temp = PyObject_Str(obj)) == NULL) { #else if ((temp = PyObject_Unicode(obj)) == NULL) { #endif return -1; } itemsize = PyUnicode_GET_DATA_SIZE(temp); #ifndef Py_UNICODE_WIDE itemsize <<= 1; #endif } else { goto fail; } Py_DECREF(temp); if (*out_dtype != NULL && (*out_dtype)->type_num == string_type && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(string_type); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; } goto promote_types; } /* Check if it's a Python scalar */ dtype = _array_find_python_scalar_type(obj); if (dtype != NULL) { if (string_type) { int itemsize; PyObject *temp; if (string_type == NPY_STRING) { if ((temp = PyObject_Str(obj)) == NULL) { return -1; } #if defined(NPY_PY3K) #if PY_VERSION_HEX >= 0x03030000 itemsize = PyUnicode_GetLength(temp); #else itemsize = PyUnicode_GET_SIZE(temp); #endif #else itemsize = PyString_GET_SIZE(temp); #endif } else if (string_type == NPY_UNICODE) { #if defined(NPY_PY3K) if ((temp = PyObject_Str(obj)) == NULL) { #else if ((temp = PyObject_Unicode(obj)) == NULL) { #endif return -1; } itemsize = PyUnicode_GET_DATA_SIZE(temp); #ifndef Py_UNICODE_WIDE itemsize <<= 1; #endif } else { goto fail; } Py_DECREF(temp); if (*out_dtype != NULL && (*out_dtype)->type_num == string_type && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(string_type); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; } goto promote_types; } /* Check if it's an ASCII string */ if (PyBytes_Check(obj)) { int itemsize = PyString_GET_SIZE(obj); /* If it's already a big enough string, don't bother type promoting */ if (*out_dtype != NULL && (*out_dtype)->type_num == NPY_STRING && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(NPY_STRING); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; goto promote_types; } /* Check if it's a Unicode string */ if (PyUnicode_Check(obj)) { int itemsize = PyUnicode_GET_DATA_SIZE(obj); #ifndef Py_UNICODE_WIDE itemsize <<= 1; #endif /* * If it's already a big enough unicode object, * don't bother type promoting */ if (*out_dtype != NULL && (*out_dtype)->type_num == NPY_UNICODE && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(NPY_UNICODE); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; goto promote_types; } /* PEP 3118 buffer interface */ if (PyObject_CheckBuffer(obj) == 1) { memset(&buffer_view, 0, sizeof(Py_buffer)); if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT|PyBUF_STRIDES) == 0 || PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) { PyErr_Clear(); dtype = _descriptor_from_pep3118_format(buffer_view.format); PyBuffer_Release(&buffer_view); if (dtype) { goto promote_types; } } else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 || PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) { PyErr_Clear(); dtype = PyArray_DescrNewFromType(NPY_VOID); dtype->elsize = buffer_view.itemsize; PyBuffer_Release(&buffer_view); goto promote_types; } else { PyErr_Clear(); } } /* The array interface */ ip = PyArray_LookupSpecial_OnInstance(obj, "__array_interface__"); if (ip != NULL) { if (PyDict_Check(ip)) { PyObject *typestr; #if defined(NPY_PY3K) PyObject *tmp = NULL; #endif typestr = PyDict_GetItemString(ip, "typestr"); #if defined(NPY_PY3K) /* Allow unicode type strings */ if (PyUnicode_Check(typestr)) { tmp = PyUnicode_AsASCIIString(typestr); typestr = tmp; } #endif if (typestr && PyBytes_Check(typestr)) { dtype =_array_typedescr_fromstr(PyBytes_AS_STRING(typestr)); #if defined(NPY_PY3K) if (tmp == typestr) { Py_DECREF(tmp); } #endif Py_DECREF(ip); if (dtype == NULL) { goto fail; } goto promote_types; } } Py_DECREF(ip); } /* The array struct interface */ ip = PyArray_LookupSpecial_OnInstance(obj, "__array_struct__"); if (ip != NULL) { PyArrayInterface *inter; char buf[40]; if (NpyCapsule_Check(ip)) { inter = (PyArrayInterface *)NpyCapsule_AsVoidPtr(ip); if (inter->two == 2) { PyOS_snprintf(buf, sizeof(buf), "|%c%d", inter->typekind, inter->itemsize); dtype = _array_typedescr_fromstr(buf); Py_DECREF(ip); if (dtype == NULL) { goto fail; } goto promote_types; } } Py_DECREF(ip); } /* The old buffer interface */ #if !defined(NPY_PY3K) if (PyBuffer_Check(obj)) { dtype = PyArray_DescrNewFromType(NPY_VOID); if (dtype == NULL) { goto fail; } dtype->elsize = Py_TYPE(obj)->tp_as_sequence->sq_length(obj); PyErr_Clear(); goto promote_types; } #endif /* The __array__ attribute */ ip = PyArray_LookupSpecial_OnInstance(obj, "__array__"); if (ip != NULL) { Py_DECREF(ip); ip = PyObject_CallMethod(obj, "__array__", NULL); if(ip && PyArray_Check(ip)) { dtype = PyArray_DESCR((PyArrayObject *)ip); Py_INCREF(dtype); Py_DECREF(ip); goto promote_types; } Py_XDECREF(ip); if (PyErr_Occurred()) { goto fail; } } /* * If we reached the maximum recursion depth without hitting one * of the above cases, and obj isn't a sequence-like object, the output * dtype should be either OBJECT or a user-defined type. * * Note that some libraries define sequence-like classes but want them to * be treated as objects, and they expect numpy to treat it as an object if * __len__ is not defined. */ if (maxdims == 0 || !PySequence_Check(obj) || PySequence_Size(obj) < 0) { // clear any PySequence_Size error, which corrupts further calls to it PyErr_Clear(); if (*out_dtype == NULL || (*out_dtype)->type_num != NPY_OBJECT) { Py_XDECREF(*out_dtype); *out_dtype = PyArray_DescrFromType(NPY_OBJECT); if (*out_dtype == NULL) { return -1; } } return 0; } /* Recursive case, first check the sequence contains only one type */ seq = PySequence_Fast(obj, "Could not convert object to sequence"); if (seq == NULL) { goto fail; } size = PySequence_Fast_GET_SIZE(seq); objects = PySequence_Fast_ITEMS(seq); common_type = size > 0 ? Py_TYPE(objects[0]) : NULL; for (i = 1; i < size; ++i) { if (Py_TYPE(objects[i]) != common_type) { common_type = NULL; break; } } /* all types are the same and scalar, one recursive call is enough */ if (common_type != NULL && !string_type && (common_type == &PyFloat_Type || /* TODO: we could add longs if we add a range check */ #if !defined(NPY_PY3K) common_type == &PyInt_Type || #endif common_type == &PyBool_Type || common_type == &PyComplex_Type)) { size = 1; } /* Recursive call for each sequence item */ for (i = 0; i < size; ++i) { int res = PyArray_DTypeFromObjectHelper(objects[i], maxdims - 1, out_dtype, string_type); if (res < 0) { Py_DECREF(seq); goto fail; } else if (res > 0) { Py_DECREF(seq); return res; } } Py_DECREF(seq); return 0; promote_types: /* Set 'out_dtype' if it's NULL */ if (*out_dtype == NULL) { if (!string_type && dtype->type_num == NPY_STRING) { Py_DECREF(dtype); return RETRY_WITH_STRING; } if (!string_type && dtype->type_num == NPY_UNICODE) { Py_DECREF(dtype); return RETRY_WITH_UNICODE; } *out_dtype = dtype; return 0; } /* Do type promotion with 'out_dtype' */ else { PyArray_Descr *res_dtype = PyArray_PromoteTypes(dtype, *out_dtype); Py_DECREF(dtype); if (res_dtype == NULL) { return -1; } if (!string_type && res_dtype->type_num == NPY_UNICODE && (*out_dtype)->type_num != NPY_UNICODE) { Py_DECREF(res_dtype); return RETRY_WITH_UNICODE; } if (!string_type && res_dtype->type_num == NPY_STRING && (*out_dtype)->type_num != NPY_STRING) { Py_DECREF(res_dtype); return RETRY_WITH_STRING; } Py_DECREF(*out_dtype); *out_dtype = res_dtype; return 0; } fail: Py_XDECREF(*out_dtype); *out_dtype = NULL; return -1; } #undef RETRY_WITH_STRING #undef RETRY_WITH_UNICODE /* new reference */ NPY_NO_EXPORT PyArray_Descr * _array_typedescr_fromstr(char *c_str) { PyArray_Descr *descr = NULL; PyObject *stringobj = PyString_FromString(c_str); if (stringobj == NULL) { return NULL; } if (PyArray_DescrConverter(stringobj, &descr) != NPY_SUCCEED) { Py_DECREF(stringobj); return NULL; } Py_DECREF(stringobj); return descr; } NPY_NO_EXPORT char * index2ptr(PyArrayObject *mp, npy_intp i) { npy_intp dim0; if (PyArray_NDIM(mp) == 0) { PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed"); return NULL; } dim0 = PyArray_DIMS(mp)[0]; if (check_and_adjust_index(&i, dim0, 0, NULL) < 0) return NULL; if (i == 0) { return PyArray_DATA(mp); } return PyArray_BYTES(mp)+i*PyArray_STRIDES(mp)[0]; }
/* * Recursively examines the object to determine an appropriate dtype * to use for converting to an ndarray. * * 'obj' is the object to be converted to an ndarray. * * 'maxdims' is the maximum recursion depth. * * 'out_contains_na' gets set to 1 if an np.NA object is encountered. * The NA does not affect the dtype produced, so if this is set to 1 * and the result is for an array without NA support, the dtype should * be switched to NPY_OBJECT. When adding multi-NA support, this should * also signal whether just regular NAs or NAs with payloads were seen. * * 'out_dtype' should be either NULL or a minimal starting dtype when * the function is called. It is updated with the results of type * promotion. This dtype does not get updated when processing NA objects. * This is reset to NULL on failure. * * Returns 0 on success, -1 on failure. */ NPY_NO_EXPORT int PyArray_DTypeFromObject(PyObject *obj, int maxdims, int *out_contains_na, PyArray_Descr **out_dtype) { int i, size; PyArray_Descr *dtype = NULL; PyObject *ip; #if PY_VERSION_HEX >= 0x02060000 Py_buffer buffer_view; #endif /* Check if it's an ndarray */ if (PyArray_Check(obj)) { /* Check for any NAs in the array */ int containsna = PyArray_ContainsNA((PyArrayObject *)obj, NULL, NULL); if (containsna == -1) { goto fail; } else if (containsna) { *out_contains_na = 1; } dtype = PyArray_DESCR((PyArrayObject *)obj); Py_INCREF(dtype); goto promote_types; } /* Check if it's a NumPy scalar */ if (PyArray_IsScalar(obj, Generic)) { dtype = PyArray_DescrFromScalar(obj); if (dtype == NULL) { goto fail; } goto promote_types; } /* Check if it's a Python scalar */ dtype = _array_find_python_scalar_type(obj); if (dtype != NULL) { goto promote_types; } /* Check if it's an NA */ if (NpyNA_Check(obj)) { *out_contains_na = 1; return 0; } /* Check if it's an ASCII string */ if (PyBytes_Check(obj)) { int itemsize = PyString_GET_SIZE(obj); /* If it's already a big enough string, don't bother type promoting */ if (*out_dtype != NULL && (*out_dtype)->type_num == NPY_STRING && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(NPY_STRING); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; goto promote_types; } /* Check if it's a Unicode string */ if (PyUnicode_Check(obj)) { int itemsize = PyUnicode_GET_DATA_SIZE(obj); #ifndef Py_UNICODE_WIDE itemsize <<= 1; #endif /* * If it's already a big enough unicode object, * don't bother type promoting */ if (*out_dtype != NULL && (*out_dtype)->type_num == NPY_UNICODE && (*out_dtype)->elsize >= itemsize) { return 0; } dtype = PyArray_DescrNewFromType(NPY_UNICODE); if (dtype == NULL) { goto fail; } dtype->elsize = itemsize; goto promote_types; } #if PY_VERSION_HEX >= 0x02060000 /* PEP 3118 buffer interface */ memset(&buffer_view, 0, sizeof(Py_buffer)); if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT|PyBUF_STRIDES) == 0 || PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) { PyErr_Clear(); dtype = _descriptor_from_pep3118_format(buffer_view.format); PyBuffer_Release(&buffer_view); if (dtype) { goto promote_types; } } else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 || PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) { PyErr_Clear(); dtype = PyArray_DescrNewFromType(NPY_VOID); dtype->elsize = buffer_view.itemsize; PyBuffer_Release(&buffer_view); goto promote_types; } else { PyErr_Clear(); } #endif /* The array interface */ ip = PyObject_GetAttrString(obj, "__array_interface__"); if (ip != NULL) { if (PyDict_Check(ip)) { PyObject *typestr; typestr = PyDict_GetItemString(ip, "typestr"); if (typestr && PyString_Check(typestr)) { dtype =_array_typedescr_fromstr(PyString_AS_STRING(typestr)); Py_DECREF(ip); if (dtype == NULL) { goto fail; } goto promote_types; } } Py_DECREF(ip); } else { PyErr_Clear(); } /* The array struct interface */ ip = PyObject_GetAttrString(obj, "__array_struct__"); if (ip != NULL) { PyArrayInterface *inter; char buf[40]; if (NpyCapsule_Check(ip)) { inter = (PyArrayInterface *)NpyCapsule_AsVoidPtr(ip); if (inter->two == 2) { PyOS_snprintf(buf, sizeof(buf), "|%c%d", inter->typekind, inter->itemsize); dtype = _array_typedescr_fromstr(buf); Py_DECREF(ip); if (dtype == NULL) { goto fail; } goto promote_types; } } Py_DECREF(ip); } else { PyErr_Clear(); } /* The old buffer interface */ #if !defined(NPY_PY3K) if (PyBuffer_Check(obj)) { dtype = PyArray_DescrNewFromType(NPY_VOID); if (dtype == NULL) { goto fail; } dtype->elsize = Py_TYPE(obj)->tp_as_sequence->sq_length(obj); PyErr_Clear(); goto promote_types; } #endif /* The __array__ attribute */ if (PyObject_HasAttrString(obj, "__array__")) { ip = PyObject_CallMethod(obj, "__array__", NULL); if(ip && PyArray_Check(ip)) { dtype = PyArray_DESCR((PyArrayObject *)ip); Py_INCREF(dtype); Py_DECREF(ip); goto promote_types; } Py_XDECREF(ip); if (PyErr_Occurred()) { goto fail; } } /* Not exactly sure what this is about... */ #if !defined(NPY_PY3K) if (PyInstance_Check(obj)) { dtype = _use_default_type(obj); if (dtype == NULL) { goto fail; } else { goto promote_types; } } #endif /* * If we reached the maximum recursion depth without hitting one * of the above cases, the output dtype should be OBJECT */ if (maxdims == 0 || !PySequence_Check(obj)) { if (*out_dtype == NULL || (*out_dtype)->type_num != NPY_OBJECT) { Py_XDECREF(*out_dtype); *out_dtype = PyArray_DescrFromType(NPY_OBJECT); if (*out_dtype == NULL) { return -1; } } return 0; } /* Recursive case */ size = PySequence_Size(obj); if (size < 0) { goto fail; } /* Recursive call for each sequence item */ for (i = 0; i < size; ++i) { ip = PySequence_GetItem(obj, i); if (ip==NULL) { goto fail; } if (PyArray_DTypeFromObject(ip, maxdims - 1, out_contains_na, out_dtype) < 0) { Py_DECREF(ip); goto fail; } Py_DECREF(ip); } return 0; promote_types: /* Set 'out_dtype' if it's NULL */ if (*out_dtype == NULL) { *out_dtype = dtype; return 0; } /* Do type promotion with 'out_dtype' */ else { PyArray_Descr *res_dtype = PyArray_PromoteTypes(dtype, *out_dtype); Py_DECREF(dtype); if (res_dtype == NULL) { return -1; } Py_DECREF(*out_dtype); *out_dtype = res_dtype; return 0; } fail: Py_XDECREF(*out_dtype); *out_dtype = NULL; return -1; }