| 239 | } |
| 240 | |
| 241 | static PyArray_Descr * |
| 242 | _convert_from_tuple(PyObject *obj, int align) |
| 243 | { |
| 244 | if (PyTuple_GET_SIZE(obj) != 2) { |
| 245 | PyErr_Format(PyExc_TypeError, |
| 246 | "Tuple must have size 2, but has size %zd", |
| 247 | PyTuple_GET_SIZE(obj)); |
| 248 | return NULL; |
| 249 | } |
| 250 | PyArray_Descr *type = _convert_from_any(PyTuple_GET_ITEM(obj, 0), align); |
| 251 | if (type == NULL) { |
| 252 | return NULL; |
| 253 | } |
| 254 | PyObject *val = PyTuple_GET_ITEM(obj,1); |
| 255 | /* try to interpret next item as a type */ |
| 256 | PyArray_Descr *res = _try_convert_from_inherit_tuple(type, val); |
| 257 | if ((PyObject *)res != Py_NotImplemented) { |
| 258 | Py_DECREF(type); |
| 259 | return res; |
| 260 | } |
| 261 | Py_DECREF(res); |
| 262 | /* |
| 263 | * We get here if _try_convert_from_inherit_tuple failed without crashing |
| 264 | */ |
| 265 | if (PyDataType_ISUNSIZED(type)) { |
| 266 | /* interpret next item as a typesize */ |
| 267 | int itemsize = PyArray_PyIntAsInt(PyTuple_GET_ITEM(obj,1)); |
| 268 | |
| 269 | if (error_converting(itemsize)) { |
| 270 | PyErr_SetString(PyExc_ValueError, |
| 271 | "invalid itemsize in generic type tuple"); |
| 272 | Py_DECREF(type); |
| 273 | return NULL; |
| 274 | } |
| 275 | PyArray_DESCR_REPLACE(type); |
| 276 | if (type == NULL) { |
| 277 | return NULL; |
| 278 | } |
| 279 | if (type->type_num == NPY_UNICODE) { |
| 280 | type->elsize = itemsize << 2; |
| 281 | } |
| 282 | else { |
| 283 | type->elsize = itemsize; |
| 284 | } |
| 285 | return type; |
| 286 | } |
| 287 | else if (type->metadata && (PyDict_Check(val) || PyDictProxy_Check(val))) { |
| 288 | /* Assume it's a metadata dictionary */ |
| 289 | if (PyDict_Merge(type->metadata, val, 0) == -1) { |
| 290 | Py_DECREF(type); |
| 291 | return NULL; |
| 292 | } |
| 293 | return type; |
| 294 | } |
| 295 | else { |
| 296 | /* |
| 297 | * interpret next item as shape (if it's a tuple) |
| 298 | * and reset the type to NPY_VOID with |
no test coverage detected