I am writing a simple extension module using the C API. Here is a test example:
#include <Python.h>
#include <structmember.h>
typedef struct {
PyObject_HEAD
int i;
} MyObject;
static PyMemberDef my_members[] = {
{"i", T_INT, offsetof(MyObject, i), READONLY, "Some integer"},
{NULL} /* Sentinel */
};
static int MyType_init(MyObject *self, PyObject *args, PyObject *kwds)
{
char *keywords[] = {"i", NULL};
int i = 0;
if(!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &i)) {
return -1;
}
self->i = i;
return 0;
}
static PyTypeObject MyType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "_my.MyType",
.tp_doc = "Pointless placeholder class",
.tp_basicsize = sizeof(MyObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_init = (initproc)MyType_init,
.tp_members = my_members,
};
static PyModuleDef my_module = {
PyModuleDef_HEAD_INIT,
.m_name = "_my",
.m_doc = "My module is undocumented!",
.m_size = -1,
};
/* Global entry point */
PyMODINIT_FUNC PyInit__my(void)
{
PyObject *m = NULL;
PyExc_MyException = PyErr_NewExceptionWithDoc("_my.MyException",
"Indicates that something went horribly wrong.",
NULL, NULL);
if(PyExc_MyException == NULL) {
return NULL;
}
if(PyType_Ready(&MyType) < 0) {
goto err;
}
if((m = PyModule_Create(&my_module)) == NULL) {
goto err;
}
Py_INCREF(&MyType);
PyModule_AddObject(m, "MyType", (PyObject *)&MyType);
PyModule_AddObject(m, "MyException", (PyObject *)PyExc_MyException);
return m;
err:
Py_CLEAR(PyExc_MyException);
return NULL;
}
This module contains a class MyType
and an exception MyException
. The purpose of this module is to provide the base functionality for some additional code written in Python. I would like to be able to do something like:
my.py
from _my import *
class MyType(MyType):
def __init__(i=0):
raise MyException
Obviously this example is highly contrived. I just want to illustrate how I would like to use the names in my
extension. Right now the import is working fine according to this rule:
If
__all__
is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character ('_'
).
However, I would like to have a finer level of control. So far, all I have been able to come up with is manually adding an __all__
attribute to the module:
PyObject *all = NULL;
...
all = Py_BuildValue("[s, s]", "MyType", "MyException");
if(all == NULL) {
goto err;
}
PyModule_AddObject(m, "__all__", all);
...
err:
...
Py_CLEAR(all);
This seems a bit clunky. Is there a function in the C API for defining an internal equivalent to __all__
for a module?
Part of the reason that I think there may be an internal equivalent is that __all__
is after all a dunder attribute.