#include <Python.h>
#include <stdio.h>

#ifdef Py_LIMITED_API
#error Py_LIMITED_API must not be defined.
#endif

/* This function explicitly calls functions whose declaration is elided when
 * Py_LIMITED_API is defined. This is to test that the linker is actually
 * linking to the right version of the library on Windows. */
static PyObject *meth_not_limited(PyObject *self, PyObject *args)
{
    PyObject *list;
    Py_ssize_t size;

    if (!PyArg_ParseTuple(args, "o", &  list))
        return NULL;

    if (!PyList_Check(list)) {
        PyErr_Format(PyExc_TypeError, "expected 'list'");
        return NULL;
    }

    /* PyList_GET_SIZE and PyList_GET_ITEM are only available if Py_LIMITED_API
     * is not defined. It seems likely that they will remain excluded from the
     * limited API as their checked counterparts (PyList_GetSize and
     * PyList_GetItem) are made available in that mode instead. */
    size = PyList_GET_SIZE(list);
    for(Py_ssize_t i = 0; i < size; ++i) {
        PyObject *element = PyList_GET_ITEM(list, i);
        if (element == NULL) {
            return NULL;
        }

        if(PyObject_Print(element, stdout, Py_PRINT_RAW) == -1) {
            return NULL;
        }
    }

    Py_RETURN_NONE;
}

static struct PyMethodDef not_limited_methods[] = {
    { "not_limited", meth_not_limited, METH_VARARGS,
     "Calls functions whose declaration is elided by Py_LIMITED_API" },
    { NULL, NULL, 0, NULL }
};

static struct PyModuleDef not_limited_module = {
   PyModuleDef_HEAD_INIT,
   "not_limited_api_test",
   NULL,
   -1,
   not_limited_methods
};

PyMODINIT_FUNC PyInit_not_limited(void) {
    return PyModule_Create(&not_limited_module);
}
