#include <Python.h>

static PyObject*
seqnew(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    PyObject *ret = PyStructSequence_New(type);
    if (!ret)
        return NULL;
    if (Py_SIZE(ret) != PyTuple_GET_SIZE(args)) {
        PyErr_Format(PyExc_TypeError, "expected %zd args, received %zd", Py_SIZE(ret), PyTuple_GET_SIZE(args));
        Py_CLEAR(ret);
    } else {
        for (Py_ssize_t i = 0; i < Py_SIZE(ret); ++i) {
            PyObject *v = PyTuple_GET_ITEM(args, i);
            Py_INCREF(v);
            PyStructSequence_SET_ITEM(ret, i, v);
        }
    }
    return ret;
}

static PyObject*
makeseq(PyObject *self, PyObject *args)
{
    const char *typename;
    PyObject *fieldargs;
    PyTypeObject *newtype = NULL;
    if (PyArg_ParseTuple(args, "sO", &typename, &fieldargs)) {
        PyObject *fields = PySequence_Fast(fieldargs, "Must be sequence of strings");
        PyStructSequence_Desc descr = {(char*)typename, (char*)typename, NULL, PySequence_Fast_GET_SIZE(fields)}; 
        descr.fields = PyMem_Calloc(descr.n_in_sequence + 1, sizeof(descr.fields[0]));
        for (Py_ssize_t i = 0; i < descr.n_in_sequence; ++i) {
            descr.fields[i].name = PyUnicode_AsUTF8(PySequence_Fast_GET_ITEM(fields, i));
            descr.fields[i].doc = descr.fields[i].name;
        }
        newtype = PyStructSequence_NewType(&descr);
        newtype->tp_new = seqnew;
        // Uncomment the next line to "fix"
        //newtype->tp_flags |= Py_TPFLAGS_HEAPTYPE;
        PyType_Modified(newtype);

        Py_DECREF(fields);
        PyMem_Free(descr.fields);
    }
    printf("Flags: %lx\n", newtype->tp_flags);
    return (PyObject*)newtype;
}

static PyMethodDef testnewtypemethods[] = {
    {"makeseq", makeseq, METH_VARARGS,
     "Make new struct sequence type."},
    {NULL, NULL, 0, NULL}        /* Sentinel */
};
static PyModuleDef testnewtypemodule = {
    PyModuleDef_HEAD_INIT,
    "testnewtype",
    "Example module for making dynamic struct sequence type.",
    -1,
    testnewtypemethods,
};

PyMODINIT_FUNC
PyInit_testnewtype(void)
{
    return PyModule_Create(&testnewtypemodule);
}
