Repository: numpy/numpy
File: numpy/_core/src/multiarray/ctors.c (C)

Code before:
 * Steals a reference to newtype --- which can be NULL
 */
NPY_NO_EXPORT PyObject *
PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
                int max_depth, int flags, PyObject *context)
{
    npy_dtype_info dt_info = {NULL, NULL};

    int res = PyArray_ExtractDTypeAndDescriptor(
        newtype, &dt_info.descr, &dt_info.dtype);

    Py_XDECREF(newtype);

    if (res < 0) {
        Py_XDECREF(dt_info.descr);
        Py_XDECREF(dt_info.dtype);
        return NULL;
    }

    if (max_depth == 0 || max_depth > NPY_MAXDIMS) {
        max_depth = NPY_MAXDIMS;
    }

    int was_scalar;
    PyObject* ret =  PyArray_FromAny_int(
            op, dt_info.descr, dt_info.dtype,
            min_depth, max_depth, flags, context, &was_scalar);

    Py_XDECREF(dt_info.descr);
    Py_XDECREF(dt_info.dtype);
    return ret;
}

/*
 * Internal version of PyArray_FromAny that accepts a dtypemeta. Borrows
 * references to the descriptor and dtype.
 *
 * The `was_scalar` output returns 1 when the object was a "scalar".
 * This means it was:
 * - Recognized as a scalar by a/the dtype.  This can be DType specific,
 *   for example a tuple may be a scalar, but only for structured dtypes.
 * - Anything not recognized as an instance of a DType's scalar type but also not
 *   convertible to an array.  (no __array__ protocol, etc.)
 *   these must map to `dtype=object` (if a dtype wasn't specified).
 */
NPY_NO_EXPORT PyObject *
PyArray_FromAny_int(PyObject *op, PyArray_Descr *in_descr,
                    PyArray_DTypeMeta *in_DType, int min_depth, int max_depth,
                    int flags, PyObject *context, int *was_scalar)
{
    /*

Review comment (suggestion):
This would not be worth doing if there was nothing else, but since we need to do the docs, maybe worth putting in a comment, say along the lines of
```
/*
 * The` internal implementation treats 0 as actually wanting a zero-dimensional
 * array, but the API for this function has typically treated it as "anything is fine",
 * so convert. TODO: should we use another value as a placeholder instead?
 */
```

Code after:
 * Steals a reference to newtype --- which can be NULL
 */
NPY_NO_EXPORT PyObject *
PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
                int max_depth, int flags, PyObject *context)
{
    npy_dtype_info dt_info = {NULL, NULL};

    int res = PyArray_ExtractDTypeAndDescriptor(
        newtype, &dt_info.descr, &dt_info.dtype);

    Py_XDECREF(newtype);

    if (res < 0) {
        Py_XDECREF(dt_info.descr);
        Py_XDECREF(dt_info.dtype);
        return NULL;
    }

    /*
     * The internal implementation treats 0 as actually wanting a zero-dimensional
     * array, but the API for this function has typically treated it as
     * "anything is fine", so convert here.
     * TODO: should we use another value as a placeholder instead?
     */
    if (max_depth == 0 || max_depth > NPY_MAXDIMS) {
        max_depth = NPY_MAXDIMS;
    }

    int was_scalar;
    PyObject* ret =  PyArray_FromAny_int(
            op, dt_info.descr, dt_info.dtype,
            min_depth, max_depth, flags, context, &was_scalar);

    Py_XDECREF(dt_info.descr);
    Py_XDECREF(dt_info.dtype);
    return ret;
}

/*
 * Internal version of PyArray_FromAny that accepts a dtypemeta. Borrows
 * references to the descriptor and dtype.
 *
 * The `was_scalar` output returns 1 when the object was a "scalar".
 * This means it was:
 * - Recognized as a scalar by a/the dtype.  This can be DType specific,
 *   for example a tuple may be a scalar, but only for structured dtypes.
 * - Anything not recognized as an instance of a DType's scalar type but also not
 *   convertible to an array.  (no __array__ protocol, etc.)
 *   these must map to `dtype=object` (if a dtype wasn't specified).
 */