#include <Python.h>

static int {modname}_exec(PyObject *module)
{{
    PyObject *tmp;
    // Use ImportModuleLevel with a non-empty fromlist so Python returns the
    // leaf submodule via sys.modules lookup, avoiding the top-down getattr
    // walk done by PyImport_ImportModule. That walk fails when the shim runs
    // during a parent package's __init__.py, because the parent's submodule
    // attribute isn't set until after __init__ returns.
    static PyObject *fromlist = NULL;
    if (!fromlist) {{
        fromlist = Py_BuildValue("(s)", "*");
        if (!fromlist) return -1;
    }}
    tmp = PyImport_ImportModuleLevel("{libname}", NULL, NULL, fromlist, 0);
    if (!tmp) return -1;
    // Populate cross-group export tables lazily, just before we instantiate
    // the per-module real init. Deferring this out of the shared lib's own
    // PyInit keeps separate-mode compiled modules from recursively triggering
    // sibling-package __init__.py mid-bootstrap.
    // PyObject_GetOptionalAttrString would be cleaner, but it's 3.13+ and the
    // shim deliberately #includes only <Python.h>, so we can't pull in the
    // pythoncapi_compat.h shim from lib-rt here. AttributeError + PyErr_Clear
    // is the portable form.
    PyObject *deps_capsule = PyObject_GetAttrString(tmp, "ensure_deps");
    if (deps_capsule != NULL) {{
        int (*deps_func)(void) = (int (*)(void))PyCapsule_GetPointer(
            deps_capsule, "{libname}.ensure_deps");
        Py_DECREF(deps_capsule);
        if (deps_func == NULL) {{
            Py_DECREF(tmp);
            return -1;
        }}
        if (deps_func() < 0) {{
            Py_DECREF(tmp);
            return -1;
        }}
    }} else {{
        PyErr_Clear();
    }}
    PyObject *capsule = PyObject_GetAttrString(tmp, "exec_{full_modname}");
    Py_DECREF(tmp);
    if (capsule == NULL) return -1;
    void *exec_func = PyCapsule_GetPointer(capsule, "{libname}.exec_{full_modname}");
    Py_DECREF(capsule);
    if (!exec_func) return -1;
    if (((int (*)(PyObject *))exec_func)(module) != 0) return -1;
    return 0;
}}

static PyModuleDef_Slot {modname}_slots[] = {{
    {{Py_mod_exec, {modname}_exec}},
    {{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}},
    {{Py_mod_gil, Py_MOD_GIL_NOT_USED}},
    {{0, NULL}},
}};

static struct PyModuleDef {modname}_module = {{
    PyModuleDef_HEAD_INIT,
    .m_name = "{modname}",
    .m_doc = NULL,
    .m_methods = NULL,
    .m_size = 0,
    .m_slots = {modname}_slots,
}};

PyMODINIT_FUNC
PyInit_{modname}(void)
{{
    return PyModuleDef_Init(&{modname}_module);
}}

// distutils sometimes spuriously tells cl to export CPyInit___init__,
// so provide that so it chills out
PyMODINIT_FUNC PyInit___init__(void) {{ return PyInit_{modname}(); }}
