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

Code before:
         * just fall back on regular __reduce_ex__ implementation
         * (gh-12745).
         */
        PyErr_Clear();
        return array_reduce_ex_regular(self, protocol);
    }

    /* Get the _frombuffer() function for reconstruction */

    numeric_mod = PyImport_ImportModule("numpy._core.numeric");
    if (numeric_mod == NULL) {
        Py_DECREF(buffer);
        return NULL;
    }
    from_buffer_func = PyObject_GetAttrString(numeric_mod,
                                              "_frombuffer");
    Py_DECREF(numeric_mod);
    if (from_buffer_func == NULL) {
        Py_DECREF(buffer);
        return NULL;
    }


    PyObject* shape = NULL;
    if(order == 'K') {
        shape = PyObject_GetAttrString((PyObject *)transposed_array, "shape");
    } else {
        shape = PyObject_GetAttrString((PyObject *)self, "shape");
    }
    return Py_BuildValue("N(NONNO)", from_buffer_func, buffer, (PyObject *)descr, shape,
            PyUnicode_FromStringAndSize(&order, 1), rev_perm);
}

static PyObject *
array_reduce_ex(PyArrayObject *self, PyObject *args)
{
    int protocol;
    PyArray_Descr *descr = NULL;

    if (!PyArg_ParseTuple(args, "i", &protocol)) {
        return NULL;
    }

    descr = PyArray_DESCR(self);
    if ((protocol < 5) ||
        PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT) ||
        (PyType_IsSubtype(((PyObject*)self)->ob_type, &PyArray_Type) &&
         ((PyObject*)self)->ob_type != &PyArray_Type) ||
        descr->elsize == 0) {
        /* The PickleBuffer class from version 5 of the pickle protocol
         * can only be used for arrays backed by a contiguous data buffer.

Review comment (refactor):
Old messy code, so you can ignore: but we have a `PyArray_IntTupleFromIntp` helper to use `PyArray_NDIM` and `PyArray_DIMS` directly.

Code after:
    }
    else {
        shape = PyArray_IntTupleFromIntp(PyArray_NDIM(self),
                                         PyArray_SHAPE(self));
    }
    Py_XDECREF(transposed_array);
    if (shape == NULL) {
        Py_XDECREF(rev_perm);
        Py_DECREF(buffer);
        return NULL;
    }
    if (order == 'K') {
        return Py_BuildValue("N(NONNN)", from_buffer_func, buffer,
                             (PyObject *)descr, shape,
                             PyUnicode_FromStringAndSize(&order, 1), rev_perm);
    }
    else {
        return Py_BuildValue("N(NONN)", from_buffer_func, buffer,
                             (PyObject *)descr, shape,
                             PyUnicode_FromStringAndSize(&order, 1));
    }
}

static PyObject *
array_reduce_ex(PyArrayObject *self, PyObject *args)
{
    int protocol;
    PyArray_Descr *descr = NULL;

    if (!PyArg_ParseTuple(args, "i", &protocol)) {
        return NULL;
    }

    descr = PyArray_DESCR(self);
    if ((protocol < 5) ||
        PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT) ||
        (PyType_IsSubtype(((PyObject*)self)->ob_type, &PyArray_Type) &&
         ((PyObject*)self)->ob_type != &PyArray_Type) ||
        descr->elsize == 0) {
        /* The PickleBuffer class from version 5 of the pickle protocol
         * can only be used for arrays backed by a contiguous data buffer.
         * For all other cases we fallback to the generic array_reduce
         * method that involves using a temporary bytes allocation. */
        return array_reduce_ex_regular(self, protocol);
    }
    else {
        /* The func will check internally
         * if the array isn't backed by a contiguous data buffer or
         * if the array refuses to export a buffer
         * In either case, fall back to `array_reduce_ex_regular`
         */