* Finish conversion parsing of the DType signature. NumPy always only * honored the type number for passed in descriptors/dtypes. * The `dtype` argument is interpreted as the first output DType (not * descriptor). * Unlike the dtype of an `out` array, it influences loop selection! * * It is the callers responsibility to clean `signature` and NULL it before * calling. */
| 4395 | * calling. |
| 4396 | */ |
| 4397 | static int |
| 4398 | _get_fixed_signature(PyUFuncObject *ufunc, |
| 4399 | PyObject *dtype_obj, PyObject *signature_obj, |
| 4400 | PyArray_DTypeMeta **signature) |
| 4401 | { |
| 4402 | if (dtype_obj == NULL && signature_obj == NULL) { |
| 4403 | return 0; |
| 4404 | } |
| 4405 | |
| 4406 | int nin = ufunc->nin, nout = ufunc->nout, nop = nin + nout; |
| 4407 | |
| 4408 | if (dtype_obj != NULL) { |
| 4409 | if (dtype_obj == Py_None) { |
| 4410 | /* If `dtype=None` is passed, no need to do anything */ |
| 4411 | return 0; |
| 4412 | } |
| 4413 | if (nout == 0) { |
| 4414 | /* This may be allowed (NumPy does not do this)? */ |
| 4415 | PyErr_SetString(PyExc_TypeError, |
| 4416 | "Cannot provide `dtype` when a ufunc has no outputs"); |
| 4417 | return -1; |
| 4418 | } |
| 4419 | PyArray_DTypeMeta *dtype = _get_dtype(dtype_obj); |
| 4420 | if (dtype == NULL) { |
| 4421 | return -1; |
| 4422 | } |
| 4423 | for (int i = nin; i < nop; i++) { |
| 4424 | Py_INCREF(dtype); |
| 4425 | signature[i] = dtype; |
| 4426 | } |
| 4427 | Py_DECREF(dtype); |
| 4428 | return 0; |
| 4429 | } |
| 4430 | |
| 4431 | assert(signature_obj != NULL); |
| 4432 | /* Fill in specified_types from the tuple or string (signature_obj) */ |
| 4433 | if (PyTuple_Check(signature_obj)) { |
| 4434 | Py_ssize_t n = PyTuple_GET_SIZE(signature_obj); |
| 4435 | if (n == 1 && nop != 1) { |
| 4436 | /* |
| 4437 | * Special handling, because we deprecate this path. The path |
| 4438 | * probably mainly existed since the `dtype=obj` was passed through |
| 4439 | * as `(obj,)` and parsed later. |
| 4440 | */ |
| 4441 | if (PyTuple_GET_ITEM(signature_obj, 0) == Py_None) { |
| 4442 | PyErr_SetString(PyExc_TypeError, |
| 4443 | "a single item type tuple cannot contain None."); |
| 4444 | return -1; |
| 4445 | } |
| 4446 | if (DEPRECATE("The use of a length 1 tuple for the ufunc " |
| 4447 | "`signature` is deprecated. Use `dtype` or fill the" |
| 4448 | "tuple with `None`s.") < 0) { |
| 4449 | return -1; |
| 4450 | } |
| 4451 | /* Use the same logic as for `dtype=` */ |
| 4452 | return _get_fixed_signature(ufunc, |
| 4453 | PyTuple_GET_ITEM(signature_obj, 0), NULL, signature); |
| 4454 | } |
no test coverage detected