* This function analyzes the input arguments and determines an appropriate * method (__array_prepare__ or __array_wrap__) function to call, taking it * from the input with the highest priority. Return NULL if no argument * defines the method. */
| 186 | * defines the method. |
| 187 | */ |
| 188 | static PyObject* |
| 189 | _find_array_method(PyObject *args, PyObject *method_name) |
| 190 | { |
| 191 | int i, n_methods; |
| 192 | PyObject *obj; |
| 193 | PyObject *with_method[NPY_MAXARGS], *methods[NPY_MAXARGS]; |
| 194 | PyObject *method = NULL; |
| 195 | |
| 196 | n_methods = 0; |
| 197 | for (i = 0; i < PyTuple_GET_SIZE(args); i++) { |
| 198 | obj = PyTuple_GET_ITEM(args, i); |
| 199 | if (PyArray_CheckExact(obj) || PyArray_IsAnyScalar(obj)) { |
| 200 | continue; |
| 201 | } |
| 202 | method = PyObject_GetAttr(obj, method_name); |
| 203 | if (method) { |
| 204 | if (PyCallable_Check(method)) { |
| 205 | with_method[n_methods] = obj; |
| 206 | methods[n_methods] = method; |
| 207 | ++n_methods; |
| 208 | } |
| 209 | else { |
| 210 | Py_DECREF(method); |
| 211 | method = NULL; |
| 212 | } |
| 213 | } |
| 214 | else { |
| 215 | PyErr_Clear(); |
| 216 | } |
| 217 | } |
| 218 | if (n_methods > 0) { |
| 219 | /* If we have some methods defined, find the one of highest priority */ |
| 220 | method = methods[0]; |
| 221 | if (n_methods > 1) { |
| 222 | double maxpriority = PyArray_GetPriority(with_method[0], |
| 223 | NPY_PRIORITY); |
| 224 | for (i = 1; i < n_methods; ++i) { |
| 225 | double priority = PyArray_GetPriority(with_method[i], |
| 226 | NPY_PRIORITY); |
| 227 | if (priority > maxpriority) { |
| 228 | maxpriority = priority; |
| 229 | Py_DECREF(method); |
| 230 | method = methods[i]; |
| 231 | } |
| 232 | else { |
| 233 | Py_DECREF(methods[i]); |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | return method; |
| 239 | } |
| 240 | |
| 241 | /* |
| 242 | * Returns an incref'ed pointer to the proper __array_prepare__/__array_wrap__ |
no test coverage detected