Repository: numpy/numpy
File: numpy/_core/src/umath/dispatching.cpp (C++)

Code before:
                        dtype);
                return -1;
            }

            NPY_DT_SLOTS(dtype)->sort_meth = sort_meth->method;
            Py_INCREF(sort_meth->method);
            Py_DECREF(sort_meth);
        }
        else if (strcmp(slot->ufunc_name, "argsort") == 0) {
            PyArray_DTypeMeta *dtype = slot->spec->dtypes[0];

            PyBoundArrayMethodObject *argsort_meth = PyArrayMethod_FromSpec_int(slot->spec, 0);
            if (argsort_meth == NULL) {
                PyErr_Format(PyExc_TypeError,
                        "Failed to create argsort method for %R",
                        dtype);
                return -1;
            }

            NPY_DT_SLOTS(dtype)->argsort_meth = argsort_meth->method;
            Py_INCREF(argsort_meth->method);
            Py_DECREF(argsort_meth);
        }
        else {
            PyObject *ufunc =
                PyObject_GetAttrString(PyImport_ImportModule("numpy"), slot->ufunc_name);
            if (ufunc == NULL) {
                PyErr_Format(PyExc_TypeError,
                        "numpy.%s is not a ufunc!", slot->ufunc_name);
                return -1;
            }

            if (!PyObject_TypeCheck(ufunc, &PyUFunc_Type)) {
                PyErr_Format(PyExc_TypeError,
                        "numpy.%s was not a ufunc!", slot->ufunc_name);
                Py_DECREF(ufunc);
                return -1;
            }

            int ret = PyUFunc_AddLoopFromSpec_int(ufunc, slot->spec, 0);
            if (ret < 0) {
                Py_DECREF(ufunc);
                return -1;
            }

            Py_DECREF(ufunc);
        }
    }

    return 0;
}

Review comment (bug):
So, this is the part where I think if it fails, one perhaps should have a more general import - surely, there is something available that can help importing a `module.submodule.function` string...

Code after:

    PyUFunc_LoopSlot *slot;
    for (slot = slots; slot->name != NULL; slot++) {
        PyObject *ufunc = npy_import("numpy", slot->name);
        if (ufunc == NULL) {
            return -1;
        }

        if (ufunc == npy_runtime_imports.sort) {
            Py_DECREF(ufunc);

            PyArray_DTypeMeta *dtype = slot->spec->dtypes[0];
            PyBoundArrayMethodObject *sort_meth = PyArrayMethod_FromSpec_int(slot->spec, 0);
            if (sort_meth == NULL) {
                return -1;
            }

            NPY_DT_SLOTS(dtype)->sort_meth = sort_meth->method;
            Py_INCREF(sort_meth->method);
            Py_DECREF(sort_meth);
        }
        else if (ufunc == npy_runtime_imports.argsort) {
            Py_DECREF(ufunc);

            PyArray_DTypeMeta *dtype = slot->spec->dtypes[0];
            PyBoundArrayMethodObject *argsort_meth = PyArrayMethod_FromSpec_int(slot->spec, 0);
            if (argsort_meth == NULL) {
                return -1;
            }

            NPY_DT_SLOTS(dtype)->argsort_meth = argsort_meth->method;
            Py_INCREF(argsort_meth->method);
            Py_DECREF(argsort_meth);
        }
        else {
            if (!PyObject_TypeCheck(ufunc, &PyUFunc_Type)) {
                PyErr_Format(PyExc_TypeError, "%s was not a ufunc!", slot->name);
                Py_DECREF(ufunc);
                return -1;
            }

            int ret = PyUFunc_AddLoopFromSpec_int(ufunc, slot->spec, 0);
            Py_DECREF(ufunc);
            if (ret < 0) {
                return -1;
            }
        }
    }

    return 0;
}