[Python-Dev] creating __all__ in extension modules
Skip Montanaro
skip@mojam.com (Skip Montanaro)
Sat, 3 Feb 2001 17:01:01 -0600 (CST)
Tim> I'm afraid I find it hard to believe people will *keep* C-module
Tim> __all__ lists in synch with the code as the years go by. If we're
Tim> going to do this, how about adding code to Py_InitModule4 that
Tim> sucks the non-underscore names out of its PyMethodDef argument and
Tim> automagically builds an __all__ attr? Then nothing ever needs to
Tim> be fiddled by hand for C modules.
The way it works now is that the module author inserts a call to
_PyModuleCreateAllList at or near the end of the module's init func
/* initialize module's __all__ list */
_PyModule_CreateAllList(d);
that initializes and populates __all__ based on the keys in the module's
dict. Unlike having to manually maintain __all__, I think this solution is
fairly un-onerous (one-time change). Again, my assumption is that all
non-underscore prefixed symbols in a module's dict will be exported. If
this isn't true, the author can simply delete any elements from __all__
after the call to _PyModule_CreateAllList.
This functionality can't be subsumed by Py_InitModule4 because the author is
allowed to insert values into the module dict after that call (see
posixmodule.c for a significant example of this).
_PyModule_CreateAllList is currently defined in modsupport.c (not checked in
yet) as
/* helper function to create __all__ from an extension module's dict */
int
_PyModule_CreateAllList(PyObject *d) {
PyObject *v, *k, *s;
unsigned int i;
int res;
v = PyList_New(0);
if (v == NULL)
return -1;
res = 0;
if (!PyDict_SetItemString(d, "__all__", v)) {
k = PyDict_Keys(d);
if (k == NULL)
res = -1;
else {
for (i = 0; res == 0 && i < PyObject_Length(k); i++) {
s = PySequence_GetItem(k, i);
if (s == NULL)
res = -1;
else {
if (PyString_AsString(s)[0] != '_')
if (PyList_Append(v, s))
res = -1;
Py_DECREF(s);
}
}
}
}
Py_DECREF(v);
return res;
}
I don't know (nor much care - you guys decide) if it's named with or without
a leading underscore. I view it as a more-or-less internal function, but
one that many C extension modules will call (guess that might make it not
internal). I haven't written a doc blurb for the API manual yet.
Skip