Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 80 additions & 17 deletions peps/pep-0803.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Abstract
========

Add a new variant of the Stable ABI, called “Stable ABI for Free-Threaded
Python” (or ``abi3t`` for short), and a corresponding API limitations.
Python” (or ``abi3t`` for short).

``abi3t`` will be based on the existing Stable ABI (``abi3``), but make the
:c:type:`PyObject` structure opaque.
Expand Down Expand Up @@ -461,18 +461,36 @@ and may be removed in future CPython versions,
if the internal object layout needs to change.


The ``abi3t`` wheel tag
-----------------------
The ``abi3t`` wheel and filename tags
-------------------------------------

Wheels that use a stable ABI compatible with free-threading CPython builds
should use a new `ABI tag`_: ``abi3t``.

.. _ABI tag: https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#abi-tag

On systems where filenames of Stable ABI extensions end with ``.abi3.so``,
extensions compatible with ``abi3t`` should instead use ``.abi3t.so``.
Extensions compatible with *both* ``abi3`` and ``abi3t`` should not use
a tag; they sould end in ``.so`` only.

On these systems, free-threaded builds of CPython will load extensions
with the ``abi3t`` tag.

For example, for ``x86_64-linux-gnu`` builds of CPython,
``importlib.machinery.EXTENSION_SUFFIXES`` will be:

* for ``python3.15``:
``['.cpython-315-x86_64-linux-gnu.so', '.abi3.so', '.so']``
* for ``python3.15t``:
``['.cpython-315-x86_64-linux-gnu.so', '.abi3t.so', '.so']``


Recommendations for installers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Package installers should treat this tag as completely separate from ``abi3``.
Package installers should treat the ``abi3t`` tag as completely separate
from ``abi3``.
They should allow ``abi3t``-tagged wheels for free-threaded builds wherever
they currently allow ``abi3``-tagged ones for (otherwise equal)
non-free-threaded builds.
Expand All @@ -492,14 +510,25 @@ Stable ABI (``abi3``):
- defining ``Py_GIL_DISABLED`` (on Windows)
- building with free-threaded CPython headers (elsewhere)

Such extensions should be tagged with the `compressed tag set`_
``abi3.abi3t``.
The filename of the resulting extension should not have a :pep:`3149`
tag: it should be named :samp:`{modulename}.so`, :samp:`{modulename}.pyd`
or similar.

Wheels with such extensions should be tagged with the
`compressed tag set`_ ``abi3.abi3t``.

- Compile extensions compatible with *only* ``abi3t``, by defining only
:samp:`Py_TARGET_ABI3T={v}` and tagging the result with ``abi3t``.
This will initially offer no advantages over the ``abi3.abi3t`` option
above, but there is a possibility that it will become useful in the future.

On systems that use the :pep:`3149` tag ``abi3`` tag (e.g. on Linux, macOS,
and similar, which use :samp:`{modulename}.abi3.so`),
such extensions should use the tag ``abi3t`` (that is, the extension should
be named :samp:`{modulename}.abi3t.so` on those systems).

Wheels with such extensions should be tagged with the ABI tag ``abi3t``.

In the above, :samp:`{v}` stands for a the lowest Python version with which
the extension should be compatible, in :c:func:`Py_PACK_VERSION` format.
In the cases above, this version must be set to 3.15 or higher.
Expand Down Expand Up @@ -644,7 +673,7 @@ free-threaded one.
(*): Wheels with these tags cannot be built; see table below

The following table summarizes which wheel tag should be used for an extension
built with a given interpreter and ``Py_LIMITED_API`` macro:
built with the given interpreter and defined macros:

+-----------------------+-------------+--------------------+---------------------+-----------+
| To get the wheel tag… | Compile on… | ``Py_LIMITED_API`` | ``Py_TARGET_ABI3T`` | Note |
Expand Down Expand Up @@ -720,7 +749,8 @@ This PEP combines several pieces, implemented individually:
`python/cpython#137212 <https://github.com/python/cpython/pull/137212>`__.
- A check for older ``abi3`` was implemented in GitHub pull request
`python/cpython#137957 <https://github.com/python/cpython/pull/137957>`__.
- For wheel tags, there is no implementation yet.
- For wheel tags, a draft pull request is at
`pypa/packaging/pull#1099 <https://github.com/pypa/packaging/pull/1099>`__.
- A porting guide is not yet written.


Expand Down Expand Up @@ -783,15 +813,8 @@ Naming this ``abi4``
Instead of ``abi3t``, we could “bump the version” and use ``abi4`` instead.
The difference is largely cosmetic.

However, one thing this PEP does not propose is changing the *filename*
tag: extensions will be named with the extensions like ``.abi3.so``.
Changing this while keeping compatibility with GIL-enabled builds would be
an unnecessary technical change.

Using ``abi3.abi4`` in wheel tags but only ``.abi3`` in filenames would
look more inconsistent than ``abi3.abi3t`` and ``.abi3``.

If we added an ``abi4`` tag, the ``Py_LIMITED_API`` value would either need to:
If we added an ``abi4`` tag, the value of the opt-in macro (``Py_TARGET_ABI4``
or ``Py_LIMITED_API`` or some such) would either need to:

* change to start with ``4`` to match ``abi4``, but no longer correspond
to ``PY_VERSION_HEX`` (making it harder to generate and check), or
Expand All @@ -802,6 +825,24 @@ better as a transitional state before larger changes like :pep:`809`'s
``abi2026``.


``abi3+abi3t`` filename tag
---------------------------

Extensions that are compatible with both ``abi3`` and ``abi3t`` can
use a "compressed tag set" (``abi3.abi3t``) in wheel metadata,
but not in filenames (``.abi3.so``/``.abi3t.so``).

We could add a dedicated tag for the combination -- for example,
``.abi3+abi3t.so`` -- but this would have no practical benefits over
omitting the tag altogether -- that is, using bare ``.so``.
Specifically, bare ``.so`` meets the needs of :pep:`3149` (which introduced
the filename tags): existing stable ABI extensions (``.abi3.so``)
and version-specific ABI extensions (``.cpNN-*.so``) can be installed
alongside the ``.so`` file, and will be preferred by interpreters that can
load them.



Reusing ``Py_GIL_DISABLED`` to enable the new ABI
-------------------------------------------------

Expand All @@ -825,6 +866,28 @@ the ability to build for the GIL-only Stable ABI with no source changes
was deemed to be worth an extra configuration macro (``Py_TARGET_ABI3T``).


Making ``abi3t`` compatible with GIL-enabled builds
---------------------------------------------------

Initially, ``abi3t`` will be compatible with ``abi3``.
It would be possible to promise that it will always be so.
This would make the ``abi3.abi3t`` tag unnecessary;
``abi3t`` could be used instead.

In this case, installers would need to allow ``abi3t``-tagged wheels
for GIL-enabled builds of Python, needing a change in installers.
Since installers written in Python typically use/vendor the :pypi:`packaging`
library, this change would mostly be limited to one repository.

The wheel tag ``abi3.abi3t`` would be valid in this scenario;
it could be used to support existing installers (which "know about" ``abi3``
but not ``abi3t``), to experiment with supporting Python 3.14, and in similar
cases.

However, this would prevent the possibility of ever making ``abi3``
and ``abi3t`` diverge.


Copyright
=========

Expand Down
Loading