* Validate that the input is usable to create a new ArrayMethod. * * @param spec * @return 0 on success -1 on error. */
| 173 | * @return 0 on success -1 on error. |
| 174 | */ |
| 175 | static int |
| 176 | validate_spec(PyArrayMethod_Spec *spec) |
| 177 | { |
| 178 | int nargs = spec->nin + spec->nout; |
| 179 | /* Check the passed spec for invalid fields/values */ |
| 180 | if (spec->nin < 0 || spec->nout < 0 || nargs > NPY_MAXARGS) { |
| 181 | PyErr_Format(PyExc_ValueError, |
| 182 | "ArrayMethod inputs and outputs must be greater zero and" |
| 183 | "not exceed %d. (method: %s)", NPY_MAXARGS, spec->name); |
| 184 | return -1; |
| 185 | } |
| 186 | switch (spec->casting) { |
| 187 | case NPY_NO_CASTING: |
| 188 | case NPY_EQUIV_CASTING: |
| 189 | case NPY_SAFE_CASTING: |
| 190 | case NPY_SAME_KIND_CASTING: |
| 191 | case NPY_UNSAFE_CASTING: |
| 192 | break; |
| 193 | default: |
| 194 | if (spec->casting != -1) { |
| 195 | PyErr_Format(PyExc_TypeError, |
| 196 | "ArrayMethod has invalid casting `%d`. (method: %s)", |
| 197 | spec->casting, spec->name); |
| 198 | return -1; |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | for (int i = 0; i < nargs; i++) { |
| 203 | /* |
| 204 | * Note that we could allow for output dtypes to not be specified |
| 205 | * (the array-method would have to make sure to support this). |
| 206 | * We could even allow for some dtypes to be abstract. |
| 207 | * For now, assume that this is better handled in a promotion step. |
| 208 | * One problem with providing all DTypes is the definite need to |
| 209 | * hold references. We probably, eventually, have to implement |
| 210 | * traversal and trust the GC to deal with it. |
| 211 | */ |
| 212 | if (spec->dtypes[i] == NULL) { |
| 213 | PyErr_Format(PyExc_TypeError, |
| 214 | "ArrayMethod must provide all input and output DTypes. " |
| 215 | "(method: %s)", spec->name); |
| 216 | return -1; |
| 217 | } |
| 218 | if (!PyObject_TypeCheck(spec->dtypes[i], &PyArrayDTypeMeta_Type)) { |
| 219 | PyErr_Format(PyExc_TypeError, |
| 220 | "ArrayMethod provided object %R is not a DType." |
| 221 | "(method: %s)", spec->dtypes[i], spec->name); |
| 222 | return -1; |
| 223 | } |
| 224 | if (NPY_DT_is_abstract(spec->dtypes[i])) { |
| 225 | PyErr_Format(PyExc_TypeError, |
| 226 | "abstract DType %S are currently not supported." |
| 227 | "(method: %s)", spec->dtypes[i], spec->name); |
| 228 | return -1; |
| 229 | } |
| 230 | } |
| 231 | return 0; |
| 232 | } |
no outgoing calls
no test coverage detected