| 3551 | } |
| 3552 | |
| 3553 | NPY_NO_EXPORT PyArray_Descr * |
| 3554 | arraydescr_field_subset_view(PyArray_Descr *self, PyObject *ind) |
| 3555 | { |
| 3556 | int seqlen, i; |
| 3557 | PyObject *fields = NULL; |
| 3558 | PyObject *names = NULL; |
| 3559 | PyArray_Descr *view_dtype; |
| 3560 | |
| 3561 | seqlen = PySequence_Size(ind); |
| 3562 | if (seqlen == -1) { |
| 3563 | return NULL; |
| 3564 | } |
| 3565 | |
| 3566 | fields = PyDict_New(); |
| 3567 | if (fields == NULL) { |
| 3568 | goto fail; |
| 3569 | } |
| 3570 | names = PyTuple_New(seqlen); |
| 3571 | if (names == NULL) { |
| 3572 | goto fail; |
| 3573 | } |
| 3574 | |
| 3575 | for (i = 0; i < seqlen; i++) { |
| 3576 | PyObject *name; |
| 3577 | PyObject *tup; |
| 3578 | |
| 3579 | name = PySequence_GetItem(ind, i); |
| 3580 | if (name == NULL) { |
| 3581 | goto fail; |
| 3582 | } |
| 3583 | |
| 3584 | /* Let the names tuple steal a reference now, so we don't need to |
| 3585 | * decref name if an error occurs further on. |
| 3586 | */ |
| 3587 | PyTuple_SET_ITEM(names, i, name); |
| 3588 | |
| 3589 | tup = PyDict_GetItemWithError(self->fields, name); |
| 3590 | if (tup == NULL) { |
| 3591 | if (!PyErr_Occurred()) { |
| 3592 | PyErr_SetObject(PyExc_KeyError, name); |
| 3593 | } |
| 3594 | goto fail; |
| 3595 | } |
| 3596 | |
| 3597 | /* disallow use of titles as index */ |
| 3598 | if (PyTuple_Size(tup) == 3) { |
| 3599 | PyObject *title = PyTuple_GET_ITEM(tup, 2); |
| 3600 | int titlecmp = PyObject_RichCompareBool(title, name, Py_EQ); |
| 3601 | if (titlecmp < 0) { |
| 3602 | goto fail; |
| 3603 | } |
| 3604 | if (titlecmp == 1) { |
| 3605 | /* if title == name, we were given a title, not a field name */ |
| 3606 | PyErr_SetString(PyExc_KeyError, |
| 3607 | "cannot use field titles in multi-field index"); |
| 3608 | goto fail; |
| 3609 | } |
| 3610 | if (PyDict_SetItem(fields, title, tup) < 0) { |
no test coverage detected