Skip to content

Commit 415c032

Browse files
authored
PEP 803: Updates based on Discourse discussion (GH-4594)
- Use the more explicit tag `abi3.abi3t` to allow possibly expanding compatibility to 3.14 - Turn `Py_SIZE` & `Py_SET_SIZE` to functions, don't remove them - Add a table of compatibiity between extensions & interpreters - 2 more of the steps are now implemented. (They make sense on their own and are small enough to not need a PEP, but it does make sense to “collect” them in the PEP.)
1 parent 96bb9f2 commit 415c032

File tree

1 file changed

+190
-38
lines changed

1 file changed

+190
-38
lines changed

peps/pep-0803.rst

Lines changed: 190 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Type: Standards Track
77
Requires: 703, 793, 697
88
Created: 19-Aug-2025
99
Python-Version: 3.15
10+
Post-History: `08-Sep-2025 <https://discuss.python.org/t/103628>`__
1011

1112

1213
Abstract
@@ -18,6 +19,9 @@ To allow this, the :c:type:`PyObject` internal structure and related APIs
1819
will be removed from version 3.15 of the Limited API, requiring migration to
1920
new API for common tasks like defining modules and most classes.
2021

22+
Binary distributions (wheels) built with Limited API version 3.15 and above
23+
should use the ABI tag ``abi3.abi3t``.
24+
2125

2226
Terminology
2327
===========
@@ -77,11 +81,14 @@ One ABI
7781
A single compiled extension module should support both
7882
free-threaded and GIL-enabled builds.
7983

80-
No backwards compatibility
84+
No backwards compatibility now
8185
The new limited API will not support CPython 3.14 and below.
8286
Projects that need this support can build separate extensions specifically
8387
for the 3.14 free-threaded interpreter, and for older stable ABI versions.
8488

89+
However, we won't block the possibility of extending compatibility to
90+
CPython 3.14 and below.
91+
8592
API changes are OK
8693
The new Limited API may require extension authors to make significant
8794
changes to their code.
@@ -116,12 +123,12 @@ Version 3.15 of the Limited API will:
116123
- :c:macro:`!_PyObject_EXTRA_INIT`
117124
- :c:macro:`PyObject_HEAD_INIT`
118125
- :c:macro:`PyObject_VAR_HEAD`
126+
- :c:func:`Py_SET_TYPE`
119127

120-
- no longer include these function-like macros:
128+
- export the following as functions in the ABI, rather than macros:
121129

122130
- :c:func:`Py_SIZE`
123131
- :c:func:`Py_SET_SIZE`
124-
- :c:func:`Py_SET_TYPE`
125132

126133

127134
Implications
@@ -164,7 +171,7 @@ they will not yet be removed from the Limited API:
164171
New Export Hook (PEP 793)
165172
-------------------------
166173

167-
Implementation of this PEP requires :pep:`793` (``PyModExport``:
174+
Implementation of this PEP requires :pep:`793` (``PyModExport``):
168175
A new entry point for C extension modules) to be
169176
accepted, providing a new “export hook” for defining extension modules.
170177
Using the new hook will become mandatory in Limited API 3.15.
@@ -207,17 +214,19 @@ removed in future CPython versions, if the internal object layout needs
207214
to change.
208215

209216

210-
Wheel tags
211-
----------
217+
The ``abi3t`` wheel tag
218+
-----------------------
212219

213-
PyPA build tools should not need changes: if they allow the user to set the
214-
limited API version, setting it to 3.15 should define :c:macro:`Py_LIMITED_API`
215-
to ``0x030f0000``.
216-
The resulting wheel should be tagged with the Python-ABI tag ``cp315-abi3``.
220+
Wheels that use a stable ABI compatible with free-threading CPython builds
221+
should use a new ABI tag: ``abi3t``.
222+
The name is chosen to reflect the fact that this ABI is similar to ``abi3``,
223+
except changes necessary to support free-threading (which uses the letter ``t``
224+
in existing, version-specific ABI tags like ``cp314t``).
217225

218-
Installers and other tools should assume that wheels with a *python tag*
219-
``cp315`` and above and ABI tag ``abi3`` are compatible with free-threaded
220-
builds.
226+
Since wheels built using Limited API 3.15 will be compatible with both
227+
GIL-enabled builds and free-threaded ones, they should use the
228+
`compressed ABI tag set <https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#compressed-tag-sets>`__
229+
``abi3.abi3t``.
221230

222231

223232
New API
@@ -231,18 +240,140 @@ Limited API to allow thread-safety without a GIL -- presumably ``PyMutex``, ``Py
231240
similar -- will be added via the C API working group, or in a follow-up PEP.
232241

233242

