This was also a common opinion when I asked around at EuroPython.
And making the ABI backwards-compatible is not as important as I thought. One can always build extra wheels with an older Python.
Also, an API change seems less problematic than I thought. Since extensions opt in to new versions of limited API, it can be done there.
So, my updated current plan is option 2 above:
Version 3.15 of the limited API makes PyObject opaque
The following API is removed:
PyObject_HEAD_PyObject_EXTRA_INITPyObject_HEAD_INITPyObject_VAR_HEADstruct _object(i.e. PyObject)struct PyVarObjectPyModuleDef_Base(made opaque)PyModuleDef_HEAD_INITPyModuleDef(made opaque)Py_SIZE(can be added back as a function)Py_SET_TYPE(ditto)Py_SET_SIZE(ditto)
(You can test the effects in current main, by defining _Py_OPAQUE_PYOBJECT before including <Python.h>. Note that this macro will be either removed or renamed for 3.15.0.)
Module creation API is left in, but becomes unusable in practice (since
you can’t create the input for these functions):
PyModuleDef_InitPyModule_Create,PyModule_Create2PyModule_FromDefAndSpec,PyModule_FromDefAndSpec2
New export hook
To allow defining modules with opaque PyObject, we add the PyModExport
hook from PEP 793 (now submitted to the SC).
Wheel tags
There are two main options:
-
Wheels that use the new version of the ABI use the
abi3.abi3tABI tag.This adds an ugly new tag.
-
Tools learn that
cp315and above + ABI tagabi3is compatible with free-threading.This avoids a new tag, but is much less obvious.
For the long term: tools that don’t support 3.14 any more may only use option 2, and ignore abi3t.
Runtime ABI checks
It still makes sense to me that build/install tools are responsible for
not putting incompatible extensions in site-packages – the metadata they can use is much richer.
But, we can provide some checks for when the tools get it wrong (or you’re not
using a tool that follows the latest spect).
-
Add an ABI checking slot is added, and made mandatory if
PyModExportis used (that is: for stable ABI 3.15+).
This will prevent new extensions (stable ABI 3.15+) from being loaded in incompatible interpreters. -
In free-threaded builds,
PyModuleDef_Initshould reject extensions compiled for the pre-free-threading ABI.
(PyModuleDef_Initis also called fromPyModule_Create*and PyModule_FromDefAndSpec*`, so this covers single-phase init too.)I’m testing a prototype that looks at a certain bit pattern which appears in
PyModuleDefof free-threaded builds but not inPyModuleDef_HEAD_INITof the currentabi3.
This is fragile, and the check might need to be removed asPyObjectinternals change further. But, hopefully it can stay in for the transition period toward free-threading.
What’s missing is preventing existing free-threading extensions (cp314t) being loaded in gil-ful builds of Python, but, that’s out of scope of this thread.
Sunsetting; ABI support windows
The current stable ABI (3.14 & below) will, necessarily, become less useful when free-threading builds become default (phase III of the rollout), and unusable after the GIL builds are removed entirely.
We might also plan to regularly deprecate older versions of stable ABI after some time.
With the ABI checking slot, we can start emitting deprecation warnings as soon as we agree on a policy; there’s no rush to start the discussions now.
New API
[help welcome]
Add APIs like PyMutex and PyCriticalSection to stable ABI, so extensions with Py_MOD_GIL_NOT_USED are practical.