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

Code before:
 * 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)
{
    /*
     * This is the main code to make a NumPy array from a Python
     * Object.  It is called from many different places.
     */
    PyArrayObject *arr = NULL, *ret = NULL;
    PyArray_Descr *dtype = NULL;
    coercion_cache_obj *cache = NULL;
    int ndim = 0;
    npy_intp dims[NPY_MAXDIMS];

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

    if (context != NULL) {
        PyErr_SetString(PyExc_RuntimeError, "'context' must be NULL");
        return NULL;
    }

    // Default is copy = None
    int copy = -1;
    int was_copied_by__array__ = 0;

    if (flags & NPY_ARRAY_ENSURENOCOPY) {
        copy = 0;
    } else if (flags & NPY_ARRAY_ENSURECOPY) {
        copy = 1;
    }

    Py_BEGIN_CRITICAL_SECTION(op);

    ndim = PyArray_DiscoverDTypeAndShape(
            op, max_depth, dims, &cache, in_DType, in_descr, &dtype,
            copy, &was_copied_by__array__);

    if (ndim < 0) {

Review comment (suggestion):
To support actually using `max_depth = 0` as a real option, the check here would need to be removed.

But that means adjusting code that calls it. The main user is `PyArray_FromAny` (in `ctors.c` as well), which would then need this `if` statement (indeed, perhaps the whole statement should be moved there; it is not unreasonable to assume that for internal calls the values are known to be good).

One other user is `PyArray_CheckFromAny_int` (also in`ctors.c`), though logically there also perhaps `PyArray_CheckFromAny` is the one that should be adjusted.

The final user seems to be `scalartypes.c.src` -- there one could just replace the 0 with `NPY_MAX_DIMS`.

Code after:
            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)
{
    /*
     * This is the main code to make a NumPy array from a Python
     * Object.  It is called from many different places.
     */
    PyArrayObject *arr = NULL, *ret = NULL;
    PyArray_Descr *dtype = NULL;
    coercion_cache_obj *cache = NULL;
    int ndim = 0;
    npy_intp dims[NPY_MAXDIMS];

    if (context != NULL) {
        PyErr_SetString(PyExc_RuntimeError, "'context' must be NULL");
        return NULL;
    }

    // Default is copy = None
    int copy = -1;
    int was_copied_by__array__ = 0;

    if (flags & NPY_ARRAY_ENSURENOCOPY) {
        copy = 0;
    } else if (flags & NPY_ARRAY_ENSURECOPY) {
        copy = 1;
    }

    Py_BEGIN_CRITICAL_SECTION(op);