234-
Backwards Compatibility
235-
=======================
243+
Backwards and Forwards Compatibility
244+
====================================
236245

237246
Limited API 3.15 will not be backwards-compatible with older CPython releases,
238-
due to removed structs and functions.
247+
due to the need to use new ``PyModExport`` API added in :pep:`793`.
239248

240249
Extension authors who cannot switch may continue to use Limited API 3.14
241250
and below.
242251
For compatibility with free-threaded builds, they can compile using
243252
version-specific ABI -- for example, compile on CPython 3.15 without defining
244253
``Py_LIMITED_API``.
245254

255+
Limited API 3.15 will be forward-compatible with future versions of CPython 3.x.
256+
Older versions of the Limited API (that is, 3.14 and below) will continue
257+
to be forward-compatible with GIL-enabled builds of CPython 3.x, starting with
258+
the version that introduced the given Limited API.
259+
260+
261+
Compatibility Overview
262+
----------------------
263+
264+
The following table summarizes compatibility of wheel tags with CPython
265+
interpreters. “GIL” stands for GIL-enabled interpreter; “FT” stands for a
266+
free-threaded one.
267+
268+
.. list-table::
269+
:widths: auto
270+
:header-rows: 1
271+
272+
* * Wheel tag
273+
* 3.14 (GIL)
274+
* 3.14 (FT)
275+
* 3.15 (GIL)
276+
* 3.15 (FT)
277+
* 3.16+ (GIL)
278+
* 3.16+ (FT)
279+
* * ``cp314-cp314``
280+
* ✅
281+
* ❌
282+
* ❌
283+
* ❌
284+
* ❌
285+
* ❌
286+
* * ``cp314-cp314t``
287+
* ❌
288+
* ✅
289+
* ❌
290+
* ❌
291+
* ❌
292+
* ❌
293+
* * ``cp314-abi3``
294+
* ✅
295+
* ❌
296+
* ✅
297+
* ❌
298+
* ✅
299+
* ❌
300+
* * ``cp315-cp315``
301+
* ❌
302+
* ❌
303+
* ✅
304+
* ❌
305+
* ❌
306+
* ❌
307+
* * ``cp315-cp315t``
308+
* ❌
309+
* ❌
310+
* ❌
311+
* ✅
312+
* ❌
313+
* ❌
314+
* * ``cp315-abi3``
315+
* ❌
316+
* ❌
317+
* ✅
318+
* ❌
319+
* ✅
320+
* ❌
321+
* * ``cp315-abi3.abi3t``
322+
* ❌
323+
* ❌
324+
* ✅
325+
* ✅
326+
* ✅
327+
* ✅
328+
329+
The following table summarizes which wheel tag should be used for an extension
330+
built with a given interpreter and ``Py_LIMITED_API`` macro:
331+
332+
.. list-table::
333+
:widths: auto
334+
:header-rows: 1
335+
336+
* * To get the wheel tag…
337+
* Compile on…
338+
* with ``Py_LIMITED_API`` set to…
339+
* Note
340+
* * ``cp314-cp314``
341+
* 3.14 (GIL)
342+
* (unset)
343+
* existing
344+
* * ``cp314-cp314t``
345+
* 3.14 (FT)
346+
* (unset)
347+
* existing
348+
* * ``cp314-abi3``
349+
* 3.14+ (GIL)
350+
* ``PY_PACK_VERSION(3, 14)``
351+
* existing
352+
* * ``cp315-cp315``
353+
* 3.15 (GIL)
354+
* (unset)
355+
* continued
356+
* * ``cp315-cp315t``
357+
* 3.15 (FT)
358+
* (unset)
359+
* continued
360+
* * ``cp315-abi3``
361+
* 3.15+ (GIL)
362+
* ``PY_PACK_VERSION(3, 15)``
363+
* discontinued
364+
* * ``cp315-abi3.abi3t``
365+
* 3.15+ (any)
366+
* ``PY_PACK_VERSION(3, 15)``
367+
* new
368+
369+
Values in the *Note* column:
370+
371+
* *existing*: The wheel tag is currently in use
372+
* *continued*: The wheel tag continues the existing scheme
373+
* *discontinued*: The wheel tag continues the existing scheme, but it will
374+
be discouraged. Older tools may still generate it.
375+
* *new*: Proposed in this PEP.
376+
246377

