From 33459f0eeb4f6158020bec7b437e58d6be25ab74 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Tue, 24 Feb 2026 11:13:17 -0700 Subject: [PATCH 1/2] Add support for abi3.abi3t tag from PEP 803 --- src/packaging/tags.py | 22 +++++++++++++++++++++- tests/test_tags.py | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/packaging/tags.py b/src/packaging/tags.py index e3cc602ec..322433261 100644 --- a/src/packaging/tags.py +++ b/src/packaging/tags.py @@ -173,12 +173,20 @@ def _abi3_applies(python_version: PythonVersion, threading: bool) -> bool: """ Determine if the Python version supports abi3. - PEP 384 was first implemented in Python 3.2. The threaded (`--disable-gil`) + PEP 384 was first implemented in Python 3.2. The free-threaded builds do not support abi3. """ return len(python_version) > 1 and tuple(python_version) >= (3, 2) and not threading +def _abi3t_applies(python_version: PythonVersion) -> bool: + """ + Determine if the Python version supports abi3.abi3t. + + PEP 803 was first implemented in Python 3.15. + """ + return len(python_version) > 1 and tuple(python_version) >= (3, 15) + def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: py_version = tuple(py_version) # To allow for version comparison. abis = [] @@ -256,8 +264,13 @@ def cpython_tags( threading = _is_threaded_cpython(abis) use_abi3 = _abi3_applies(python_version, threading) + use_abi3t = _abi3t_applies(python_version) + if use_abi3: yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) + if use_abi3t: + yield from (Tag(interpreter, "abi3.abi3t", platform_) for platform_ in platforms) + yield from (Tag(interpreter, "none", platform_) for platform_ in platforms) if use_abi3: @@ -267,6 +280,13 @@ def cpython_tags( interpreter = f"cp{version}" yield Tag(interpreter, "abi3", platform_) + if use_abi3t: + for minor_version in range(python_version[1] - 1, 14, -1): + for platform_ in platforms: + version = _version_nodot((python_version[0], minor_version)) + interpreter = f"cp{version}" + yield Tag(interpreter, "abi3.abi3t", platform_) + def _generic_abi() -> list[str]: """ diff --git a/tests/test_tags.py b/tests/test_tags.py index 0439377ac..07d78a112 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -1042,6 +1042,44 @@ def test_all_args(self) -> None: tags.Tag("cp313", "none", "plat2"), ] + result = list(tags.cpython_tags((3, 15), ["cp315t"], ["platform"])) + assert result == [ + tags.Tag("cp315", "cp315t", "platform"), + tags.Tag("cp315", "abi3.abi3t", "platform"), + tags.Tag("cp315", "none", "platform"), + ] + + result = list(tags.cpython_tags((3, 16), ["cp316t"], ["platform"])) + assert result == [ + tags.Tag("cp316", "cp316t", "platform"), + tags.Tag("cp316", "abi3.abi3t", "platform"), + tags.Tag("cp316", "none", "platform"), + tags.Tag("cp315", "abi3.abi3t", "platform"), + ] + + result = list(tags.cpython_tags((3, 16), ["cp316"], ["platform"])) + assert result == [ + tags.Tag("cp316", "cp316", "platform"), + tags.Tag("cp316", "abi3", "platform"), + tags.Tag("cp316", "abi3.abi3t", "platform"), + tags.Tag("cp316", "none", "platform"), + tags.Tag("cp315", "abi3", "platform"), + tags.Tag("cp314", "abi3", "platform"), + tags.Tag("cp313", "abi3", "platform"), + tags.Tag("cp312", "abi3", "platform"), + tags.Tag("cp311", "abi3", "platform"), + tags.Tag("cp310", "abi3", "platform"), + tags.Tag("cp39", "abi3", "platform"), + tags.Tag("cp38", "abi3", "platform"), + tags.Tag("cp37", "abi3", "platform"), + tags.Tag("cp36", "abi3", "platform"), + tags.Tag("cp35", "abi3", "platform"), + tags.Tag("cp34", "abi3", "platform"), + tags.Tag("cp33", "abi3", "platform"), + tags.Tag("cp32", "abi3", "platform"), + tags.Tag("cp315", "abi3.abi3t", "platform"), + ] + def test_python_version_defaults(self) -> None: tag = next(tags.cpython_tags(abis=["abi3"], platforms=["any"])) interpreter = "cp" + tags._version_nodot(sys.version_info[:2]) From a8e97af48fb70469d9a79bfbe8fb3dca2359cad0 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Tue, 24 Feb 2026 12:28:06 -0700 Subject: [PATCH 2/2] fix linter --- src/packaging/tags.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/packaging/tags.py b/src/packaging/tags.py index 322433261..b28b032ea 100644 --- a/src/packaging/tags.py +++ b/src/packaging/tags.py @@ -187,6 +187,7 @@ def _abi3t_applies(python_version: PythonVersion) -> bool: """ return len(python_version) > 1 and tuple(python_version) >= (3, 15) + def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: py_version = tuple(py_version) # To allow for version comparison. abis = [] @@ -269,7 +270,9 @@ def cpython_tags( if use_abi3: yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) if use_abi3t: - yield from (Tag(interpreter, "abi3.abi3t", platform_) for platform_ in platforms) + yield from ( + Tag(interpreter, "abi3.abi3t", platform_) for platform_ in platforms + ) yield from (Tag(interpreter, "none", platform_) for platform_ in platforms)