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

Code before:
     * the 'descr' attribute.
     */
    if (dtype->type_num == NPY_VOID) {
        PyObject *descr = _PyDict_GetItemStringWithError(iface, "descr");
        if (descr == NULL && PyErr_Occurred()) {
            goto fail;
        }
        PyArray_Descr *new_dtype = NULL;
        if (descr != NULL) {
            int is_default = _is_default_descr(descr, attr);
            if (is_default < 0) {
                goto fail;
            }
            if (!is_default) {
                if (PyArray_DescrConverter2(descr, &new_dtype) != NPY_SUCCEED) {
                    goto fail;
                }
                if (new_dtype != NULL) {
                    Py_DECREF(dtype);
                    dtype = new_dtype;
                }
            }

        }

    }

    /* Get shape tuple from interface specification */
    attr = _PyDict_GetItemStringWithError(iface, "shape");
    if (attr == NULL) {
        if (PyErr_Occurred()) {
            return NULL;
        }
        /* Shape must be specified when 'data' is specified */
        PyObject *data = _PyDict_GetItemStringWithError(iface, "data");
        if (data == NULL && PyErr_Occurred()) {
            return NULL;
        }
        else if (data != NULL) {
            Py_DECREF(iface);
            PyErr_SetString(PyExc_ValueError,
                    "Missing __array_interface__ shape");
            return NULL;
        }
        /* Assume shape as scalar otherwise */
        else {
            /* NOTE: pointers to data and base should be NULL */
            n = dims[0] = 0;
        }
    }
    /* Make sure 'shape' is a tuple */

Review comment (bug):
@ngoldbaum this is at the wrong indentation level.  It's too late here, and I am not sure where to put a test though.  `cunumeric` notices this, it seems they use void (I suspect unstructured but dunno), without a `descr`.

Code after:
     * the 'descr' attribute.
     */
    if (dtype->type_num == NPY_VOID) {
        PyObject *descr = NULL;
        result = PyDict_GetItemStringRef(iface, "descr", &descr);
        if (result == -1) {
            goto fail;
        }
        PyArray_Descr *new_dtype = NULL;
        if (result == 1) {
            int is_default = _is_default_descr(descr, attr);
            if (is_default < 0) {
                Py_DECREF(descr);
                goto fail;
            }
            if (!is_default) {
                if (PyArray_DescrConverter2(descr, &new_dtype) != NPY_SUCCEED) {
                    Py_DECREF(descr);
                    goto fail;
                }
                if (new_dtype != NULL) {
                    Py_SETREF(dtype, new_dtype);
                }
            }
        }
        Py_DECREF(descr);
    }
    Py_CLEAR(attr);

    /* Get shape tuple from interface specification */
    result = PyDict_GetItemStringRef(iface, "shape", &attr);
    if (result < 0) {
        return NULL;
    }
    if (result == 0) {
        /* Shape must be specified when 'data' is specified */
        int result = PyDict_ContainsString(iface, "data");
        if (result < 0) {
            Py_DECREF(attr);
            return NULL;
        }
        else if (result == 1) {
            Py_DECREF(iface);
            Py_DECREF(attr);
            PyErr_SetString(PyExc_ValueError,
                    "Missing __array_interface__ shape");
            return NULL;
        }
        /* Assume shape as scalar otherwise */
        else {
            /* NOTE: pointers to data and base should be NULL */