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

Code before:
      If it is a sequence, this object is the argument to PySequence_Fast, e.g.
      the iterable that the user wants to coerce into an array
    */
    PyObject *orig_seq = (*cache)->converted_obj;
    /* Owned reference to an item in the sequence */
    PyObject *item_pyvalue = NULL;
    int depth = (*cache)->depth;
    *cache = npy_unlink_coercion_cache(*cache);

    /* The element is either a sequence or an array */
    if (!is_sequence) {
        /* Straight forward array assignment */
        assert(PyArray_Check(obj));
        if (PyArray_CopyInto(self, (PyArrayObject *)obj) < 0) {
            goto finish;
        }
    }
    else {
        assert(depth != ndim);
        npy_intp orig_length = PyArray_DIMS(self)[0];
        for (npy_intp i = 0; i < orig_length; i++) {
            int critical_section_error = 0;
            // this macro takes *the argument* of PySequence_Fast, which is orig_seq;
            // not the object returned by PySequence_Fast, which is obj
            NPY_BEGIN_CRITICAL_SECTION_SEQUENCE_FAST(orig_seq);
            npy_intp length = PySequence_Length(obj);
            if (length != orig_length) {
                PyErr_SetString(PyExc_RuntimeError,
                                "Inconsistent object during array creation? "
                                "Content of sequences changed (length inconsistent).");
                critical_section_error = 1;
            }
            else {
                Py_XSETREF(item_pyvalue, Py_NewRef(PySequence_Fast_GET_ITEM(obj, i)));
            }
            NPY_END_CRITICAL_SECTION_SEQUENCE_FAST();

            if (critical_section_error) {
                goto finish;
            }

            if (ndim == depth + 1) {
                /*
                 * Straight forward assignment of elements.  Note that it is
                 * possible for such an element to be a 0-D array or array-like.
                 * `PyArray_Pack` supports arrays as well as we want: We
                 * support exact NumPy arrays, but at this point ignore others.
                 * (Please see the `PyArray_Pack` function comment if this
                 * rightly confuses you.)
                 */
                char *item;

Review comment (suggestion):
You can use `PySequence_Fast_GET_SIZE` here which would be faster.

Code after:
      If it is a sequence, this object is the argument to PySequence_Fast, e.g.
      the iterable that the user wants to coerce into an array
    */
    PyObject *orig_seq = (*cache)->converted_obj;
    /* Owned reference to an item in the sequence */
    PyObject *item_pyvalue = NULL;
    int depth = (*cache)->depth;
    *cache = npy_unlink_coercion_cache(*cache);

    /* The element is either a sequence or an array */
    if (!is_sequence) {
        /* Straight forward array assignment */
        assert(PyArray_Check(obj));
        if (PyArray_CopyInto(self, (PyArrayObject *)obj) < 0) {
            goto finish;
        }
    }
    else {
        assert(depth != ndim);
        npy_intp orig_length = PyArray_DIMS(self)[0];
        int err = 1;
        NPY_BEGIN_CRITICAL_SECTION_SEQUENCE_FAST(orig_seq);
        for (npy_intp i = 0; i < orig_length; i++) {
            // this macro takes *the argument* of PySequence_Fast, which is orig_seq;
            // not the object returned by PySequence_Fast, which is a proxy object
            // with its own per-object PyMutex lock.
            // We want to lock the list object exposed to users, not the proxy.
            npy_intp length = PySequence_Fast_GET_SIZE(obj);
            if (length != orig_length) {
                PyErr_SetString(PyExc_RuntimeError,
                                "Inconsistent object during array creation? "
                                "Content of sequences changed (length inconsistent).");
                goto finish_critical_section;
            }
            else {
                Py_XSETREF(item_pyvalue, Py_NewRef(PySequence_Fast_GET_ITEM(obj, i)));
            }

            if (ndim == depth + 1) {
                /*
                 * Straight forward assignment of elements.  Note that it is
                 * possible for such an element to be a 0-D array or array-like.
                 * `PyArray_Pack` supports arrays as well as we want: We
                 * support exact NumPy arrays, but at this point ignore others.
                 * (Please see the `PyArray_Pack` function comment if this
                 * rightly confuses you.)
                 */
                char *item;
                item = (PyArray_BYTES(self) + i * PyArray_STRIDES(self)[0]);
                if (PyArray_Pack(PyArray_DESCR(self), item, item_pyvalue) < 0) {
                    goto finish_critical_section;