From 4e066a20567ab09d6252116d367a449f86425d76 Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Tue, 23 Sep 2025 18:02:43 +0200 Subject: [PATCH 01/36] PEP 780: Update to use sys.abi_info --- peps/pep-0780.rst | 123 ++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 59 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index b488e3872cc..54158f3b9ed 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -22,15 +22,16 @@ Post-History: Abstract ======== -This PEP defines using ABI features as environment markers for project -dependencies, through a new ``sys_abi_features`` environment marker. :pep:`508` -(later moved to :ref:`packaging:dependency-specifiers`) introduced environment -markers to specify dependencies based on rules that describe when the -dependency should be used. This PEP extends the environment markers to allow -specifying dependencies based on specific ABI features of the Python -interpreter. For this, it defines a set of `ABI Features`_ and specifies how -they are made available for `environment markers `_ -as a new marker variable, ``sys_abi_features``. +This PEP defines the use of information about the interpreter ABI as +environment markers for project dependencies through a new ``sys_abi_info`` +environment marker variable. :pep:`508` (later moved to +:ref:`packaging:dependency-specifiers`) introduced environment markers to +specify dependencies based on rules that describe when the dependency should +be used. This PEP extends environment markers to allow specifying dependencies +based on specific information about the ABI of the Python interpreter. For +this, it defines a set of `ABI Features`_ and specifies how they are made +available for `environment markers `_ via a new marker +variable, ``sys_abi_info``. Motivation ========== @@ -57,23 +58,19 @@ marker for free-threading`_ Discourse thread: wheels. Picking up the wrong Cython version is causing a lot of obscure build failures and runtime crashes. It would be beneficial if the metadata could express that (c.f. `Require Cython Pre-release for Free-Threaded Python`_). -- CFFI has no support for free-threading yet, and `Armin Rigo, one of the - maintainers, has stated - `__ - that it may be a good idea to fork ``cffi``, implement support for - free-threading, and only come back to the CFFI project with a single large PR - that adds support after the functionality "is reasonably well-tested (either - as tests or, better in this case, tested by being in use in various other - projects)". There are a lot of projects that depend on ``cffi``. They are - likely fine to start depending on a fork for free-threading only, however +- CFFI has only recently gained support for free-threading, and for a + significant period of time, it looked likely that support would first be + added in a fork. There are a lot of projects that depend on ``cffi``, which + are likely fine to start depending on a fork for free-threading only, however depending on a fork for >=3.13 or for all Python versions seems like a much - larger ask, and more disruptive for distribution packagers. + larger ask, and more disruptive for distribution packagers. While the + situation has been resolved with CFFI 2.0.0, other projects may face similar + issues. -While these concrete examples may be addressed later this year by Cython and -CFFI making compatible releases, the same issue is going to repeat further up -the stack. The free-threading rollout is expected to take several years, and an -environment marker for free-threading will make that rollout significantly -easier. +While concrete examples may be addressed with compatible releases, the same +issue is going to repeat further up the stack. The free-threading rollout is +expected to take several years, and an environment marker for free-threading +will make that rollout significantly easier. Another important ABI feature that is not yet covered by environment markers is the bitness of the interpreter. In most cases, the ``sys_platform`` or @@ -135,7 +132,7 @@ Relation to Other PEPs This PEP extends environment markers with set semantics for ABI features. :pep:`751#additions-to-marker-expression-syntax` includes a similar extension for lock file specific environment markers; although the two have been -developed indepedently, they are compatible where they overlap in terms of the +developed independently, they are compatible where they overlap in terms of the new set semantics. Specification @@ -149,49 +146,57 @@ and "**OPTIONAL**"" in this document are to be interpreted as described in ABI Features ------------ -ABI features are intrinsic properties of the Python interpreter, expressed as -simple, understandable strings. However, not all features are equally -applicable to all Python interpreters or Python versions. For example, the -distinction between free-threaded and GIL-enabled interpreters is only relevant -for CPython 3.13 onwards, but the bitness of the interpreter is relevant for -all interpreters. +ABI features are intrinsic properties of the Python interpreter. +However, not all features are equally applicable to all Python interpreters or +Python versions. For example, the distinction between free-threaded and +GIL-enabled interpreters is only relevant for CPython 3.13 onwards, but the +bitness of the interpreter, i.e. the number of bits in a pointer, is relevant +for all interpreters. All interpreters MUST handle the following ABI features as stated. ABI features that are restricted to particular interpreters MUST NOT be provided by other -interpreters. The features are subdivided into groups and for each group there -MUST be exactly one feature present, except when the group is marked as -optional, in which case there MUST be at most one feature present. +interpreters. -``free-threading`` or ``gil-enabled`` (only CPython) - If the Python interpreter is free-threaded, the ``free-threading`` feature - MUST be present and the ``gil-enabled`` feature MUST NOT be present. - Otherwise, the ``gil-enabled`` feature MUST be present and the - ``free-threading`` feature MUST NOT be present. +In Python 3.15 and later, the ABI features are determined by the new +``sys.abi_info`` attribute. In earlier Python versions, the ABI features are +the same as for Python 3.15 and given as follows: -``debug`` (only CPython, optional) +``pointer_bits`` + The bitness of the interpreter, that is, the number of bits in a pointer, + typically ``32`` or ``64`` [#bitness]_. + +``free_threaded`` (only CPython) + If the Python interpreter is free-threaded, ``free_threaded`` MUST be + ``True``, otherwise it MUST be ``False``. + +``debug`` (only CPython) This ABI feature is reserved for the ``--with-pydebug`` build of CPython. If the interpreter is a CPython interpreter with ``Py_DEBUG`` capabilities, - the ``debug`` feature MUST be present. On POSIX systems, this corresponds + the ``debug`` feature MUST be ``True``. On POSIX systems, this corresponds to the Python expression ``"d" in sys.abiflags``. -``32-bit`` or ``64-bit`` (optional) - The bitness of the interpreter, that is, whether it is a 32-bit or 64-bit - build [#bitness]_. If the bitness is unknown or neither 32-bit nor 64-bit, - this feature MUST NOT be present. +``byteorder`` + Indicates the byte order of the interpreter. The value MUST be either + ``"little"`` or ``"big"``. -.. _pep-780-sys_abi_features: +.. _pep-780-sys_abi_info: -The ``sys_abi_features`` Environment Marker +The ``sys_abi_info`` Environment Marker ------------------------------------------- To make ABI features available in dependency specifications, a new environment -marker variable, ``sys_abi_features``, is added to the format of dependency -specifiers. +marker variable, ``sys_abi_info``, is added to the format of dependency +specifiers. It is built to reflect the value of ``sys.abi_info``, which is a +new attribute of the ``sys`` module introduced in Python 3.15 as a simple +namespace. To represent its fields in the environment marker variable, they are +expressed as a frozen set of strings of the form ``f"{name}::{value}"``, where +``name`` is the name of the field and ``value`` is the string representation of +its value. To do this, we need to extend the grammar laid out in :pep:`508` and maintained in the :ref:`packaging:dependency-specifiers` and document the possible values. -The grammar is extended to include the ``sys_abi_features`` marker variable by +The grammar is extended to include the ``sys_abi_info`` marker variable by augmenting the definition of ``env_var`` as follows:: env_var = ('python_version' | 'python_full_version' | @@ -199,7 +204,7 @@ augmenting the definition of ``env_var`` as follows:: 'platform_system' | 'platform_version' | 'platform_machine' | 'platform_python_implementation' | 'implementation_name' | 'implementation_version' | - 'sys_abi_features' | + 'sys_abi_info' | 'extra' # ONLY when defined by a containing layer ) @@ -212,10 +217,10 @@ Like the grammar, also the overview table of environment markers in * - Marker - Python equivalent - Sample values - * - ``sys_abi_features`` - - no direct equivalent available - - ``{'free-threading', '64-bit'}``, - ``{'gil-enabled', 'debug', '32-bit'}`` + * - ``sys_abi_info`` + - ``sys.abi_info`` + - ``{'free_threaded::True', 'pointer_bits::64'}``, + ``{'free_threaded::False', 'debug::True', 'pointer_bits::32'}`` With these additions, ABI features can be used in dependency specifications via the ``in`` operator to test for the presence of a feature, or the ``not in`` @@ -229,22 +234,22 @@ Require Cython Pre-release for Free-Threaded Python To require a pre-release of Cython only for a free-threaded Python interpreter, the following dependency specification can be used:: - cython >3.1.0a1; "free-threading" in sys_abi_features - cython ==3.0.*; "free-threading" not in sys_abi_features + cython >3.1.0a1; "free_threaded::True" in sys_abi_info + cython ==3.0.*; "free_threaded::False" in sys_abi_info Require SciPy Unless on 32-bit ``win32`` ---------------------------------------- To require SciPy unless on a 32-bit interpreter on Windows, the following dependency specification can be used:: - scipy; platform_system != "Windows" or "32-bit" not in sys_abi_features + scipy; platform_system != "Windows" or "pointer_bits::32" not in sys_abi_info Require NumPy for a Free-Threaded Interpreter With Debugging Capabilities -------------------------------------------------------------------------- To require NumPy only for a free-threaded interpreter with debugging capabilities, the following dependency can be used:: - numpy; "free-threading" in sys_abi_features and "debug" in sys_abi_features + numpy; "free-threaded::True" in sys_abi_info and "debug::True" in sys_abi_info Backwards Compatibility ======================= From 174ff299937a8231afe1fe3cf62ae90269b274a9 Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Fri, 26 Sep 2025 15:13:37 +0200 Subject: [PATCH 02/36] Address review --- peps/pep-0780.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 54158f3b9ed..bd0b8441557 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -8,7 +8,7 @@ Status: Draft Type: Standards Track Topic: Packaging Created: 21-Mar-2025 -Python-Version: 3.14 +Python-Version: 3.15 Post-History: `05-Aug-2024 `__, `26-Mar-2025 `__, @@ -158,8 +158,8 @@ that are restricted to particular interpreters MUST NOT be provided by other interpreters. In Python 3.15 and later, the ABI features are determined by the new -``sys.abi_info`` attribute. In earlier Python versions, the ABI features are -the same as for Python 3.15 and given as follows: +:external+py3.15:py:data:`sys.abi_info` attribute. In earlier Python versions, +the ABI features are the same as for Python 3.15 and given as follows: ``pointer_bits`` The bitness of the interpreter, that is, the number of bits in a pointer, @@ -170,10 +170,8 @@ the same as for Python 3.15 and given as follows: ``True``, otherwise it MUST be ``False``. ``debug`` (only CPython) - This ABI feature is reserved for the ``--with-pydebug`` build of CPython. - If the interpreter is a CPython interpreter with ``Py_DEBUG`` capabilities, - the ``debug`` feature MUST be ``True``. On POSIX systems, this corresponds - to the Python expression ``"d" in sys.abiflags``. + This ABI feature corresponds to the + :external+py3.15:py:attr:`sys.abi_info.debug` field. ``byteorder`` Indicates the byte order of the interpreter. The value MUST be either @@ -182,7 +180,7 @@ the same as for Python 3.15 and given as follows: .. _pep-780-sys_abi_info: The ``sys_abi_info`` Environment Marker -------------------------------------------- +--------------------------------------- To make ABI features available in dependency specifications, a new environment marker variable, ``sys_abi_info``, is added to the format of dependency From bb774520d02a1a9c9b26d496b471ab3ee5c24272 Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Fri, 31 Oct 2025 15:39:24 +0100 Subject: [PATCH 03/36] Apply suggestion from @AA-Turner Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- peps/pep-0780.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index bd0b8441557..32112c611f6 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -62,7 +62,7 @@ marker for free-threading`_ Discourse thread: significant period of time, it looked likely that support would first be added in a fork. There are a lot of projects that depend on ``cffi``, which are likely fine to start depending on a fork for free-threading only, however - depending on a fork for >=3.13 or for all Python versions seems like a much + depending on a fork for >=3.13 or for all Python versions seemed like a much larger ask, and more disruptive for distribution packagers. While the situation has been resolved with CFFI 2.0.0, other projects may face similar issues. From 53531773d45d1c5a4e0b9b6b143a9760b621fd3e Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Fri, 31 Oct 2025 16:01:54 +0100 Subject: [PATCH 04/36] Address review comments --- peps/pep-0780.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 32112c611f6..73206b164c4 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -218,7 +218,8 @@ Like the grammar, also the overview table of environment markers in * - ``sys_abi_info`` - ``sys.abi_info`` - ``{'free_threaded::True', 'pointer_bits::64'}``, - ``{'free_threaded::False', 'debug::True', 'pointer_bits::32'}`` + ``{'free_threaded::False', 'debug::True', 'pointer_bits::32'}``, + ``{'byteorder::little', 'pointer_bits::64'}`` With these additions, ABI features can be used in dependency specifications via the ``in`` operator to test for the presence of a feature, or the ``not in`` From 9fd6dad328253166d076b1e1ce1c7918f1fb7449 Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Sun, 2 Nov 2025 16:17:00 +0100 Subject: [PATCH 05/36] Add pyyaml fork example --- peps/pep-0780.rst | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 73206b164c4..24a130e10b9 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -229,7 +229,7 @@ Examples ======== Require Cython Pre-release for Free-Threaded Python ----------------------------------------------------- +--------------------------------------------------- To require a pre-release of Cython only for a free-threaded Python interpreter, the following dependency specification can be used:: @@ -244,12 +244,24 @@ dependency specification can be used:: scipy; platform_system != "Windows" or "pointer_bits::32" not in sys_abi_info Require NumPy for a Free-Threaded Interpreter With Debugging Capabilities --------------------------------------------------------------------------- +------------------------------------------------------------------------- To require NumPy only for a free-threaded interpreter with debugging capabilities, the following dependency can be used:: numpy; "free-threaded::True" in sys_abi_info and "debug::True" in sys_abi_info +Require Free-Threaded Fork of PyYAML +------------------------------------ +PyYAML initially decided not to support free-threading in its mainline +distribution before wider testing of free-threaded Python in the real world. +To faciliate this testing, a free-threaded fork, PyYAML-ft, was created. +To require this fork, for a free-threaded Python interpreter, without forcing +it also on the GIL-enabled interpreter, the following dependency specification +can be used:: + + pyyaml-ft; "free_threaded::True" in sys_abi_info + pyyaml; "free_threaded::True" not in sys_abi_info + Backwards Compatibility ======================= From 388c7d35449ea2b71ce5253bad0df7803930b06e Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Mon, 3 Nov 2025 14:16:32 +0100 Subject: [PATCH 06/36] Update env_var grammar specs --- peps/pep-0780.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 24a130e10b9..310c7bcc2fe 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -203,7 +203,7 @@ augmenting the definition of ``env_var`` as follows:: 'platform_machine' | 'platform_python_implementation' | 'implementation_name' | 'implementation_version' | 'sys_abi_info' | - 'extra' # ONLY when defined by a containing layer + 'extra' | 'extras' | 'dependency_groups' # ONLY when defined by a containing layer ) Like the grammar, also the overview table of environment markers in From 4051d6cd27ef899fa05edd9af848c6d30c788c4b Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Mon, 3 Nov 2025 15:09:19 +0100 Subject: [PATCH 07/36] Add details to specification and explain use w/ unknown features --- peps/pep-0780.rst | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 310c7bcc2fe..dd5b724e186 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -191,11 +191,12 @@ expressed as a frozen set of strings of the form ``f"{name}::{value}"``, where ``name`` is the name of the field and ``value`` is the string representation of its value. +The ``sys_abi_info`` environment variable +''''''''''''''''''''''''''''''''''''''''' To do this, we need to extend the grammar laid out in :pep:`508` and maintained -in the :ref:`packaging:dependency-specifiers` and document the possible values. - -The grammar is extended to include the ``sys_abi_info`` marker variable by -augmenting the definition of ``env_var`` as follows:: +in the :ref:`packaging:dependency-specifiers` and document the possible values, +to include the ``sys_abi_info`` marker variable by augmenting the definition of +``env_var`` as follows:: env_var = ('python_version' | 'python_full_version' | 'os_name' | 'sys_platform' | 'platform_release' | @@ -206,6 +207,10 @@ augmenting the definition of ``env_var`` as follows:: 'extra' | 'extras' | 'dependency_groups' # ONLY when defined by a containing layer ) +This makes ``sys_abi_info`` available as a variable in marker expressions. + +The Values of ``sys_abi_info`` +'''''''''''''''''''''''''''''' Like the grammar, also the overview table of environment markers in :ref:`packaging:dependency-specifiers` is augmented to add the following row: @@ -225,6 +230,31 @@ With these additions, ABI features can be used in dependency specifications via the ``in`` operator to test for the presence of a feature, or the ``not in`` operator to test for the absence of a feature. +This allows for marker expressions such as:: + + "free_threaded::True" in sys_abi_info + "pointer_bits::32" not in sys_abi_info and "debug::True" in sys_abi_info + +Note that this is forward compatible in the sense that future additions to the +set of ABI features will not be in conflict with the grammar, such that tools +encountering unknown ABI features in a dependency specification will naturally +evaluate the test as false. This empowers package authors to decide on the +default resolution in this case. For example, a package author may decide to +require a dependency only if an ABI feature is present, by using a presence +test like ``"new_feature::True" in sys_abi_info``, which will evaluate to +false on current interpreters that do not support the new feature, or an +absence test like ``"new_feature::False" not in sys_abi_info``, which will +evaluate to true on current interpreters. + +While covering all ABI features specified at the moment, this mechanism is only +meaningfully applicable where the ABI feature is unambiguously representable as +a string. Currently, all ABI features are either booleans, integers, or +strings, which all satisfy this requirement. + +Should the future reveal a need for ABI features that are not unambiguously +represented as strings, like floating point numbers or more complex data +structures, this PEP would need to be revisited to address those. + Examples ======== From 9356687e834471439c678be1fdd728de637962e9 Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Mon, 3 Nov 2025 16:22:36 +0100 Subject: [PATCH 08/36] Expand on backward compatibility --- peps/pep-0780.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index dd5b724e186..a842fb7dec7 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -191,7 +191,7 @@ expressed as a frozen set of strings of the form ``f"{name}::{value}"``, where ``name`` is the name of the field and ``value`` is the string representation of its value. -The ``sys_abi_info`` environment variable +The ``sys_abi_info`` Environment Variable ''''''''''''''''''''''''''''''''''''''''' To do this, we need to extend the grammar laid out in :pep:`508` and maintained in the :ref:`packaging:dependency-specifiers` and document the possible values, @@ -303,6 +303,15 @@ However, the introduction of the feature has implications for a number of ecosystem tools, especially those which attempt to support examination of data in ``pyproject.toml`` and ``requirements.txt``. +In particular, current tools generally work with a fixed list of environment +variables, either in their own implementation (e.g. `uv `_) +or via an established package like `pypa/packaging `_ (e.g. pip). +Hence, it is principally impossible to add any new environment markers without +making new packages using these markers incompatible with older versions of +these tools. +However, once these tools support the proposed marker variable, changes in its +contents are handled gracefully. + Audit and Update Tools ---------------------- From c33d407365c7facf0c287fb801304d3406583746 Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Tue, 4 Nov 2025 09:46:15 +0100 Subject: [PATCH 09/36] Update peps/pep-0780.rst Co-authored-by: Jelle Zijlstra --- peps/pep-0780.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index a842fb7dec7..d3094cfdcf5 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -284,7 +284,7 @@ Require Free-Threaded Fork of PyYAML ------------------------------------ PyYAML initially decided not to support free-threading in its mainline distribution before wider testing of free-threaded Python in the real world. -To faciliate this testing, a free-threaded fork, PyYAML-ft, was created. +To facilitate this testing, a free-threaded fork, PyYAML-ft, was created. To require this fork, for a free-threaded Python interpreter, without forcing it also on the GIL-enabled interpreter, the following dependency specification can be used:: From 81194b1f7c12e7b40702fd1ad469faaa98fbb1a9 Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Tue, 4 Nov 2025 09:53:56 +0100 Subject: [PATCH 10/36] Move long links to link collection --- peps/pep-0780.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index d3094cfdcf5..8c64bda8cc6 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -304,8 +304,8 @@ ecosystem tools, especially those which attempt to support examination of data in ``pyproject.toml`` and ``requirements.txt``. In particular, current tools generally work with a fixed list of environment -variables, either in their own implementation (e.g. `uv `_) -or via an established package like `pypa/packaging `_ (e.g. pip). +variables, either in their own implementation (e.g. `uv`_) or via an +established package like `pypa/packaging`_ (e.g. pip). Hence, it is principally impossible to add any new environment markers without making new packages using these markers incompatible with older versions of these tools. @@ -415,6 +415,8 @@ Footnotes particularly on platforms that allow the execution of either kind of binary. +.. _uv: https://github.com/astral-sh/uv/blob/86e7b2e97a193ce3f506804be4c41c611191fa72/crates/uv-pep508/src/marker/tree.rs#L170 +.. _pypa/packaging: https://github.com/pypa/packaging/blob/8f13a4309aa620bf643cd508304f783b456e8c49/src/packaging/_tokenizer.py#L63 .. _Python experimental support for free threading: https://docs.python.org/3/howto/free-threading-python.html .. _Python free-threading guide: https://py-free-threading.github.io/ .. _Environment marker for free-threading: https://discuss.python.org/t/environment-marker-for-free-threading/60007 From 3a4baea75f95c5685459e0d7980af6ce72fca34c Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Tue, 4 Nov 2025 10:06:44 +0100 Subject: [PATCH 11/36] Add clarification for pyyaml example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Górny --- peps/pep-0780.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 8c64bda8cc6..fe967f75a7f 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -292,6 +292,15 @@ can be used:: pyyaml-ft; "free_threaded::True" in sys_abi_info pyyaml; "free_threaded::True" not in sys_abi_info +Note that in the absence of the features described in this PEP, early adopting +projects have had to resort to using the fork for *all* builds of a potentially +free threading Python interpreter; typical dependencies than look like:: + + pyyaml; python_version<"3.13" + pyyaml-ft; python_version>="3.13" + +which is an undesirable side effect for GIL-enabled environments. + Backwards Compatibility ======================= From 1f150be365e083006c566db7b6a2c2c6138ee3c2 Mon Sep 17 00:00:00 2001 From: Klaus Zimmermann Date: Wed, 5 Nov 2025 15:57:49 +0100 Subject: [PATCH 12/36] Update peps/pep-0780.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Górny --- peps/pep-0780.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index fe967f75a7f..29957a38b57 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -294,7 +294,7 @@ can be used:: Note that in the absence of the features described in this PEP, early adopting projects have had to resort to using the fork for *all* builds of a potentially -free threading Python interpreter; typical dependencies than look like:: +free threading Python interpreter; typical dependencies then looked like:: pyyaml; python_version<"3.13" pyyaml-ft; python_version>="3.13" From fb6eed136322f30f167994843ab06b3fc9940bc3 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 19:39:35 +0000 Subject: [PATCH 13/36] Add sections and appendix with analysis for tools seeing unknown markers --- peps/pep-0780.rst | 115 ++++++++--- ...appendix-tool-behavior-unknown-markers.rst | 188 ++++++++++++++++++ 2 files changed, 276 insertions(+), 27 deletions(-) create mode 100644 peps/pep-0780/appendix-tool-behavior-unknown-markers.rst diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 29957a38b57..725258a9ff2 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -255,6 +255,33 @@ Should the future reveal a need for ABI features that are not unambiguously represented as strings, like floating point numbers or more complex data structures, this PEP would need to be revisited to address those. +Handling Unsupported Marker Fields +---------------------------------- + +The Dependency Specifiers specification states that references to unknown marker +fields SHOULD render a package version ineligible for installation or inclusion +in a locked dependency tree. This PEP clarifies that rule as follows. + +Consumers do not need to successfully parse an unknown marker field to implement +this behavior. When a locking or installation tool cannot interpret published +dependency metadata because a marker field is unsupported, it SHOULD treat the +containing package version as ineligible and SHOULD continue considering other +versions where possible. A consumer MAY conservatively reject a package version +when any of its published dependency specifications cannot be parsed, without +distinguishing unsupported marker fields from malformed requirements. + +Consumers MUST NOT recover by dropping an unsupported marker, discarding the +dependency that contains it, or assuming a truth value for its expression. Such +recovery can produce an apparently successful installation with incorrect +dependencies. If no eligible candidate +remains, consumers SHOULD report a descriptive failure explaining the unsupported +metadata and, where possible, suggesting an upgrade of the consuming tool. + +This clarification concerns interpreting published dependency metadata. It does +not require tools to recover from failures while preparing an sdist or generating +its metadata, as discussed in `Backwards Compatibility`_. + + Examples ======== @@ -301,41 +328,69 @@ free threading Python interpreter; typical dependencies then looked like:: which is an undesirable side effect for GIL-enabled environments. +.. _pep780-backwards-compatibility: + Backwards Compatibility ======================= -This is a pure extension to the existing environment markers and does not -affect existing environment markers or dependency specifications, hence there -are no direct backwards compatibility concerns. - -However, the introduction of the feature has implications for a number of -ecosystem tools, especially those which attempt to support examination of data -in ``pyproject.toml`` and ``requirements.txt``. - -In particular, current tools generally work with a fixed list of environment -variables, either in their own implementation (e.g. `uv`_) or via an -established package like `pypa/packaging`_ (e.g. pip). -Hence, it is principally impossible to add any new environment markers without -making new packages using these markers incompatible with older versions of -these tools. -However, once these tools support the proposed marker variable, changes in its -contents are handled gracefully. +Introducing a new environment marker can affect tools that do not understand +it. Packaging interoperability generally follows the principle of strict +validation when producing or admitting new metadata, and forward-compatible +handling when consuming metadata that has already been published. + +Build backends, publishing tools, and package indexes should understand and +validate new metadata features before producing or accepting them. Consumers +can ignore new optional information when it is unnecessary for their operation. +When new semantics are needed to determine dependencies or compatibility, +consumers should instead consider the affected package version unsupported. +This PEP introduces no additional index activation mechanism or waiting period. + +Marker field names are part of a closed grammar. Tools that predate +``sys_abi_info`` may therefore reject a dependency containing it as a parsing +error. No open-ended marker grammar is needed for safe consumption: the +resolver can treat that error as making the containing package version +ineligible and try other versions. This preserves correctness without requiring +the consumer to understand the new marker. See +`Handling Unsupported Marker Fields`_ for the specification clarification. + +Already released tools cannot acquire this behavior retroactively. For wheel +dependency metadata, pip 24.1 and later can skip a package version with an +unsupported marker and select an older version; pip 24.0 instead aborts +resolution. Other tools also differ in their handling of unsupported markers. +A pinned version or directly requested artifact may leave no eligible alternative +and result in an installation failure. + +Source distributions have additional limitations. An unsupported marker in +``build-system.requires`` can cause the frontend to fail before running the +backend. An unsupported marker in ``project.dependencies`` can cause the backend +to fail during metadata generation. Validation may occur as early as the +backend hook that determines additional build requirements. These errors may +abort installation rather than cause fallback to an older release, including +when installing from an +index. This PEP does not require changes to that behavior: failure is an +acceptable outcome for older tools encountering such source distributions. +Installing a usable wheel does not require inspecting the sdist's build +requirements. The :ref:`tool behavior appendix +` records these distinctions in detail. + +Projects adopting ``sys_abi_info`` should account for these compatibility +boundaries and their users' installation and locking tools. Adoption timing is +left to projects; this PEP specifies no minimum ecosystem support threshold. +Once tools understand ``sys_abi_info``, additional values in its set can be +handled through the membership semantics specified above. Unknown marker +*fields* must not be confused with absent or unknown ABI feature *values*. Audit and Update Tools ---------------------- -A wide range of tools understand Python dependency data as expressed in -``requirements.txt`` files. (e.g., Dependabot, Tidelift, etc) +A wide range of tools inspect dependency data in ``requirements.txt`` and +``pyproject.toml`` files and offer assisted or automated updates, for example +Dependabot and Tidelift. Tools that interpret the meaning of ``sys_abi_info`` +need explicit support for it. Tools consuming published distributions can +remain correct by rejecting versions with unsupported dependency metadata, +although this can limit which releases they consider. Static analysis and +update workflows may lose functionality until their tools support the marker. -Such tools inspect dependency data and, in some cases, offer tool-assisted or -fully automated updates. It is our expectation that no such tools would support -the new environment markers at first, and broad ecosystem support could take -many months or even some number of years to arrive. - -As a result, users of the new environment markers would experience a -degradation in their workflows and tool support at the time that they start -using them. This is true of any new standard for where and how dependency data -are encoded. Security Implications ===================== @@ -440,6 +495,12 @@ Thanks to Filipe Laíns for the suggestion of the ``abi_features`` attribute and to Stephen Rosen for the Backwards Compatibility section of :pep:`735`, which served as a template for the corresponding section in this PEP. +Appendices +========== + +- :ref:`pep780-tool-behavior-unknown-markers` + + Copyright ========= diff --git a/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst b/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst new file mode 100644 index 00000000000..ebe3b6302e2 --- /dev/null +++ b/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst @@ -0,0 +1,188 @@ +:orphan: + +.. _pep780-tool-behavior-unknown-markers: + +Appendix: Compatibility behavior in existing tools +================================================== + +This non-normative appendix supplements the :ref:`Backwards Compatibility +` section of :pep:`780`. It describes how +existing packaging tools handle dependencies containing markers they do not +understand. + +To test whether tools can fall back to an older release, two versions of a +package named ``marker-test`` are made available as wheels. Version 1.0 has no +dependencies. Version 2.0 adds a dependency on ``idna`` conditional on +``sys_abi_info``, which the tested tools do not recognize. Its wheel metadata +contains:: + + Requires-Dist: idna; "pointer_bits::64" in sys_abi_info + +A consumer that does not understand ``sys_abi_info`` should reject version 2.0 +and may select version 1.0. The marker expression tests whether the interpreter +has 64-bit pointers, but consumers that do not recognize the field name cannot +interpret that condition. + +The following table summarizes the wheel case. The detailed sections below +separate resolver tests from source inspection and metadata-conversion tests. + +.. list-table:: Wheel dependency metadata containing an unknown marker + :header-rows: 1 + :widths: 20 55 25 + + * - Tool + - Behavior + - Older-release fallback + * - pip + - 24.0 (Feb 2024) aborts; 24.1 (Jun 2024) and later reject the package version + - Yes from 24.1 + * - uv + - 0.7.0 (Apr 2025) and 0.13.6 (Oct 2026), without preview features, + select the older release + - Yes + * - PDM + - 2.29.5 (Oct 2026) rejects the package version; the recovery policy is also + present in 2.13.0 (Mar 2024) + - Yes + * - Poetry + - 1.8.2 (Mar 2024) and 2.5.1 (Sep 2026) strip invalid markers; + 2.5.1 drops the unknown-marker dependency in the tested conversion path + - No + + +For their pip-based resolver paths, Pipenv and pip-tools do not add independent +resolver behavior here: Pipenv uses an embedded/patched pip resolver, while +pip-tools invokes pip's resolver internals. Their behavior therefore follows +the corresponding pip version. + +pip +--- + +The table below shows how pip handles an unsupported marker in runtime or +build dependencies when installing a local project, a wheel, or a source +distribution. Local tests with +pip 26.2.2 (Oct 2026) used ``--find-links`` candidates, isolated setuptools builds, and +dry-run installation; packages were not uploaded to TestPyPI. Backend +validation of ``project.dependencies`` failed during +``get_requires_for_build_wheel``, before metadata could be generated. + +.. list-table:: pip behavior with an unsupported marker + :header-rows: 1 + :widths: 40 40 20 + + * - Installation case + - Outcome + - Older-release fallback + * - ``pip install .``; marker in ``project.dependencies`` + - Backend validation fails before dependency metadata is available + - Not applicable + * - ``pip install .``; marker in ``build-system.requires`` + - Frontend fails while reading ``pyproject.toml`` + - Not applicable + * - ``pip install marker-test``; marker in wheel ``Requires-Dist`` + - pip 24.1 and later reject the version as invalid metadata + - Yes + * - ``pip install marker-test``; marker in sdist ``project.dependencies`` + - Backend validation fails before dependency metadata is available + - No + * - ``pip install marker-test``; marker in sdist ``build-system.requires`` + - Frontend fails while preparing the candidate + - No + * - Release has a usable wheel and an sdist with an unsupported marker in + ``build-system.requires`` + - Wheel installs without inspecting the sdist's build requirements + - Not applicable + +The sdist cases fail earlier than wheel dependency processing. Build requirement +parsing occurs before invoking the backend, and backend metadata validation can +fail before the resolver receives dependency metadata. The wheel fallback +behavior therefore does not imply fallback for arbitrary build or backend +errors. Local source installs have no older index candidate to select in any +case. + +The remainder of this appendix considers only the third row, the case where a +wheel's dependency metadata contains an unsupported marker. This is the key case for fallback to an older +package version. The other cases are not expected to provide such fallback, +as discussed in the :ref:`Backwards Compatibility +` section of :pep:`780`. + +For the wheel case, pip 24.0 aborts with a requirement-parsing error +instead of trying version 1.0. The behavior changed in pip 24.1 through +`pypa/pip#12300 `__, which discards +candidates with invalid dependencies and excludes other candidates of the same +version. This is package-version rejection, rather than permission to choose +another artifact with inconsistent dependency metadata. + +Local dry-run resolution with pip 24.0, 24.1, and 26.2.2 reproduced the wheel +version boundary using the current ``sys_abi_info`` example. Both newer versions +selected 1.0, and both failed when the requirement pinned version 2.0. + +The pip 24.1 and 26.2.2 diagnostic begins with a warning +that version 2.0 has invalid metadata, followed by the parser's explanation. It also suggests using +``pip<24.1``. That diagnostic addresses invalid metadata generally; +it is not appropriate upgrade advice for a newly standardized marker. An +unsupported marker needs a consumer that understands it, or rejection of the +affected version, rather than removal of the condition. + +uv +-- + +A local test with stable uv 0.13.6, using ``uv pip compile --no-index`` with +``--find-links`` pointing at the two-wheel fixture, selected version 1.0. +Testing with uv 0.7.0 produced the same fallback to version 1.0. No preview +feature was enabled. + +PDM +--- + +PDM provides an independent implementation of candidate-level fallback. +`PDM 2.13.0 +`__ +has a resolver that catches requirement and specifier errors when obtaining +candidate dependencies and marks that candidate as conflicting. The same policy is present in +`PDM 2.29.5 +`__. +With wheels for both versions of ``marker-test`` available from a local index, +PDM 2.29.5 rejected version 2.0 as invalid metadata and locked version 1.0. + +Poetry +------ + +Poetry has long used permissive recovery when converting published +``Requires-Dist`` entries into dependencies. Both +`Poetry 1.8.2 +`__ +and `Poetry 2.5.1 +`__ +catch an invalid-marker exception, remove everything after the semicolon, and +parse the dependency again. This turns a conditional dependency into an +unconditional one. The exception name changed from ``InvalidMarker`` to +``InvalidMarkerError``, but the recovery policy remained. + +An unknown marker name need not reach that handler. In a local test passing the +fixture's dependency to the ``PackageInfo`` metadata conversion in Poetry +2.5.1, parsing instead raised an invalid-requirement error. Poetry logged a warning +and skipped the entire dependency, yielding a package with no dependencies. +This tested metadata conversion, not end-to-end resolution. + +Related issues document the history of this inspection path: + +* `Poetry #3629 `__ + reported malformed Kivy wheel dependencies in 2021. The reporter quoted the + marker-stripping code and questioned whether warning instead of raising could + have consequences. Closing the issue did not remove that recovery policy. +* `Poetry #7729 `__ + reported a parsing failure with malformed ``super-state-machine`` metadata, + where older Poetry versions had warned and skipped the dependency. It shows + that recovery versus failure has varied across versions and parsing errors. +* `Poetry #9154 `__ + concerns a Windows file URL in dependency metadata, with a traceback through + the same inspection code. It is a related cross-platform metadata problem, + rather than a report about unknown markers. + +None of these issues specifically addresses a future standardized marker that +an older consumer does not understand. In that case, the producer's metadata +can be valid even though the consumer rejects it. Stripping the condition can +add an unsuitable dependency; skipping the requirement can omit a needed one. +Neither preserves dependency semantics. The safe fallback is to reject the +containing package version and consider alternatives. From 5a9c47278cc7ae7da8ab16ef2a4f36bfcbae5cbe Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 20:55:57 +0000 Subject: [PATCH 14/36] Remove Open Issues section --- peps/pep-0780.rst | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 725258a9ff2..18c749ed905 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -450,22 +450,6 @@ Second, the introduction of a dynamic mechanism would require a more complex implementation in the packaging library, which would be a significant departure from the current approach. -Open Issues -=========== - -Other Environment Markers -------------------------- -If other environment markers are needed right now, this PEP could be extended -to include them. - -Other Tooling -------------- -The reference implementation is based on the ``packaging`` library and ``pip``. -We have confirmed that this allows for building and installing packages with -several build backends. It is possible that other tools should be added to the -reference implementation. - - Footnotes ========= From 5fcb9f26146f8a367b6893e3dbf49cbfde573da7 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 20:57:20 +0000 Subject: [PATCH 15/36] Add the uv prototype under Reference Implementation --- peps/pep-0780.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 18c749ed905..336617cc2a8 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -429,6 +429,15 @@ the reference implementation linked above. __ https://github.com/zklaus/pip/tree/env-marker-free-threading +uv prototype +------------ + +An independent prototype by Charlie Marsh is available in +`astral-sh/uv#21840 `__. It adds +preview support for ABI feature markers during dependency resolution and wheel +coverage checks. The prototype implements an earlier draft of this PEP, using +the marker name ``sys_abi_features`` and its earlier value format. + Rejected Ideas ============== From ad07d9ba3fb3e63fc2586a7fadb0ba16ced3f14a Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 21:05:00 +0000 Subject: [PATCH 16/36] Add metadata consistency as an additional motivation for the PEP --- peps/pep-0780.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 336617cc2a8..27cbbf9b94a 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -86,6 +86,22 @@ able to specify that SciPy is required *unless* the interpreter is a 32-bit one on Windows (c.f. `Require SciPy Unless on 32-bit win32`_), to avoid failed from-source installations due to the missing wheels. +Enabling consistent dependency metadata across a package release is another +motivation for this PEP. The :ref:`PEP 825 investigation of metadata consistency +` identified ``apache-beam``'s omission of +``pyarrow`` on 32-bit Windows as the only remaining real-world case in that +investigation where existing markers could not express the required dependency +conditions. The bitness information exposed by ``sys_abi_info`` closes that +gap, allowing the condition to be expressed in the same dependency metadata in +the sdist and every wheel of the release. + +Closing this gap also enables future requirements for consistent dependency +metadata across release artifacts. Resolvers can then use one artifact's +dependency metadata for the release, evaluating markers for each target +environment, rather than inspecting every wheel separately. Tools such as +`uv already expect this consistency +`__. + Rationale ========= From 252a9a780db8c6278f96e58c653bc849df0ea58f Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 21:11:15 +0000 Subject: [PATCH 17/36] Update section on free-threading for today's status --- peps/pep-0780.rst | 55 +++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 27cbbf9b94a..614e4b391fb 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -50,27 +50,26 @@ precisely in metadata is currently not possible, and increasing the minimum version of a dependency also for the GIL-enabled build is usually undesirable since it unnecessarily limits compatibility between packages. -Some concrete examples of such issues have been discussed in the `Environment -marker for free-threading`_ Discourse thread: - -- Cython has (experimental) support for free-threading only in its master - branch, and is used by a lot of projects that already publish ``cp313t`` - wheels. Picking up the wrong Cython version is causing a lot of obscure build - failures and runtime crashes. It would be beneficial if the metadata could - express that (c.f. `Require Cython Pre-release for Free-Threaded Python`_). -- CFFI has only recently gained support for free-threading, and for a - significant period of time, it looked likely that support would first be - added in a fork. There are a lot of projects that depend on ``cffi``, which - are likely fine to start depending on a fork for free-threading only, however - depending on a fork for >=3.13 or for all Python versions seemed like a much - larger ask, and more disruptive for distribution packagers. While the - situation has been resolved with CFFI 2.0.0, other projects may face similar - issues. - -While concrete examples may be addressed with compatible releases, the same -issue is going to repeat further up the stack. The free-threading rollout is -expected to take several years, and an environment marker for free-threading -will make that rollout significantly easier. +At the time of writing of the first version of this PEP, concrete examples of +such issues were discussed in the `Environment marker for free-threading`_ +Discourse thread: + +- Cython had experimental support for free-threading only in its master + branch, and was used by many projects already publishing ``cp313t`` + wheels. Picking up the wrong Cython version caused obscure build + failures and runtime crashes. It would have been beneficial if the metadata + could express that (c.f. `Require Cython Pre-release for Free-Threaded Python`_). +- CFFI did not yet support free-threading, and for a significant period of + time, it looked likely that support would first be added in a fork. Many + projects depend on ``cffi`` and could have depended on a fork for + free-threading only; however, depending on a fork for >=3.13 or for all + Python versions seemed like a much + larger ask, and more disruptive for distribution packagers. + +Cython 3.1.0 and CFFI 2.0.0 have since added free-threading support, but the same +principle remains relevant as other projects further up the stack add support. +The free-threading rollout is an ongoing multi-year effort, and an environment +marker for free-threading will make that rollout significantly easier. Another important ABI feature that is not yet covered by environment markers is the bitness of the interpreter. In most cases, the ``sys_platform`` or @@ -120,14 +119,14 @@ process over multiple releases. It is therefore important to make sure that the mechanisms in this PEP are useable for Python interpreters where either free-threading or non-free-threading could be the default or the only option. -At the time of writing, free-threaded Python is in Phase I: experimental phase. -In this phase, there is an acute need for the proposed environment markers to -help with the transition to free-threaded Python as package authors gradually -add support. +When the first version of this PEP was written, free-threaded Python was in +Phase I: experimental phase. The proposed environment markers were needed to +help with the transition as package authors gradually added support. -As the number of packages with support increases, and particularly during -Phase II: Supported-but-not-default phase, we still anticipate a strong need -for the environment markers to help with the transition. +Since Python 3.14, free-threaded Python is officially supported, entering +Phase II: Supported-but-not-default phase, as described in :pep:`779`. +As the number of packages with support increases, there remains a need for +environment markers to help with this ongoing transition. As free-threaded Python enters into Phase III: Default phase, the need for the environment markers will decrease, though at this point it is not clear that From 399071e69dbcbc05493d36a793783649a5ec5ce7 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 21:13:07 +0000 Subject: [PATCH 18/36] Update the content for PEP 751's acceptance, that's a while ago by now --- peps/pep-0780.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 614e4b391fb..5457aefa21c 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -144,11 +144,11 @@ simplicity for the foreseeable future in a changing Python ecosystem. Relation to Other PEPs ---------------------- -This PEP extends environment markers with set semantics for ABI features. -:pep:`751#additions-to-marker-expression-syntax` includes a similar extension -for lock file specific environment markers; although the two have been -developed independently, they are compatible where they overlap in terms of the -new set semantics. +:pep:`751#additions-to-marker-expression-syntax`, which standardized +``pylock.toml``, introduced set-valued environment markers for extras and +dependency groups in lock files. This PEP applies those set semantics to ABI +features through ``sys_abi_info``, making them available in dependency +specifications as well as lock files. Specification ============= From 622a430d47b82b347ff68e9bd99e6cd76c65e23a Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 21:16:41 +0000 Subject: [PATCH 19/36] Remove the RFC 2119 boilerplate --- peps/pep-0780.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 5457aefa21c..6b3c6ede7b7 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -153,11 +153,6 @@ specifications as well as lock files. Specification ============= -The keywords "**MUST**", "**MUST NOT**", "**REQUIRED**", "**SHALL**", -"**SHALL NOT**", "**SHOULD**", "**SHOULD NOT**", "**RECOMMENDED**", "**MAY**", -and "**OPTIONAL**"" in this document are to be interpreted as described in -:rfc:`RFC 2119 <2119>`. - ABI Features ------------ From d221156501e421483843a58c5c4599fdead44086 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 21:31:31 +0000 Subject: [PATCH 20/36] Improve the section "The Values of `sys_abi_info`" --- peps/pep-0780.rst | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 6b3c6ede7b7..6d59f3f17a2 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -232,38 +232,32 @@ Like the grammar, also the overview table of environment markers in - Sample values * - ``sys_abi_info`` - ``sys.abi_info`` - - ``{'free_threaded::True', 'pointer_bits::64'}``, - ``{'free_threaded::False', 'debug::True', 'pointer_bits::32'}``, + - ``{'free_threaded::True', 'debug::False', 'pointer_bits::64', 'byteorder::little'}``, + ``{'free_threaded::False', 'debug::True', 'pointer_bits::32', 'byteorder::little'}``, ``{'byteorder::little', 'pointer_bits::64'}`` With these additions, ABI features can be used in dependency specifications via -the ``in`` operator to test for the presence of a feature, or the ``not in`` -operator to test for the absence of a feature. +the ``in`` operator to test for the presence of a feature-value pair, or the +``not in`` operator to test for its absence. This allows for marker expressions such as:: "free_threaded::True" in sys_abi_info "pointer_bits::32" not in sys_abi_info and "debug::True" in sys_abi_info -Note that this is forward compatible in the sense that future additions to the -set of ABI features will not be in conflict with the grammar, such that tools -encountering unknown ABI features in a dependency specification will naturally -evaluate the test as false. This empowers package authors to decide on the -default resolution in this case. For example, a package author may decide to -require a dependency only if an ABI feature is present, by using a presence -test like ``"new_feature::True" in sys_abi_info``, which will evaluate to -false on current interpreters that do not support the new feature, or an -absence test like ``"new_feature::False" not in sys_abi_info``, which will -evaluate to true on current interpreters. - -While covering all ABI features specified at the moment, this mechanism is only -meaningfully applicable where the ABI feature is unambiguously representable as -a string. Currently, all ABI features are either booleans, integers, or -strings, which all satisfy this requirement. - -Should the future reveal a need for ABI features that are not unambiguously -represented as strings, like floating point numbers or more complex data -structures, this PEP would need to be revisited to address those. +Adding new ABI features does not require changes to the marker grammar, +because the feature names and values are encoded as strings. If the tested +string is absent from ``sys_abi_info``, ``in`` evaluates to false and ``not in`` +evaluates to true. Package authors can therefore choose the +default behavior for interpreters that do not provide a new feature. For +example, ``"new_feature::True" in sys_abi_info`` requires the feature to be +explicitly true, while ``"new_feature::False" not in sys_abi_info`` also +evaluates to true when the feature is absent. + +ABI feature values must be unambiguously representable as strings. Currently, +all ABI features are either booleans, integers, or strings, which all satisfy +this requirement. This is expected to remain the case; packaging tools are not +required to handle other data types. Handling Unsupported Marker Fields ---------------------------------- From 97b2f69deff0e4ff56e2ff75cd8dc17edd080073 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 21:39:20 +0000 Subject: [PATCH 21/36] Improve section "Handling Unsupported Marker Fields" --- peps/pep-0780.rst | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 6d59f3f17a2..b5a8dcf2ae2 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -262,28 +262,33 @@ required to handle other data types. Handling Unsupported Marker Fields ---------------------------------- -The Dependency Specifiers specification states that references to unknown marker -fields SHOULD render a package version ineligible for installation or inclusion -in a locked dependency tree. This PEP clarifies that rule as follows. +The :ref:`Dependency Specifiers ` specification +states that references to unknown marker fields SHOULD render a package version +ineligible for installation or inclusion in a locked dependency tree. This PEP +clarifies that rule as follows. Consumers do not need to successfully parse an unknown marker field to implement this behavior. When a locking or installation tool cannot interpret published dependency metadata because a marker field is unsupported, it SHOULD treat the containing package version as ineligible and SHOULD continue considering other -versions where possible. A consumer MAY conservatively reject a package version +versions where possible. Such tools MAY conservatively reject a package version when any of its published dependency specifications cannot be parsed, without distinguishing unsupported marker fields from malformed requirements. -Consumers MUST NOT recover by dropping an unsupported marker, discarding the -dependency that contains it, or assuming a truth value for its expression. Such -recovery can produce an apparently successful installation with incorrect -dependencies. If no eligible candidate -remains, consumers SHOULD report a descriptive failure explaining the unsupported -metadata and, where possible, suggesting an upgrade of the consuming tool. - -This clarification concerns interpreting published dependency metadata. It does -not require tools to recover from failures while preparing an sdist or generating -its metadata, as discussed in `Backwards Compatibility`_. +When determining dependencies for installation or inclusion in a locked +dependency tree, tools MUST NOT recover by dropping an unsupported marker, +discarding the dependency that contains it, or assuming a truth value for its +expression. Such recovery can produce an apparently successful installation +with incorrect dependencies. This does not prevent static analysis tools from +ignoring markers when collecting all potential dependencies. If no eligible +candidate remains, installation and locking tools SHOULD report a descriptive +failure explaining the unsupported metadata and, where possible, suggesting an +upgrade of the consuming tool. + +This clarification concerns interpreting distribution dependency metadata, +including metadata in wheels or successfully generated from an sdist. It does +not require tools to recover from failures while preparing an sdist or +generating its metadata, as discussed in `Backwards Compatibility`_. Examples From 1a2ceff4188a1f1dee0fbca4561566de8c0ead14 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 21:45:05 +0000 Subject: [PATCH 22/36] Put Examples under Specification, it shouldn't be a top-level section --- peps/pep-0780.rst | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index b5a8dcf2ae2..6659a0299e9 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -58,7 +58,7 @@ Discourse thread: branch, and was used by many projects already publishing ``cp313t`` wheels. Picking up the wrong Cython version caused obscure build failures and runtime crashes. It would have been beneficial if the metadata - could express that (c.f. `Require Cython Pre-release for Free-Threaded Python`_). + could express that (see `Examples`_). - CFFI did not yet support free-threading, and for a significant period of time, it looked likely that support would first be added in a fork. Many projects depend on ``cffi`` and could have depended on a fork for @@ -82,7 +82,7 @@ to due to the lack of a suitable 32-bit compiler toolchain with Fortran support). Those wheels lacking can be awkward especially for projects where SciPy is an optional dependency only. In that case, it would be useful to be able to specify that SciPy is required *unless* the interpreter is a 32-bit one -on Windows (c.f. `Require SciPy Unless on 32-bit win32`_), to avoid failed +on Windows (see `Examples`_), to avoid failed from-source installations due to the missing wheels. Enabling consistent dependency metadata across a package release is another @@ -292,32 +292,26 @@ generating its metadata, as discussed in `Backwards Compatibility`_. Examples -======== +-------- -Require Cython Pre-release for Free-Threaded Python ---------------------------------------------------- To require a pre-release of Cython only for a free-threaded Python interpreter, the following dependency specification can be used:: cython >3.1.0a1; "free_threaded::True" in sys_abi_info cython ==3.0.*; "free_threaded::False" in sys_abi_info -Require SciPy Unless on 32-bit ``win32`` ----------------------------------------- To require SciPy unless on a 32-bit interpreter on Windows, the following dependency specification can be used:: scipy; platform_system != "Windows" or "pointer_bits::32" not in sys_abi_info -Require NumPy for a Free-Threaded Interpreter With Debugging Capabilities -------------------------------------------------------------------------- To require NumPy only for a free-threaded interpreter with debugging capabilities, the following dependency can be used:: numpy; "free-threaded::True" in sys_abi_info and "debug::True" in sys_abi_info -Require Free-Threaded Fork of PyYAML ------------------------------------- +**Require Free-Threaded Fork of PyYAML** + PyYAML initially decided not to support free-threading in its mainline distribution before wider testing of free-threaded Python in the real world. To facilitate this testing, a free-threaded fork, PyYAML-ft, was created. From dd7f9bcbc620ea041ad7fabab7afed6cea34714e Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 22:11:23 +0000 Subject: [PATCH 23/36] Fix some minor textual issues --- peps/pep-0780.rst | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 6659a0299e9..704d3ccb3ce 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -308,7 +308,7 @@ dependency specification can be used:: To require NumPy only for a free-threaded interpreter with debugging capabilities, the following dependency can be used:: - numpy; "free-threaded::True" in sys_abi_info and "debug::True" in sys_abi_info + numpy; "free_threaded::True" in sys_abi_info and "debug::True" in sys_abi_info **Require Free-Threaded Fork of PyYAML** @@ -338,47 +338,49 @@ Backwards Compatibility Introducing a new environment marker can affect tools that do not understand it. Packaging interoperability generally follows the principle of strict -validation when producing or admitting new metadata, and forward-compatible -handling when consuming metadata that has already been published. +validation when producing or accepting new metadata and forward-compatible +handling when consuming previously published metadata. Build backends, publishing tools, and package indexes should understand and validate new metadata features before producing or accepting them. Consumers -can ignore new optional information when it is unnecessary for their operation. +can ignore new optional information when it is unnecessary for the operation +being performed. When new semantics are needed to determine dependencies or compatibility, consumers should instead consider the affected package version unsupported. This PEP introduces no additional index activation mechanism or waiting period. Marker field names are part of a closed grammar. Tools that predate -``sys_abi_info`` may therefore reject a dependency containing it as a parsing -error. No open-ended marker grammar is needed for safe consumption: the -resolver can treat that error as making the containing package version +``sys_abi_info`` may therefore report a parsing error when encountering a +dependency containing it. An open-ended marker grammar is not needed to handle +this safely: the resolver can treat the containing package version as ineligible and try other versions. This preserves correctness without requiring the consumer to understand the new marker. See `Handling Unsupported Marker Fields`_ for the specification clarification. -Already released tools cannot acquire this behavior retroactively. For wheel +Not all existing tools implement this fallback behavior. For wheel dependency metadata, pip 24.1 and later can skip a package version with an unsupported marker and select an older version; pip 24.0 instead aborts resolution. Other tools also differ in their handling of unsupported markers. -A pinned version or directly requested artifact may leave no eligible alternative -and result in an installation failure. +Pinning a version or requesting an artifact directly may leave no eligible +alternative, resulting in an installation failure. Source distributions have additional limitations. An unsupported marker in ``build-system.requires`` can cause the frontend to fail before running the backend. An unsupported marker in ``project.dependencies`` can cause the backend to fail during metadata generation. Validation may occur as early as the backend hook that determines additional build requirements. These errors may -abort installation rather than cause fallback to an older release, including -when installing from an -index. This PEP does not require changes to that behavior: failure is an -acceptable outcome for older tools encountering such source distributions. +abort installation rather than trigger fallback to an older release, including +when installing from an index. This PEP does not require changes to that +behavior: failure is an acceptable outcome for older tools encountering such +source distributions. Installing a usable wheel does not require inspecting the sdist's build requirements. The :ref:`tool behavior appendix ` records these distinctions in detail. Projects adopting ``sys_abi_info`` should account for these compatibility -boundaries and their users' installation and locking tools. Adoption timing is -left to projects; this PEP specifies no minimum ecosystem support threshold. +boundaries and the installation and locking tools their users rely on. Projects +decide when to adopt the marker; this PEP specifies no minimum ecosystem support +threshold. Once tools understand ``sys_abi_info``, additional values in its set can be handled through the membership semantics specified above. Unknown marker *fields* must not be confused with absent or unknown ABI feature *values*. @@ -386,9 +388,10 @@ handled through the membership semantics specified above. Unknown marker Audit and Update Tools ---------------------- -A wide range of tools inspect dependency data in ``requirements.txt`` and -``pyproject.toml`` files and offer assisted or automated updates, for example -Dependabot and Tidelift. Tools that interpret the meaning of ``sys_abi_info`` +A wide range of tools, including Dependabot and Tidelift, inspect dependency +data in ``pyproject.toml``, ``pylock.toml``, and ``requirements.txt`` files and +offer assisted or automated updates. Tools that interpret the meaning of +``sys_abi_info`` need explicit support for it. Tools consuming published distributions can remain correct by rejecting versions with unsupported dependency metadata, although this can limit which releases they consider. Static analysis and @@ -465,8 +468,8 @@ from the current approach. Footnotes ========= -.. [#python-free-threading] Python experimental support for free threading is - available in Python 3.13 and later. For more information, see `Python +.. [#python-free-threading] Free threading was experimental in Python 3.13 and + is officially supported since Python 3.14. For more information, see `Python experimental support for free threading`_. .. [#bitness] While there are some related environment markers available, such From da5cea5e66aa63fbfc4613630d456e845e062a0f Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 22:13:35 +0000 Subject: [PATCH 24/36] Some clarification to the spec for non-bool/int/string data types --- peps/pep-0780.rst | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 704d3ccb3ce..49d371400be 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -245,6 +245,12 @@ This allows for marker expressions such as:: "free_threaded::True" in sys_abi_info "pointer_bits::32" not in sys_abi_info and "debug::True" in sys_abi_info +Integer-valued features support exact-value tests, not numerical comparisons. +This is sufficient for the bitness use case: excluding 32-bit Windows requires +testing for ``"pointer_bits::32"``, without enumerating other possible pointer +widths. An unfamiliar value, such as ``128``, remains a distinct string; +absence of ``"pointer_bits::32"`` does not imply a 64-bit interpreter. + Adding new ABI features does not require changes to the marker grammar, because the feature names and values are encoded as strings. If the tested string is absent from ``sys_abi_info``, ``in`` evaluates to false and ``not in`` @@ -256,8 +262,9 @@ evaluates to true when the feature is absent. ABI feature values must be unambiguously representable as strings. Currently, all ABI features are either booleans, integers, or strings, which all satisfy -this requirement. This is expected to remain the case; packaging tools are not -required to handle other data types. +this requirement. This is expected to remain the case. When constructing +``sys_abi_info``, packaging tools MUST ignore fields whose values have other +data types. Handling Unsupported Marker Fields ---------------------------------- From e4f4ae80289242c4ea3edd2929c45bd3b3dd8bfd Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 22:15:29 +0000 Subject: [PATCH 25/36] Clarify that the `free_threaded` value is build-time (see post 2-5 of DPO thread) --- peps/pep-0780.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 49d371400be..fa0278be71c 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -176,8 +176,11 @@ the ABI features are the same as for Python 3.15 and given as follows: typically ``32`` or ``64`` [#bitness]_. ``free_threaded`` (only CPython) - If the Python interpreter is free-threaded, ``free_threaded`` MUST be - ``True``, otherwise it MUST be ``False``. + If the Python interpreter was built with free-threading support, + ``free_threaded`` MUST be ``True``, otherwise it MUST be ``False``. + This value reflects the build configuration, not whether the GIL is + currently enabled. It is unaffected by ``-X gil``, ``PYTHON_GIL``, or + changes to the GIL state at runtime. ``debug`` (only CPython) This ABI feature corresponds to the From 89ef9d25e68fc9c3e73891b0e5e9aa0a09ba10ef Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 22:46:20 +0000 Subject: [PATCH 26/36] Add specification for determining abi_info values for older Pythons --- peps/pep-0780.rst | 74 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index fa0278be71c..8b04080f2ad 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -158,38 +158,41 @@ ABI Features ABI features are intrinsic properties of the Python interpreter. However, not all features are equally applicable to all Python interpreters or -Python versions. For example, the distinction between free-threaded and -GIL-enabled interpreters is only relevant for CPython 3.13 onwards, but the -bitness of the interpreter, i.e. the number of bits in a pointer, is relevant -for all interpreters. +Python versions. For example, CPython introduced free-threading support in +Python 3.13. Other implementations do not currently support free-threading, +so ``free_threaded`` MUST be ``False`` for them. The bitness of the interpreter, +i.e. the number of bits in a pointer, is relevant for all interpreters. -All interpreters MUST handle the following ABI features as stated. ABI features -that are restricted to particular interpreters MUST NOT be provided by other -interpreters. +Tools MUST provide the following ABI features for all Python implementations. -In Python 3.15 and later, the ABI features are determined by the new -:external+py3.15:py:data:`sys.abi_info` attribute. In earlier Python versions, -the ABI features are the same as for Python 3.15 and given as follows: +The ABI features are determined from :external+py3.15:py:data:`sys.abi_info` +where available. Tools MUST also provide the following features on older +interpreters, as specified in `Determining ABI Features on Older Interpreters`_. ``pointer_bits`` The bitness of the interpreter, that is, the number of bits in a pointer, typically ``32`` or ``64`` [#bitness]_. -``free_threaded`` (only CPython) +``free_threaded`` If the Python interpreter was built with free-threading support, ``free_threaded`` MUST be ``True``, otherwise it MUST be ``False``. This value reflects the build configuration, not whether the GIL is currently enabled. It is unaffected by ``-X gil``, ``PYTHON_GIL``, or changes to the GIL state at runtime. -``debug`` (only CPython) - This ABI feature corresponds to the - :external+py3.15:py:attr:`sys.abi_info.debug` field. +``debug`` + Indicates whether the interpreter was built in debug mode, corresponding + to the :external+py3.15:py:attr:`sys.abi_info.debug` field. ``byteorder`` Indicates the byte order of the interpreter. The value MUST be either ``"little"`` or ``"big"``. +For implementations without the corresponding ``sys.abi_info`` fields, the +values of ``free_threaded`` and ``debug`` are determined by the rules in +`Determining ABI Features on Older Interpreters`_, including false defaults +for non-CPython implementations. + .. _pep-780-sys_abi_info: The ``sys_abi_info`` Environment Marker @@ -237,7 +240,7 @@ Like the grammar, also the overview table of environment markers in - ``sys.abi_info`` - ``{'free_threaded::True', 'debug::False', 'pointer_bits::64', 'byteorder::little'}``, ``{'free_threaded::False', 'debug::True', 'pointer_bits::32', 'byteorder::little'}``, - ``{'byteorder::little', 'pointer_bits::64'}`` + ``{'free_threaded::False', 'debug::False', 'pointer_bits::64', 'byteorder::little'}`` With these additions, ABI features can be used in dependency specifications via the ``in`` operator to test for the presence of a feature-value pair, or the @@ -269,6 +272,47 @@ this requirement. This is expected to remain the case. When constructing ``sys_abi_info``, packaging tools MUST ignore fields whose values have other data types. +Determining ABI Features on Older Interpreters +------------------------------------------------ + +The features defined by this PEP describe properties that were already +available before ``sys.abi_info`` was introduced in Python 3.15. Tools MUST +provide them even when that attribute, or an applicable field, is absent. +When a field is available in ``sys.abi_info``, tools MUST use its value. +Otherwise, the following rules define the values for the target interpreter; +implementations MAY use equivalent methods to obtain the same values. + +``pointer_bits`` + ``8 * struct.calcsize("P")``. + +``byteorder`` + ``sys.byteorder``. + +``free_threaded`` + On CPython, ``bool(sysconfig.get_config_var("Py_GIL_DISABLED"))``. An + undefined configuration variable is treated as false. This detects + build-time support, independently of the runtime GIL state. On other + implementations, the value MUST be ``False``. + +``debug`` + On CPython, ``bool(sysconfig.get_config_var("Py_DEBUG"))`` when the + configuration variable is defined. Otherwise, the value is true if + ``hasattr(sys, "gettotalrefcount")`` is true or ``"_d.pyd"`` is present in + ``importlib.machinery.EXTENSION_SUFFIXES``, and false otherwise. The latter + check covers Windows builds that do not expose ``Py_DEBUG``. On other + implementations, the value MUST be ``False``. + +The resulting values are encoded as ``"name::value"`` strings in the same way +as values obtained from ``sys.abi_info``; false boolean values are included, +not omitted. Tools do not need to add ``sys.abi_info`` to the interpreter. + +Future attributes exposed by ``sys.abi_info`` are included when their values +have a supported type. Inferring those attributes on interpreters where they +are absent requires additional rules in the Dependency Specifiers +specification. Unless such rules are defined, tools MUST omit the missing +attributes rather than infer a value. In particular, an absent boolean +attribute is distinct from one whose value is false. + Handling Unsupported Marker Fields ---------------------------------- From 4942de624d61cd7bb5d26fe1ad032aa559437a0f Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 22:57:42 +0000 Subject: [PATCH 27/36] Add a Core Metadata bump to 2.7 --- peps/pep-0780.rst | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 8b04080f2ad..516faf6238c 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -33,6 +33,9 @@ this, it defines a set of `ABI Features`_ and specifies how they are made available for `environment markers `_ via a new marker variable, ``sys_abi_info``. +Use of ``sys_abi_info`` in ``Requires-Dist`` metadata is introduced with Core +Metadata version 2.7. + Motivation ========== @@ -272,6 +275,31 @@ this requirement. This is expected to remain the case. When constructing ``sys_abi_info``, packaging tools MUST ignore fields whose values have other data types. +Core Metadata +------------- + +``Requires-Dist`` is a :ref:`Core Metadata ` field +whose value syntax is defined by the :ref:`Dependency Specifiers +` specification. Because this PEP changes what +is considered valid in that field, it updates Core Metadata to version 2.7, +following the precedent of :pep:`685`. + +Build tools serializing a ``Requires-Dist`` entry whose environment marker +references ``sys_abi_info`` MUST emit Core Metadata version 2.7 or later. +Build tools MAY continue to emit an earlier Core Metadata version when +``sys_abi_info`` is not used in ``Requires-Dist`` and no other metadata feature +requires a newer version. + +Publishing tools SHOULD report an error when a distribution uses +``sys_abi_info`` in ``Requires-Dist`` while declaring a Core Metadata version +earlier than 2.7. Index servers SHOULD reject newly uploaded distributions +with this inconsistency. + +This requirement applies only when the marker is serialized into Core +Metadata. Uses of ``sys_abi_info`` in other dependency-specifier contexts, +such as ``build-system.requires``, requirements files, or ``pylock.toml``, +do not by themselves require or imply a Core Metadata version. + Determining ABI Features on Older Interpreters ------------------------------------------------ @@ -401,7 +429,15 @@ can ignore new optional information when it is unnecessary for the operation being performed. When new semantics are needed to determine dependencies or compatibility, consumers should instead consider the affected package version unsupported. -This PEP introduces no additional index activation mechanism or waiting period. +Beyond the metadata version requirement, this PEP introduces no separate +index activation date or waiting period. + +Core Metadata version 2.7 provides an explicit producer and publisher boundary +for using ``sys_abi_info`` in ``Requires-Dist``. It does not by itself make +older consumers compatible with the new marker. Core Metadata permits +consumers to process newer minor versions, so an older consumer may continue +processing 2.7 metadata and encounter the unsupported marker. The fallback +behavior described below is therefore still needed. Marker field names are part of a closed grammar. Tools that predate ``sys_abi_info`` may therefore report a parsing error when encountering a From ab5c9899de863f53e69f529db3b574afd459930c Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 23:02:27 +0000 Subject: [PATCH 28/36] Cross-link to PEP 825, which also introduces new markers --- peps/pep-0780.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 516faf6238c..4042d61203f 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -153,6 +153,12 @@ dependency groups in lock files. This PEP applies those set semantics to ABI features through ``sys_abi_info``, making them available in dependency specifications as well as lock files. +:pep:`825` also introduces new :ref:`environment markers +` as part of its Wheel Variants design. +The considerations in `Backwards Compatibility`_ and the analysis in the +:ref:`tool behavior appendix ` apply +equally to those markers when encountered by tools that do not support them. + Specification ============= From c00a7f5ef7a2b6724d2ac343e187609113d075c0 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 30 Oct 2026 23:09:50 +0000 Subject: [PATCH 29/36] Add a Change History --- peps/pep-0780.rst | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 4042d61203f..3f82664aabe 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -590,6 +590,40 @@ Thanks to Filipe Laíns for the suggestion of the ``abi_features`` attribute and to Stephen Rosen for the Backwards Compatibility section of :pep:`735`, which served as a template for the corresponding section in this PEP. +Change History +============== + +- 30-Oct-2026 + + - Rewrote `Backwards Compatibility`_ and clarified how installation and + locking tools should reject package versions with unsupported markers + and consider alternatives. Prohibited recovery that changes dependency + semantics, while allowing static analysis to collect potential + dependencies. Documented the limitations of fallback for source builds. + - Added the :ref:`tool behavior appendix + `, documenting pip, uv, PDM, and + Poetry behavior when encountering unknown markers. + - Introduced Core Metadata version 2.7 for ``Requires-Dist`` entries using + ``sys_abi_info``, with producer, publishing tool, and index validation + rules. Other dependency-specifier contexts do not require this version. + - Specified how tools determine ABI features when ``sys.abi_info`` or its + fields are unavailable, including false defaults for ``free_threaded`` + and ``debug`` on non-CPython implementations. Defined how future missing + attributes are handled. + - Clarified that ``free_threaded`` describes the interpreter's build + configuration rather than its runtime GIL state. + - Clarified exact-value membership tests, behavior for absent values, and + support for boolean, integer, and string values. Required tools to ignore + fields with other value types. + - Added consistent dependency metadata across sdists and wheels as a + motivation, referencing the PEP 825 investigation of 32-bit Windows. + Related the compatibility guidance to PEP 825's new environment markers. + - Updated the free-threading rollout discussion and the relationship to + PEP 751, and added the independent uv prototype under Reference + Implementation. + - Removed the Open Issues section, all open issues were addressed. + + Appendices ========== From e6637a52e8eae0ff5996f4679f494d1a89e3f1fc Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Mon, 2 Nov 2026 18:49:40 +0000 Subject: [PATCH 30/36] Clarify the Poetry behavior, and link the now-filed issue --- peps/pep-0780.rst | 19 +++++++++++--- ...appendix-tool-behavior-unknown-markers.rst | 25 ++++++++++--------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 3f82664aabe..7db9caffd6d 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -453,10 +453,21 @@ ineligible and try other versions. This preserves correctness without requiring the consumer to understand the new marker. See `Handling Unsupported Marker Fields`_ for the specification clarification. -Not all existing tools implement this fallback behavior. For wheel -dependency metadata, pip 24.1 and later can skip a package version with an -unsupported marker and select an older version; pip 24.0 instead aborts -resolution. Other tools also differ in their handling of unsupported markers. +Not all existing tools implement this fallback behavior. For wheel dependency +metadata, pip 24.0 aborts resolution on an unsupported marker, while pip 24.1 +(Jun 2024) and later can skip the affected package version and select an older +version. Poetry versions preceding the release that resolves +`poetry#11191 `__ instead +drop the entire dependency containing an unknown marker and keep the package +version eligible. This can produce an apparently successful +installation with a missing dependency, leading to runtime failures. It is +therefore unsafe even when resolution succeeds. + +Publishing a release that uses ``sys_abi_info`` in dependency metadata therefore +drops compatibility with pip <24.1, and with Poetry (until Poetry implements a +fix). Projects adopting the marker should make this compatibility change clear +to their users. + Pinning a version or requesting an artifact directly may leave no eligible alternative, resulting in an installation failure. diff --git a/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst b/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst index ebe3b6302e2..a1b235a2d60 100644 --- a/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst +++ b/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst @@ -41,12 +41,12 @@ separate resolver tests from source inspection and metadata-conversion tests. select the older release - Yes * - PDM - - 2.29.5 (Oct 2026) rejects the package version; the recovery policy is also - present in 2.13.0 (Mar 2024) + - 2.13.0 (Mar 2024) and 2.29.5 (Oct 2026) reject candidates with invalid + dependency metadata - Yes * - Poetry - - 1.8.2 (Mar 2024) and 2.5.1 (Sep 2026) strip invalid markers; - 2.5.1 drops the unknown-marker dependency in the tested conversion path + - 1.8.2 (Mar 2024) and 2.5.1 (Sep 2026) drop the dependency containing + the unknown marker rather than reject the package version - No @@ -127,9 +127,8 @@ affected version, rather than removal of the condition. uv -- -A local test with stable uv 0.13.6, using ``uv pip compile --no-index`` with -``--find-links`` pointing at the two-wheel fixture, selected version 1.0. -Testing with uv 0.7.0 produced the same fallback to version 1.0. No preview +Local tests with uv 0.7.0 and 0.13.6, using ``uv pip compile --no-index`` with +``--find-links`` pointing at the two wheels, selected version 1.0. No preview feature was enabled. PDM @@ -159,11 +158,13 @@ parse the dependency again. This turns a conditional dependency into an unconditional one. The exception name changed from ``InvalidMarker`` to ``InvalidMarkerError``, but the recovery policy remained. -An unknown marker name need not reach that handler. In a local test passing the -fixture's dependency to the ``PackageInfo`` metadata conversion in Poetry -2.5.1, parsing instead raised an invalid-requirement error. Poetry logged a warning -and skipped the entire dependency, yielding a package with no dependencies. -This tested metadata conversion, not end-to-end resolution. +Unknown marker names follow a different recovery path. Both versions parse +``idna; "pointer_bits::64" in sys_abi_info`` as an invalid requirement, log a +warning, and skip the entire dependency. In local-index resolution tests, both +locked ``marker-test`` 2.0 without ``idna``, rather than rejecting version 2.0 +and selecting version 1.0. By contrast, a malformed condition using a known +marker, such as ``idna; python_version == "not a version"``, triggers the +marker-stripping recovery and leaves an unconditional dependency on ``idna``. Related issues document the history of this inspection path: From a662b8e2fd6258f068b5fe75feb6a1d4992573ae Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Thu, 5 Nov 2026 21:20:38 +0000 Subject: [PATCH 31/36] Address review comments --- peps/pep-0780.rst | 33 +++++++++---------- ...appendix-tool-behavior-unknown-markers.rst | 11 ++++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 7db9caffd6d..260cbdb0ae3 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -17,7 +17,8 @@ Post-History: If accepted, the contents of this PEP should be integrated into the canonical documentation in the Python Packaging User Guide and the following directive should be added here: - .. canonical-pypa-spec:: :ref:`packaging:dependency-specifiers` + .. canonical-pypa-spec:: :ref:`packaging:dependency-specifiers` and + :ref:`packaging:core-metadata` Abstract ======== @@ -61,7 +62,7 @@ Discourse thread: branch, and was used by many projects already publishing ``cp313t`` wheels. Picking up the wrong Cython version caused obscure build failures and runtime crashes. It would have been beneficial if the metadata - could express that (see `Examples`_). + could have expressed that (see `Examples`_). - CFFI did not yet support free-threading, and for a significant period of time, it looked likely that support would first be added in a fork. Many projects depend on ``cffi`` and could have depended on a fork for @@ -92,7 +93,7 @@ Enabling consistent dependency metadata across a package release is another motivation for this PEP. The :ref:`PEP 825 investigation of metadata consistency ` identified ``apache-beam``'s omission of ``pyarrow`` on 32-bit Windows as the only remaining real-world case in that -investigation where existing markers could not express the required dependency +survey where existing markers could not express the required dependency conditions. The bitness information exposed by ``sys_abi_info`` closes that gap, allowing the condition to be expressed in the same dependency metadata in the sdist and every wheel of the release. @@ -172,11 +173,9 @@ Python 3.13. Other implementations do not currently support free-threading, so ``free_threaded`` MUST be ``False`` for them. The bitness of the interpreter, i.e. the number of bits in a pointer, is relevant for all interpreters. -Tools MUST provide the following ABI features for all Python implementations. - -The ABI features are determined from :external+py3.15:py:data:`sys.abi_info` -where available. Tools MUST also provide the following features on older -interpreters, as specified in `Determining ABI Features on Older Interpreters`_. +Tools MUST provide the ABI features listed below for all Python implementations, +using :external+py3.15:py:data:`sys.abi_info` where available and the rules in +`Determining ABI Features on Older Interpreters`_ otherwise: ``pointer_bits`` The bitness of the interpreter, that is, the number of bits in a pointer, @@ -199,8 +198,8 @@ interpreters, as specified in `Determining ABI Features on Older Interpreters`_. For implementations without the corresponding ``sys.abi_info`` fields, the values of ``free_threaded`` and ``debug`` are determined by the rules in -`Determining ABI Features on Older Interpreters`_, including false defaults -for non-CPython implementations. +`Determining ABI Features on Older Interpreters`_, including the ``False`` +defaults for non-CPython implementations. .. _pep-780-sys_abi_info: @@ -275,7 +274,7 @@ example, ``"new_feature::True" in sys_abi_info`` requires the feature to be explicitly true, while ``"new_feature::False" not in sys_abi_info`` also evaluates to true when the feature is absent. -ABI feature values must be unambiguously representable as strings. Currently, +ABI feature values MUST be unambiguously representable as strings. Currently, all ABI features are either booleans, integers, or strings, which all satisfy this requirement. This is expected to remain the case. When constructing ``sys_abi_info``, packaging tools MUST ignore fields whose values have other @@ -432,18 +431,18 @@ handling when consuming previously published metadata. Build backends, publishing tools, and package indexes should understand and validate new metadata features before producing or accepting them. Consumers can ignore new optional information when it is unnecessary for the operation -being performed. -When new semantics are needed to determine dependencies or compatibility, -consumers should instead consider the affected package version unsupported. -Beyond the metadata version requirement, this PEP introduces no separate -index activation date or waiting period. +being performed. When new semantics are needed to determine dependencies or +compatibility, consumers should instead consider the affected package version +unsupported. Core Metadata version 2.7 provides an explicit producer and publisher boundary for using ``sys_abi_info`` in ``Requires-Dist``. It does not by itself make older consumers compatible with the new marker. Core Metadata permits consumers to process newer minor versions, so an older consumer may continue processing 2.7 metadata and encounter the unsupported marker. The fallback -behavior described below is therefore still needed. +behavior described below is therefore still needed. Beyond the metadata version +requirement, this PEP introduces no separate index activation date or waiting +period. Marker field names are part of a closed grammar. Tools that predate ``sys_abi_info`` may therefore report a parsing error when encountering a diff --git a/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst b/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst index a1b235a2d60..ec8b9bd2167 100644 --- a/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst +++ b/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst @@ -157,14 +157,15 @@ catch an invalid-marker exception, remove everything after the semicolon, and parse the dependency again. This turns a conditional dependency into an unconditional one. The exception name changed from ``InvalidMarker`` to ``InvalidMarkerError``, but the recovery policy remained. +Metadata-conversion tests with both versions confirmed that +``idna; python_version == "not a version"`` becomes unconditional ``idna``. Unknown marker names follow a different recovery path. Both versions parse ``idna; "pointer_bits::64" in sys_abi_info`` as an invalid requirement, log a -warning, and skip the entire dependency. In local-index resolution tests, both -locked ``marker-test`` 2.0 without ``idna``, rather than rejecting version 2.0 -and selecting version 1.0. By contrast, a malformed condition using a known -marker, such as ``idna; python_version == "not a version"``, triggers the -marker-stripping recovery and leaves an unconditional dependency on ``idna``. +warning, and skip the entire dependency. Full ``poetry lock`` runs against a +local index confirmed this behavior in both versions: they locked +``marker-test`` 2.0 without ``idna``, rather than rejecting version 2.0 and +selecting version 1.0. Related issues document the history of this inspection path: From 441bd482fdeccc0542d1fa034d86b3721ffed283 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Thu, 5 Nov 2026 21:34:03 +0000 Subject: [PATCH 32/36] Update appendix after running Pip tests with patched setuptools Setuptools should not reject `sys_abi_info`, as Michal pointed out. That makes the results obtained for Pip more realistic. --- ...appendix-tool-behavior-unknown-markers.rst | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst b/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst index ec8b9bd2167..52380fee0d0 100644 --- a/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst +++ b/peps/pep-0780/appendix-tool-behavior-unknown-markers.rst @@ -60,11 +60,13 @@ pip The table below shows how pip handles an unsupported marker in runtime or build dependencies when installing a local project, a wheel, or a source -distribution. Local tests with -pip 26.2.2 (Oct 2026) used ``--find-links`` candidates, isolated setuptools builds, and -dry-run installation; packages were not uploaded to TestPyPI. Backend -validation of ``project.dependencies`` failed during -``get_requires_for_build_wheel``, before metadata could be generated. +distribution. Local tests with pip 26.2.2 (Oct 2026) used ``--find-links`` +candidates, isolated setuptools builds, and dry-run installation; packages were +not uploaded to TestPyPI. The original setuptools backend did not recognize +``sys_abi_info`` and rejected ``project.dependencies`` during +``get_requires_for_build_wheel``. The source-project tests were repeated with +marker recognition patched into setuptools' build dependencies, allowing the +requirement to be preserved in generated metadata. Pip itself was unchanged. .. list-table:: pip behavior with an unsupported marker :header-rows: 1 @@ -74,7 +76,8 @@ validation of ``project.dependencies`` failed during - Outcome - Older-release fallback * - ``pip install .``; marker in ``project.dependencies`` - - Backend validation fails before dependency metadata is available + - Unmodified backend fails validation; patched backend generates metadata + that pip rejects - Not applicable * - ``pip install .``; marker in ``build-system.requires`` - Frontend fails while reading ``pyproject.toml`` @@ -83,8 +86,9 @@ validation of ``project.dependencies`` failed during - pip 24.1 and later reject the version as invalid metadata - Yes * - ``pip install marker-test``; marker in sdist ``project.dependencies`` - - Backend validation fails before dependency metadata is available - - No + - Unmodified backend fails validation; patched backend generates metadata + that pip rejects + - Yes with the patched backend; no with the unmodified backend * - ``pip install marker-test``; marker in sdist ``build-system.requires`` - Frontend fails while preparing the candidate - No @@ -93,17 +97,20 @@ validation of ``project.dependencies`` failed during - Wheel installs without inspecting the sdist's build requirements - Not applicable -The sdist cases fail earlier than wheel dependency processing. Build requirement -parsing occurs before invoking the backend, and backend metadata validation can -fail before the resolver receives dependency metadata. The wheel fallback -behavior therefore does not imply fallback for arbitrary build or backend -errors. Local source installs have no older index candidate to select in any -case. +Source builds can fail before the resolver receives dependency metadata: +build requirement parsing occurs before invoking the backend, and backend +validation can fail before metadata is generated. When the patched backend +successfully generated metadata, pip rejected the indexed sdist for version +2.0 and selected the version 1.0 wheel. Pinning version 2.0 instead failed. +Local source installs have no older index candidate to select. Metadata-level +fallback therefore applies to sdists too, but does not imply fallback for +arbitrary build or backend errors. The remainder of this appendix considers only the third row, the case where a -wheel's dependency metadata contains an unsupported marker. This is the key case for fallback to an older -package version. The other cases are not expected to provide such fallback, -as discussed in the :ref:`Backwards Compatibility +wheel's dependency metadata contains an unsupported marker. This is the key +case for fallback to an older package version, as it has by far the largest +impact on backwards compatibility. The other cases have the limitations +discussed in the :ref:`Backwards Compatibility ` section of :pep:`780`. For the wheel case, pip 24.0 aborts with a requirement-parsing error From 49c8637b86b8b7e0d7373beb48c727334455b49d Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Thu, 5 Nov 2026 21:38:24 +0000 Subject: [PATCH 33/36] Update metadata: change history date, remove Python 3.15 line This is required to work for all Python versions, and the PEP no longer proposes any change to Python itself. --- peps/pep-0780.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 260cbdb0ae3..5f0e25d3931 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -8,7 +8,6 @@ Status: Draft Type: Standards Track Topic: Packaging Created: 21-Mar-2025 -Python-Version: 3.15 Post-History: `05-Aug-2024 `__, `26-Mar-2025 `__, @@ -603,7 +602,7 @@ served as a template for the corresponding section in this PEP. Change History ============== -- 30-Oct-2026 +- 05-Nov-2026 - Rewrote `Backwards Compatibility`_ and clarified how installation and locking tools should reject package versions with unsupported markers From 8d55bea2a0697ca62243fd2d8f85d170b6cbfbd3 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 6 Nov 2026 13:37:20 +0200 Subject: [PATCH 34/36] Apply suggestions from code review to fix py3.15 refs Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- peps/pep-0780.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 5f0e25d3931..ae4cdaf3ad8 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -173,7 +173,7 @@ so ``free_threaded`` MUST be ``False`` for them. The bitness of the interpreter, i.e. the number of bits in a pointer, is relevant for all interpreters. Tools MUST provide the ABI features listed below for all Python implementations, -using :external+py3.15:py:data:`sys.abi_info` where available and the rules in +using :data:`sys.abi_info` where available and the rules in `Determining ABI Features on Older Interpreters`_ otherwise: ``pointer_bits`` @@ -189,7 +189,7 @@ using :external+py3.15:py:data:`sys.abi_info` where available and the rules in ``debug`` Indicates whether the interpreter was built in debug mode, corresponding - to the :external+py3.15:py:attr:`sys.abi_info.debug` field. + to the :attr:`sys.abi_info.debug` field. ``byteorder`` Indicates the byte order of the interpreter. The value MUST be either From df7a6b012bd3d90ed8e6e8684f0448c62e767e0a Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 6 Nov 2026 11:42:29 +0000 Subject: [PATCH 35/36] Make first occurrence of `sys.abi_info` per section a link --- peps/pep-0780.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index ae4cdaf3ad8..5483d72d701 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -207,7 +207,7 @@ The ``sys_abi_info`` Environment Marker To make ABI features available in dependency specifications, a new environment marker variable, ``sys_abi_info``, is added to the format of dependency -specifiers. It is built to reflect the value of ``sys.abi_info``, which is a +specifiers. It is built to reflect the value of :data:`sys.abi_info`, which is a new attribute of the ``sys`` module introduced in Python 3.15 as a simple namespace. To represent its fields in the environment marker variable, they are expressed as a frozen set of strings of the form ``f"{name}::{value}"``, where @@ -244,7 +244,7 @@ Like the grammar, also the overview table of environment markers in - Python equivalent - Sample values * - ``sys_abi_info`` - - ``sys.abi_info`` + - :data:`sys.abi_info` - ``{'free_threaded::True', 'debug::False', 'pointer_bits::64', 'byteorder::little'}``, ``{'free_threaded::False', 'debug::True', 'pointer_bits::32', 'byteorder::little'}``, ``{'free_threaded::False', 'debug::False', 'pointer_bits::64', 'byteorder::little'}`` @@ -308,7 +308,7 @@ Determining ABI Features on Older Interpreters ------------------------------------------------ The features defined by this PEP describe properties that were already -available before ``sys.abi_info`` was introduced in Python 3.15. Tools MUST +available before :data:`sys.abi_info` was introduced in Python 3.15. Tools MUST provide them even when that attribute, or an applicable field, is absent. When a field is available in ``sys.abi_info``, tools MUST use its value. Otherwise, the following rules define the values for the target interpreter; From 751374a6e59d3c52ed3acb399583c0b9015265ea Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Fri, 6 Nov 2026 12:18:52 +0000 Subject: [PATCH 36/36] Update Post-History --- peps/pep-0780.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/peps/pep-0780.rst b/peps/pep-0780.rst index 5483d72d701..59467c757a8 100644 --- a/peps/pep-0780.rst +++ b/peps/pep-0780.rst @@ -11,6 +11,7 @@ Created: 21-Mar-2025 Post-History: `05-Aug-2024 `__, `26-Mar-2025 `__, + `06-Nov-2026 `__, .. If accepted, the contents of this PEP should be integrated into the