Now that PEP 573 (Module State Access from C Extension Methods) is in,
it's time to address the most important part missing from it: module
state access from slot methods (like tp_init or nb_add).
This has long history; see e.g. a thread I started in 2015:
Most recently, a possible solution, an MRO walker, was one of the last
things removed from PEP 573 before acceptance, because the proposed
solution was broken: see
Here's the removed text:
> Slot methods
> To allow access to `per-module state`_ from slot methods, an MRO walker
> will be implemented::
> PyTypeObject *PyType_DefiningTypeFromSlotFunc(PyTypeObject *type,
> int slot, void *func)
> The walker will go through bases of heap-allocated ``type``
> and search for class that defines ``func`` at its ``slot``.
> The ``func`` does not need to be inherited by ``type`` (i.e. it may have been
> overridden in a subclass). The only requirement for the walker to find the
> defining class is that the defining class must be heap-allocated.
> On failure, exception is set and NULL is returned.
and the last iteration of the implementation is here:
A MRO walker is not efficient. The other viable options I'm aware of are:
- putting a pointer in the class object (which would need reliable
class-level storage, see
- solutions that aren't fully general, like context variables or putting
a pointer in each instance (thorny because constructors/initializers are
- "__typeslots__" mentioned in
which are, IMO, quite invasive
Given that, I believe that some kind of MRO walker is still the best
immediate solution, mainly because it's easiest to implement. If done
well, it can only use current public API (limiting the maintenance
burden you'd have with something wired into the internals, and allowing
it to be copied to 3rd party code to support older Python versions), and
should be easy to replace with a more performant solution once that
And if it's added, more modules could switch to the stable ABI and
eschew process-global state, so we get more exposure and experience with
the remaining problems.
Now, the main problem with "PyType_DefiningTypeFromSlotFunc" is that it
looked slot functions, which can be set from Python code, and doing so
can easily introduce C-level failures.
To solve this, my next thought is instead looking for something only
available in C: the PyModuleDef.
Here's an implementation of such an MRO walker, which I call
My thinking is to start using this in 3.10 as internal API to get a feel
for its strengths and weaknesses.
It should be easy to rewrite the function to only use public API, and
added to another project (like Cython). It should also be easy to make
it public once we're sure it's the way forward.
What are your thoughts?