#include "Python.h"

static int myexception_init(PyObject *, PyObject *, PyObject *);

static PyTypeObject PyMyException_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "mymodule.MyException",     /* tp_name */
    sizeof(PyBaseExceptionObject), /* tp_basicsize */
    0,                          /* tp_itemsize */
    0,                          /* tp_dealloc */
    0,                          /* tp_print */
    0,                          /* tp_getattr */
    0,                          /* tp_setattr */
    0,                          /* tp_reserved */
    0,                          /* tp_repr */
    0,                          /* tp_as_number */
    0,                          /* tp_as_sequence */
    0,                          /* tp_as_mapping */
    0,                          /* tp_hash */
    0,                          /* tp_call */
    0,                          /* tp_str */
    0,                          /* tp_getattro */
    0,                          /* tp_setattro */
    0,                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */
    0,                          /* tp_doc */
    0,                          /* tp_traverse */
    0,                          /* tp_clear */
    0,                          /* tp_richcompare */
    0,                          /* tp_weaklistoffset */
    0,                          /* tp_iter */
    0,                          /* tp_iternext */
    0,                          /* tp_methods */
    0,                          /* tp_members */
    0,                          /* tp_getset */
    0,                          /* tp_base */
    0,                          /* tp_dict */
    0,                          /* tp_descr_get */
    0,                          /* tp_descr_set */
    0,                          /* tp_dictoffset */
    (initproc)myexception_init, /* tp_init */
    0,                          /* tp_alloc */
    0,                          /* tp_new */
};

static int
myexception_init(PyObject *self, PyObject *args, PyObject *kwds)
{
    PyObject *type = (PyObject*)&PyMyException_Type;

    /* Instantiating this exception causes infinite recursion. */
    Py_INCREF(type);
    PyErr_Restore(type, NULL, NULL);
    return -1;
}

static struct PyModuleDef mymodule_def = {
    PyModuleDef_HEAD_INIT,
    "mymodule",
    NULL,
    -1,
    NULL, NULL, NULL, NULL, NULL
};

PyMODINIT_FUNC
PyInit_mymodule(void)
{
    PyObject *m;

    if (!(m = PyModule_Create(&mymodule_def)))
        return NULL;
    PyMyException_Type.tp_base = (PyTypeObject*)PyExc_Exception;
    if (PyType_Ready(&PyMyException_Type) < 0)
        return NULL;
    Py_INCREF(&PyMyException_Type);
    PyModule_AddObject(m, "MyException", (PyObject*)&PyMyException_Type);
    return m;
}