247378
Security Implications
248379
=====================
@@ -268,10 +399,10 @@ This PEP combines several pieces, implemented individually:
268399
Implemented in GitHub pull request `python/cpython#136505
269400
<https://github.com/python/cpython/pull/136505>`__.
270401
- For ``PyModExport``, see :pep:`793`.
271-
- For a version-checking slot, see GitHub pull request `python/cpython#137212
272-
<https://github.com/python/cpython/pull/137212>`__.
273-
- For a check for older ``abi3``, see GitHub pull request `python/cpython#137957
274-
<https://github.com/python/cpython/pull/137957>`__.
402+
- A version-checking slot was implemented in GitHub pull request
403+
`python/cpython#137212 <https://github.com/python/cpython/pull/137212>`__.
404+
- A check for older ``abi3`` was implemented in GitHub pull request
405+
`python/cpython#137957 <https://github.com/python/cpython/pull/137957>`__.
275406
- For wheel tags, there is no implementation yet.
276407
- A porting guide is not yet written.
277408

@@ -285,26 +416,24 @@ Add an alternative stable ABI for free-threading
285416

286417
It would be possible to:
287418

288-
- Keep the current stable ABI (“``abi3``”) unchanged (except additions, as done
289-
in each release). Extensions would need no code changes and builds would be
290-
compatible with old and new GIL-enabled CPython versions.
291-
- Add a new stable ABI (“``abi3t``”) specifically for free-threading.
292-
Extensions would need no code changes and builds would be
419+
- Add a new stable ABI (“``abi3t``”) specifically for free-threading,
420+
which would be incompatible with the existing ``abi3``.
421+
Extensions would need no code changes to target ``abi3t`` and builds would be
293422
compatible with free-threaded CPython (3.14 and above).
294-
- Defining an additional macro (“``Py_OPAQUE_PYOBJECT``”) would make
423+
- Define an additional macro (“``Py_OPAQUE_PYOBJECT``”), which would make
295424
``PyObject`` opaque as in this PEP. Extensions would need code changes as in
296-
this PEP, and compiled extensions (“``abi3.abi3t``”) would be compatible with
297-
all builds of CPython 3.15+.
425+
this PEP, and as in this PEP, compiled extensions (“``abi3.abi3t``”) would
426+
be compatible with all builds of CPython 3.15+.
298427

299428
This scheme was rejected as too complex.
300429
It would also make the free-threading memory layout of ``PyObject`` part
301430
of the stable ABI, preventing future adjustments.
302431

303432

304-
Shim for compatibility with CPython 3.14
305-
----------------------------------------
433+
Shims for compatibility with CPython 3.14
434+
-----------------------------------------
306435

307-
The issue that prevents compatibility with Python 3.14 is that with
436+
The main issue that prevents compatibility with Python 3.14 is that with
308437
opaque ``PyObject`` and ``PyModuleDef``, it is not feasible to initialize
309438
an extension module.
310439
The solution, :pep:`793`, is only being added in Python 3.15.
@@ -314,16 +443,39 @@ free-threading and GIL-enabled) are “frozen”, so it is possible for an
314443
extension to query the running interpreter, and for 3.14, use
315444
a ``struct`` definition corresponding to the detected build's ``PyModuleDef``.
316445

317-
This is too onerous to support and test in CPython's Limited API.
318-
It would also require adding a new wheel tag (e.g. ``abi3t``) that all install
319-
tools would need to recognize. (This PEP's ``cp315-abi3`` is incompatible
320-
with Python 3.14.)
446+
This is too onerous to support and test in CPython's Limited API at this point,
447+
but it may be allowed in the future.
321448

322449

323-
Open Issues
324-
===========
450+
Using the Python wheel tag to determine compatibility
451+
-----------------------------------------------------
452+
453+
A previous version of this PEP avoided adding a new wheel tag (``abi3t``),
454+
and specified that wheels tagged ``abi3`` would be compatible with
455+
free-threading if the *Python tag* is ``cp315`` or higher.
456+
457+
Such a scheme would work for this PEP, but it cannot express that an extension
458+
is compatible with both GIL-enabled and free-threaded builds
459+
of CPython 3.14 or lower.
460+
Adding a new explicit tag means that *if* we allow building such wheels in the
461+
future, packaging tools should not need additional changes to support them.
462+
They would be tagged ``cp314-abi3.abi3t``.
463+
464+
465+
Adding an ``abi4`` wheel tag
466+
----------------------------
467+
468+
Instead of ``abi3t``, we could “bump the version” and use ``abi4`` instead
469+
as the wheel ABI tag.
470+
In the wheel tag, the difference is largely cosmetic.
471+
472+
However, one thing this PEP does not propose is changing the *filename*
473+
tag: extensions will be named with the extensions like ``.abi3.so``.
474+
Changing this while keeping compatibility with GIL-enabled builds would be
475+
an unnecessary technical change.
325476

326-
[See discussion for now.]
477+
Using ``abi3.abi4`` in wheel tags but only ``.abi3`` in filenames would
478+
look more inconsistent than ``abi3.abi3t`` and ``.abi3``.
327479

328480

329481
Copyright

0 commit comments

Comments
 (0)