From aed069454738f638cf9fa8b39010549aba05262f Mon Sep 17 00:00:00 2001 From: Herrtian <70463940+Herrtian@users.noreply.github.com> Date: Fri, 8 May 2026 10:24:03 +0200 Subject: [PATCH 01/25] Document separate build and publish jobs --- ...bution-releases-using-github-actions-ci-cd-workflows.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows.rst b/source/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows.rst index 3b5e6ed28..035a8af8a 100644 --- a/source/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows.rst +++ b/source/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows.rst @@ -104,6 +104,12 @@ We will have to define two jobs to publish to PyPI and TestPyPI respectively, and an additional job to build the distribution packages. +.. important:: + + Keep the build job separate from the publishing jobs. Building + distributions in a publishing job is unsupported; publishing jobs should + only download the already-built artifacts and upload them. + First, we'll define the job for building the dist packages of your project and storing them for later use: From 95fd4ab22a0a00a9f4f105aab76ec6071d74729c Mon Sep 17 00:00:00 2001 From: Zander Milroy Date: Mon, 1 Jun 2026 12:18:30 -0400 Subject: [PATCH 02/25] Removes reference to withdrawn PEP 459 Removes recommendation for local version identifier metadata. Resolves #1503 --- source/specifications/version-specifiers.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/specifications/version-specifiers.rst b/source/specifications/version-specifiers.rst index e05422ce2..75093c2e2 100644 --- a/source/specifications/version-specifiers.rst +++ b/source/specifications/version-specifiers.rst @@ -172,9 +172,6 @@ identified by the public version identifier, but contains additional changes indexing and hosting upstream projects, it MUST NOT allow the use of local version identifiers. -Source distributions using a local version identifier SHOULD provide the -``python.integrator`` extension metadata (as defined in :pep:`459`). - Final releases -------------- From e9ceddf1f4c1f2cfc0a1cadf4fdbe388bf98906f Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 16 Jun 2026 06:21:46 -0400 Subject: [PATCH 03/25] Add a Sphinx label for the `.dist-info/sboms/` sections --- source/specifications/binary-distribution-format.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/specifications/binary-distribution-format.rst b/source/specifications/binary-distribution-format.rst index e9cbcb53d..a6f141851 100644 --- a/source/specifications/binary-distribution-format.rst +++ b/source/specifications/binary-distribution-format.rst @@ -276,6 +276,8 @@ fields is specified, the :file:`.dist-info/` directory MUST contain a ``License-File`` fields in the :file:`METADATA` file at their respective paths relative to the :file:`licenses/` directory. +.. _dist-info-sbom-directory: + The :file:`.dist-info/sboms/` directory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From e0afd28b79a427c0cfdd224f9cbcd6a48bb3a09e Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Thu, 2 Jul 2026 14:46:09 -0400 Subject: [PATCH 04/25] docs: fix link to activestate python As far as I can tell, this is roughly the equivalent link now. Signed-off-by: Henry Schreiner --- source/overview.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/overview.rst b/source/overview.rst index 70ef2d058..d7b3efdaf 100644 --- a/source/overview.rst +++ b/source/overview.rst @@ -279,7 +279,7 @@ A similar model involves installing an alternative Python distribution, but does not support arbitrary operating system-level packages: -* `ActiveState ActivePython `_ +* `ActiveState ActivePython `_ * `WinPython `_ .. _bringing-your-own-python: From ab07e44e92d471f4b8156946d5e091eedeabb5b5 Mon Sep 17 00:00:00 2001 From: Hugo Date: Fri, 10 Jul 2026 10:21:48 +0100 Subject: [PATCH 05/25] Document self-referential extras now that pip officially supports it Relevant PR: https://github.com/pypa/pip/pull/14157 Relevant Issue: https://github.com/pypa/pip/issues/11296 --- source/guides/writing-pyproject-toml.rst | 17 +++++++++++++++++ source/specifications/pyproject-toml.rst | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/source/guides/writing-pyproject-toml.rst b/source/guides/writing-pyproject-toml.rst index 92a7f25bf..6ce28553e 100644 --- a/source/guides/writing-pyproject-toml.rst +++ b/source/guides/writing-pyproject-toml.rst @@ -175,6 +175,22 @@ Each of the keys defines a "packaging extra". In the example above, one could use, e.g., ``pip install your-project-name[gui]`` to install your project with GUI support, adding the PyQt5 dependency. +.. _self-referential-extras: + +You can also define an extra that refers back to the same project with +other extras. This is useful for convenience extras that combine several +optional features without duplicating their dependency lists: + +.. code-block:: toml + + all = ["your-project-name[gui, cli]"] + +Installing ``your-project-name[all]`` then installs both the ``gui`` and +``cli`` dependencies. You can also list extras separately, for example +``["your-project-name[gui]", "your-project-name[cli]"]``. The name in the +requirement must match the project's ``name`` field. Installers such as +:ref:`pip` and :ref:`uv` support this pattern already (pip since v21.2). + .. _requires-python: .. _python_requires: @@ -555,6 +571,7 @@ A full example "rich", "click", ] + all = ["spam-eggs[gui, cli]"] [project.urls] Homepage = "https://example.com" diff --git a/source/specifications/pyproject-toml.rst b/source/specifications/pyproject-toml.rst index b4625bbb2..4b5a4a780 100644 --- a/source/specifications/pyproject-toml.rst +++ b/source/specifications/pyproject-toml.rst @@ -498,6 +498,13 @@ marker clause on the related ``Requires-Dist`` entries to check the extra name. Optional dependencies are thus only considered for installation if installation if the associated extra name is requested. +A dependency specifier in an extra MAY name the project itself with other extras +(for example, ``all = ["spam[gui, cli]"]``). That way a combined extra does not +need its own manually maintained copy of each referenced extra's dependencies, +which can otherwise fall out of sync. Installers that support self-referential +extras will be able to install the union of these extras' dependencies. See +:ref:`self-referential extras ` for examples. + .. _pyproject-toml-import-names: From d72cd8b978e469b562fc3390c25f9641c9688b00 Mon Sep 17 00:00:00 2001 From: Hugo Date: Fri, 10 Jul 2026 10:36:58 +0100 Subject: [PATCH 06/25] Update to include pip docs link --- source/guides/writing-pyproject-toml.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/guides/writing-pyproject-toml.rst b/source/guides/writing-pyproject-toml.rst index 6ce28553e..90fb7591c 100644 --- a/source/guides/writing-pyproject-toml.rst +++ b/source/guides/writing-pyproject-toml.rst @@ -189,7 +189,8 @@ Installing ``your-project-name[all]`` then installs both the ``gui`` and ``cli`` dependencies. You can also list extras separately, for example ``["your-project-name[gui]", "your-project-name[cli]"]``. The name in the requirement must match the project's ``name`` field. Installers such as -:ref:`pip` and :ref:`uv` support this pattern already (pip since v21.2). +:ref:`pip` and :ref:`uv` support this pattern already (pip since +`version 21.2 `_). .. _requires-python: From 68c3a77baafa24e65ce1bde8ea657001ccb03090 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 09:37:18 +0000 Subject: [PATCH 07/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/guides/writing-pyproject-toml.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/guides/writing-pyproject-toml.rst b/source/guides/writing-pyproject-toml.rst index 90fb7591c..fa2760bab 100644 --- a/source/guides/writing-pyproject-toml.rst +++ b/source/guides/writing-pyproject-toml.rst @@ -189,7 +189,7 @@ Installing ``your-project-name[all]`` then installs both the ``gui`` and ``cli`` dependencies. You can also list extras separately, for example ``["your-project-name[gui]", "your-project-name[cli]"]``. The name in the requirement must match the project's ``name`` field. Installers such as -:ref:`pip` and :ref:`uv` support this pattern already (pip since +:ref:`pip` and :ref:`uv` support this pattern already (pip since `version 21.2 `_). From d45adcf5f81677fde743cffc2ee0c0d9f54c0221 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sat, 11 Jul 2026 19:52:13 +0100 Subject: [PATCH 08/25] Rework the writing --- source/guides/writing-pyproject-toml.rst | 26 ++++++++++++++++-------- source/specifications/pyproject-toml.rst | 11 ++++------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/source/guides/writing-pyproject-toml.rst b/source/guides/writing-pyproject-toml.rst index fa2760bab..665c1277b 100644 --- a/source/guides/writing-pyproject-toml.rst +++ b/source/guides/writing-pyproject-toml.rst @@ -177,20 +177,28 @@ project with GUI support, adding the PyQt5 dependency. .. _self-referential-extras: -You can also define an extra that refers back to the same project with +You can also define an extra that refers back to the current project with other extras. This is useful for convenience extras that combine several -optional features without duplicating their dependency lists: +optional features (such as an ``all`` extra hosting dependencies from both +``gui`` and ``cli``): .. code-block:: toml - all = ["your-project-name[gui, cli]"] + all = ["your-project-name[gui, cli]"] -Installing ``your-project-name[all]`` then installs both the ``gui`` and -``cli`` dependencies. You can also list extras separately, for example -``["your-project-name[gui]", "your-project-name[cli]"]``. The name in the -requirement must match the project's ``name`` field. Installers such as -:ref:`pip` and :ref:`uv` support this pattern already (pip since -`version 21.2 `_). +The combined extra does not need its own manually maintained copy of each +referenced extra's dependencies, which can otherwise fall out of sync after +a few years of maintenance and bug fixes: + +.. code-block:: toml + + gui = ["PyQt5"] + cli = [ + "rich>=14.2", # version range is added after last "all" extra update + "textual", # dependency newly added since last "all" extra update + "click", + ] + all = ["PyQt5", "rich", "click"] .. _requires-python: diff --git a/source/specifications/pyproject-toml.rst b/source/specifications/pyproject-toml.rst index 4b5a4a780..7bc6ffbe1 100644 --- a/source/specifications/pyproject-toml.rst +++ b/source/specifications/pyproject-toml.rst @@ -498,13 +498,10 @@ marker clause on the related ``Requires-Dist`` entries to check the extra name. Optional dependencies are thus only considered for installation if installation if the associated extra name is requested. -A dependency specifier in an extra MAY name the project itself with other extras -(for example, ``all = ["spam[gui, cli]"]``). That way a combined extra does not -need its own manually maintained copy of each referenced extra's dependencies, -which can otherwise fall out of sync. Installers that support self-referential -extras will be able to install the union of these extras' dependencies. See -:ref:`self-referential extras ` for examples. - +Dependency specifiers in an extra may self-reference other extras from the +current project (e.g. ``all = ["your-project-name[gui, cli]"]``). See +:ref:`self-referential extras ` for an example. +Several installers including :ref:`pip` and :ref:`uv` support this pattern. .. _pyproject-toml-import-names: From 053f40e9b42ee5d0b0bd4d146b9866ba5a372173 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Sun, 12 Jul 2026 12:14:44 +0100 Subject: [PATCH 09/25] Clarify handling of script metadata --- source/specifications/inline-script-metadata.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/specifications/inline-script-metadata.rst b/source/specifications/inline-script-metadata.rst index 6fa832a3e..0f0285307 100644 --- a/source/specifications/inline-script-metadata.rst +++ b/source/specifications/inline-script-metadata.rst @@ -70,6 +70,17 @@ and the regular expression, the text specification takes precedence. Tools MUST NOT read from metadata blocks with types that have not been standardized by this specification. +Note that the specification only requires that *top-level* comment blocks are +recognised as containing metadata. However, parsing Python code is non-trivial, +and therefore: + +* Tools MAY choose to do a simple textual scan, rather than a full Python parse. + For example, the canonical regular expression provided above does a textual + scan. +* As a result of the previous point, the behaviour of scripts that contain data + that looks like metadata within another Python construct such as a multi-line + string is tool-dependent and should not be relied on. + script type ----------- From 9dd85f27266c88c4eca58828c918c337b665d331 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 13 Jul 2026 16:49:48 +0100 Subject: [PATCH 10/25] Reorganise bullet points --- source/specifications/inline-script-metadata.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/specifications/inline-script-metadata.rst b/source/specifications/inline-script-metadata.rst index 0f0285307..f9df2f0f5 100644 --- a/source/specifications/inline-script-metadata.rst +++ b/source/specifications/inline-script-metadata.rst @@ -75,11 +75,11 @@ recognised as containing metadata. However, parsing Python code is non-trivial, and therefore: * Tools MAY choose to do a simple textual scan, rather than a full Python parse. - For example, the canonical regular expression provided above does a textual - scan. * As a result of the previous point, the behaviour of scripts that contain data that looks like metadata within another Python construct such as a multi-line string is tool-dependent and should not be relied on. +* The canonical regular expression provided above is an example of an + implementation that does a simple textual scan. script type ----------- From 71fd79232efb88eeb5795914f422b464795e08f1 Mon Sep 17 00:00:00 2001 From: LaRoyBot <104553600+LaRoyBot@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:21:42 +0530 Subject: [PATCH 11/25] docs: fix typo e. g. to e.g. in dropping older python versions guide --- source/guides/dropping-older-python-versions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/guides/dropping-older-python-versions.rst b/source/guides/dropping-older-python-versions.rst index 267d7b923..223b65cd0 100644 --- a/source/guides/dropping-older-python-versions.rst +++ b/source/guides/dropping-older-python-versions.rst @@ -89,7 +89,7 @@ such as at least Python 3.9. Or, at least Python 3.7 and beyond, skipping the 3. If using the :ref:`setuptools` build backend, consult the `dependency-management`_ documentation for more options. .. caution:: - Avoid adding upper bounds to the version ranges, e. g. ``">= 3.8, < 3.10"``. Doing so can cause different errors + Avoid adding upper bounds to the version ranges, e.g. ``">= 3.8, < 3.10"``. Doing so can cause different errors and version conflicts. See the `discourse-discussion`_ for more information. 3. Validating the Metadata before publishing From cc74d9756b4a402d3458978eddfe084e8ac18926 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Wed, 22 Jul 2026 16:47:23 -0400 Subject: [PATCH 12/25] ignore clickpy.clickhouse.com -- cloudflare challenge --- source/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/conf.py b/source/conf.py index 22b0e5e36..4516880ec 100644 --- a/source/conf.py +++ b/source/conf.py @@ -148,6 +148,8 @@ # Ignore while StackOverflow is blocking GitHub CI. Ref: # https://github.com/pypa/packaging.python.org/pull/1474 r"https://stackoverflow\.com/.*", + # Cloudflare challenge blocks automated link checking. + r"https://clickpy\.clickhouse\.com/$", r"https://pyscaffold\.org/.*", r"https://anaconda\.org", r"https://www\.cisa\.gov/sbom", From 85f5b43f5c94b6deedc61d494c6b8b0c3aad7094 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 29 Jun 2026 16:00:17 -0400 Subject: [PATCH 13/25] chore: use non-legacy hook name for ruff-check Signed-off-by: Henry Schreiner --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 47b864808..6d8d4e78b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,5 +39,5 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.14.10 hooks: - - id: ruff + - id: ruff-check - id: ruff-format From 428e3129132721c0fa88e97af918e88ab416dcc7 Mon Sep 17 00:00:00 2001 From: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> Date: Mon, 27 Jul 2026 07:17:21 +0000 Subject: [PATCH 14/25] Update uv_build version to 0.11.32 --- source/shared/build-backend-tabs.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/shared/build-backend-tabs.rst b/source/shared/build-backend-tabs.rst index 6ff17eed2..27fda9666 100644 --- a/source/shared/build-backend-tabs.rst +++ b/source/shared/build-backend-tabs.rst @@ -38,5 +38,5 @@ .. code-block:: toml [build-system] - requires = ["uv_build >= 0.11.23, <0.12.0"] + requires = ["uv_build >= 0.11.32, <0.12.0"] build-backend = "uv_build" From bf702d2d3d88fa88a6f48db0049f99b9c170c5a3 Mon Sep 17 00:00:00 2001 From: woodruffw <3059210+woodruffw@users.noreply.github.com> Date: Wed, 29 Jul 2026 19:57:19 +0000 Subject: [PATCH 15/25] Update uv_build version to 0.12.0 --- source/shared/build-backend-tabs.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/shared/build-backend-tabs.rst b/source/shared/build-backend-tabs.rst index 27fda9666..70029a72c 100644 --- a/source/shared/build-backend-tabs.rst +++ b/source/shared/build-backend-tabs.rst @@ -38,5 +38,5 @@ .. code-block:: toml [build-system] - requires = ["uv_build >= 0.11.32, <0.12.0"] + requires = ["uv_build >= 0.12.0, <0.13.0"] build-backend = "uv_build" From 460400dc5899e6b3b9f7604e567f942af077495b Mon Sep 17 00:00:00 2001 From: Jonathan Dung Date: Fri, 31 Jul 2026 18:56:03 +0800 Subject: [PATCH 16/25] Fix dependency group resolution snippet --- source/specifications/dependency-groups.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/specifications/dependency-groups.rst b/source/specifications/dependency-groups.rst index 2fa82cd90..a8f5b8bca 100644 --- a/source/specifications/dependency-groups.rst +++ b/source/specifications/dependency-groups.rst @@ -209,8 +209,8 @@ The output is therefore valid ``requirements.txt`` data. realized_group = [] for item in raw_group: if isinstance(item, str): - # packaging.requirements.Requirement parsing ensures that this - # is a valid dependency specifier + # packaging.requirements.Requirement parsing ensures that this is a valid + # PEP 508 Dependency Specifier # raises InvalidRequirement on failure Requirement(item) realized_group.append(item) @@ -232,7 +232,7 @@ The output is therefore valid ``requirements.txt`` data. def resolve(dependency_groups: dict, group: str) -> list[str]: if not isinstance(dependency_groups, dict): - raise TypeError("Dependency Groups table is not a dict") + raise TypeError("Dependency groups table is not a dict") if not isinstance(group, str): raise TypeError("Dependency group name is not a str") return _resolve_dependency_group(dependency_groups, group) @@ -244,7 +244,7 @@ The output is therefore valid ``requirements.txt`` data. dependency_groups_raw = pyproject["dependency-groups"] dependency_groups = _normalize_group_names(dependency_groups_raw) - print("\n".join(resolve(pyproject["dependency-groups"], sys.argv[1]))) + print("\n".join(resolve(dependency_groups, sys.argv[1]))) History ======= From f5a23789b496ff2ff49ba1ecebb3aa792ddafe2c Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 29 Jun 2026 15:59:07 -0400 Subject: [PATCH 17/25] feat: add METADATA 2.6 (PEP 808) This selects the 'append only' choice from the acceptence of PEP 808. I started this by hand, then tried Claude Opus 4.8, feeding PEP 808 into the context, and it did a better job of finding places that needed updating than I did, so I ended up using that as the base, editing it to the current form. Assisted-by: ClaudeCode:claude-opus-4.8 Signed-off-by: Henry Schreiner --- source/specifications/core-metadata.rst | 22 +++++++++--- source/specifications/pyproject-toml.rst | 45 ++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/source/specifications/core-metadata.rst b/source/specifications/core-metadata.rst index 0cd05f9fa..b6fd009e2 100644 --- a/source/specifications/core-metadata.rst +++ b/source/specifications/core-metadata.rst @@ -6,7 +6,7 @@ Core metadata specifications ============================ -This page describes version 2.5, approved in September 2025. +This page describes version 2.6, approved in May 2026. Fields defined in the following specification should be considered valid, complete and not subject to change. The required fields are: @@ -50,7 +50,7 @@ Metadata-Version .. versionadded:: 1.0 Version of the file format; legal values are "1.0", "1.1", "1.2", "2.1", -"2.2", "2.3", "2.4", and "2.5". +"2.2", "2.3", "2.4", "2.5", and "2.6". Automated tools consuming metadata SHOULD warn if ``metadata-version`` is greater than the highest version they support, and MUST fail if @@ -109,6 +109,10 @@ Dynamic (multiple use) ====================== .. versionadded:: 2.2 +.. versionchanged:: 2.6 + A multiple use field that is present in the sdist and also marked + ``Dynamic`` may only be appended to in a wheel built from the sdist. + Previously any field listed in Dynamic was ignored in an sdist. A string containing the name of another core metadata field. The field names ``Name``, ``Version``, and ``Metadata-Version`` may not be specified @@ -121,8 +125,12 @@ rules apply: in any wheel built from the sdist MUST match the value in the sdist. If the field is not in the sdist, and not marked as ``Dynamic``, then it MUST NOT be present in the wheel. -2. If a field is marked as ``Dynamic``, it may contain any valid value in - a wheel built from the sdist (including not being present at all). +2. If a single-use field is marked as ``Dynamic``, it may contain any valid + value in a wheel built from the sdist (including not being present at all). +3. If a multiple use field is present in the sdist and also marked ``Dynamic``, + then a wheel built from the sdist MUST include the value(s) present in the + sdist. The wheel MAY add further values, but it MUST NOT remove, reorder, or + modify the values present in the sdist. If the sdist metadata version is older than version 2.2, then all fields should be treated as if they were specified with ``Dynamic`` (i.e. there are no special @@ -1074,6 +1082,12 @@ History - January 2026: Replaced outdated direct reference to :pep:`508` with a reference to :ref:`dependency-specifiers`. +- May 2026: Core metadata 2.6 was approved through :pep:`808`. + + - Allowed a multiple use field marked ``Dynamic`` to be appended to in a + wheel built from a sdist, requiring the wheel to preserve the value(s) + present in the sdist. + ---- .. [1] reStructuredText markup: diff --git a/source/specifications/pyproject-toml.rst b/source/specifications/pyproject-toml.rst index b4625bbb2..695b6e7f7 100644 --- a/source/specifications/pyproject-toml.rst +++ b/source/specifications/pyproject-toml.rst @@ -114,6 +114,13 @@ by the metadata). Dynamic metadata is listed via the ``dynamic`` key (defined later in this specification) and represents metadata that a tool will later provide. +A key whose value is a list or a table of arbitrary entries MAY be +specified statically *and* listed in ``dynamic`` at the same time. In +that case the entries given statically are fixed and a build back-end +MAY only *append* further entries to them; the back-end MUST NOT +remove, reorder, or modify any statically-specified entries. See the +:ref:`dynamic ` key for details. + The lack of a ``[project]`` table implicitly means the :term:`build backend ` will dynamically provide all keys. @@ -619,8 +626,9 @@ provided via tooling later on. field as "Optional", the metadata MAY list it in ``dynamic`` if the expectation is a build back-end will provide the data for the key later. -- Build back-ends MUST raise an error if the metadata specifies a - key statically as well as being listed in ``dynamic``. +- Build back-ends MUST raise an error if the metadata specifies a key + statically as well as being listed in ``dynamic``, *unless* the key + represents a list or arbitrary table that can be extended, listed below. - If the metadata does not list a key in ``dynamic``, then a build back-end CANNOT fill in the requisite metadata on behalf of the user (i.e. ``dynamic`` is the only way to allow a tool to fill in @@ -630,6 +638,35 @@ provided via tooling later on. the data for it (omitting the data, if determined to be the accurate value, is acceptable). +A key whose value is a list or a table of arbitrary entries MAY be +specified statically and listed in ``dynamic`` simultaneously. The +keys fitting that description are: + +- ``authors`` +- ``classifiers`` +- ``dependencies`` +- ``entry-points`` +- ``gui-scripts`` +- ``import-names`` +- ``import-namespaces`` +- ``keywords`` +- ``license-files`` +- ``maintainers`` +- ``optional-dependencies`` +- ``scripts`` +- ``urls`` + +When such a key is specified both statically and listed in +``dynamic``: + +- A build back-end MAY only *append* entries to the value; it MUST NOT + remove, reorder, or modify any statically-specified entries. For + tables (such as ``optional-dependencies`` or ``entry-points``) this + means a back-end MAY add new keys and MAY append to the values of + existing keys (in the case of a list), but MUST NOT change or remove the + entries given statically. +- A build back-end SHOULD raise an error if a key is listed in + ``dynamic`` and it does not support extending that key. .. _pyproject-tool-table: @@ -673,4 +710,8 @@ History - January 2026: Replaced outdated direct reference to :pep:`508` with a reference to :ref:`dependency-specifiers`. +- May 2026: Allowed list and table keys to be specified statically as well + as listed in ``dynamic``, with build back-ends only able to append + entries, through :pep:`808`. + .. _TOML: https://toml.io From cdb4bf7ce8de9263fc3ec9e4c46117f49c4f72c5 Mon Sep 17 00:00:00 2001 From: Jonathan Dung Date: Sun, 2 Aug 2026 17:08:06 +0800 Subject: [PATCH 18/25] Update comment --- source/specifications/dependency-groups.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/specifications/dependency-groups.rst b/source/specifications/dependency-groups.rst index a8f5b8bca..2fa758f7e 100644 --- a/source/specifications/dependency-groups.rst +++ b/source/specifications/dependency-groups.rst @@ -209,8 +209,8 @@ The output is therefore valid ``requirements.txt`` data. realized_group = [] for item in raw_group: if isinstance(item, str): - # packaging.requirements.Requirement parsing ensures that this is a valid - # PEP 508 Dependency Specifier + # packaging.requirements.Requirement parsing ensures that this + # is a valid dependency specifier # raises InvalidRequirement on failure Requirement(item) realized_group.append(item) From a69a69f638781c522a42b6eaf061ef3b045f1220 Mon Sep 17 00:00:00 2001 From: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> Date: Mon, 3 Aug 2026 07:16:47 +0000 Subject: [PATCH 19/25] Update uv_build version to 0.12.1 --- source/shared/build-backend-tabs.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/shared/build-backend-tabs.rst b/source/shared/build-backend-tabs.rst index 70029a72c..f71f25112 100644 --- a/source/shared/build-backend-tabs.rst +++ b/source/shared/build-backend-tabs.rst @@ -38,5 +38,5 @@ .. code-block:: toml [build-system] - requires = ["uv_build >= 0.12.0, <0.13.0"] + requires = ["uv_build >= 0.12.1, <0.13.0"] build-backend = "uv_build" From c2eff8d9d436b25642cae6540922b51b7355f2cd Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 5 Aug 2026 22:00:19 +0100 Subject: [PATCH 20/25] Update list of supported installer based on test results Tests are hosted in https://github.com/Trenza1ore/Self-Referential-Extras --- source/guides/writing-pyproject-toml.rst | 2 ++ source/specifications/pyproject-toml.rst | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source/guides/writing-pyproject-toml.rst b/source/guides/writing-pyproject-toml.rst index 665c1277b..98601da8d 100644 --- a/source/guides/writing-pyproject-toml.rst +++ b/source/guides/writing-pyproject-toml.rst @@ -200,6 +200,8 @@ a few years of maintenance and bug fixes: ] all = ["PyQt5", "rich", "click"] +Most installers and dependency managers now support this kind of extra, including +:ref:`pip`, :ref:`uv`, :ref:`poetry`, :ref:`hatch`, :ref:`pdm` and :ref:`pipenv`. .. _requires-python: .. _python_requires: diff --git a/source/specifications/pyproject-toml.rst b/source/specifications/pyproject-toml.rst index 7bc6ffbe1..c65e5494f 100644 --- a/source/specifications/pyproject-toml.rst +++ b/source/specifications/pyproject-toml.rst @@ -501,7 +501,8 @@ if the associated extra name is requested. Dependency specifiers in an extra may self-reference other extras from the current project (e.g. ``all = ["your-project-name[gui, cli]"]``). See :ref:`self-referential extras ` for an example. -Several installers including :ref:`pip` and :ref:`uv` support this pattern. +Most installers and dependency managers now support this kind of extra, including +:ref:`pip`, :ref:`uv`, :ref:`poetry`, :ref:`hatch`, :ref:`pdm` and :ref:`pipenv`. .. _pyproject-toml-import-names: From cd8e36378c3b959a17dec24486e84bb662c0a85e Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 5 Aug 2026 23:46:19 +0100 Subject: [PATCH 21/25] Use the term "package managers" as it's most commonly used - "package installer" is only used to describe pip - "dependency manager" is only used to describe pipenv --- source/guides/writing-pyproject-toml.rst | 2 +- source/specifications/pyproject-toml.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/guides/writing-pyproject-toml.rst b/source/guides/writing-pyproject-toml.rst index 98601da8d..a0ff484f1 100644 --- a/source/guides/writing-pyproject-toml.rst +++ b/source/guides/writing-pyproject-toml.rst @@ -200,7 +200,7 @@ a few years of maintenance and bug fixes: ] all = ["PyQt5", "rich", "click"] -Most installers and dependency managers now support this kind of extra, including +Most package managers now support this kind of extra, including :ref:`pip`, :ref:`uv`, :ref:`poetry`, :ref:`hatch`, :ref:`pdm` and :ref:`pipenv`. .. _requires-python: diff --git a/source/specifications/pyproject-toml.rst b/source/specifications/pyproject-toml.rst index c65e5494f..d4e504317 100644 --- a/source/specifications/pyproject-toml.rst +++ b/source/specifications/pyproject-toml.rst @@ -501,7 +501,7 @@ if the associated extra name is requested. Dependency specifiers in an extra may self-reference other extras from the current project (e.g. ``all = ["your-project-name[gui, cli]"]``). See :ref:`self-referential extras ` for an example. -Most installers and dependency managers now support this kind of extra, including +Most package managers now support this kind of extra, including :ref:`pip`, :ref:`uv`, :ref:`poetry`, :ref:`hatch`, :ref:`pdm` and :ref:`pipenv`. .. _pyproject-toml-import-names: From 84ea0ced2c41efa884801ab873d00f3f3b73bf1d Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 6 Aug 2026 14:18:56 +0100 Subject: [PATCH 22/25] Add history entry for this edit --- source/specifications/pyproject-toml.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/specifications/pyproject-toml.rst b/source/specifications/pyproject-toml.rst index d4e504317..3fca99c9f 100644 --- a/source/specifications/pyproject-toml.rst +++ b/source/specifications/pyproject-toml.rst @@ -678,4 +678,7 @@ History - January 2026: Replaced outdated direct reference to :pep:`508` with a reference to :ref:`dependency-specifiers`. +- August 2026: Document self-referential extra as a supported feature by many + modern package managers of Python. + .. _TOML: https://toml.io From 90174bb0614df3780ce0a921793aa6feece87231 Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Fri, 7 Aug 2026 17:29:11 +0900 Subject: [PATCH 23/25] docs: bump flit upper bound fix #2077 --- source/shared/build-backend-tabs.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/shared/build-backend-tabs.rst b/source/shared/build-backend-tabs.rst index f71f25112..5f3e0bf4c 100644 --- a/source/shared/build-backend-tabs.rst +++ b/source/shared/build-backend-tabs.rst @@ -22,7 +22,7 @@ .. code-block:: toml [build-system] - requires = ["flit_core >= 3.12.0, <4"] + requires = ["flit_core >= 3.12.0, <5"] build-backend = "flit_core.buildapi" .. tab:: PDM From e4ff704bae3400493912367381f7edb2f6b2a401 Mon Sep 17 00:00:00 2001 From: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> Date: Mon, 17 Aug 2026 06:15:53 +0000 Subject: [PATCH 24/25] Update uv_build version to 0.12.5 --- source/shared/build-backend-tabs.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/shared/build-backend-tabs.rst b/source/shared/build-backend-tabs.rst index 5f3e0bf4c..4f2a982c6 100644 --- a/source/shared/build-backend-tabs.rst +++ b/source/shared/build-backend-tabs.rst @@ -38,5 +38,5 @@ .. code-block:: toml [build-system] - requires = ["uv_build >= 0.12.1, <0.13.0"] + requires = ["uv_build >= 0.12.5, <0.13.0"] build-backend = "uv_build" From 1e8fe5eca1e4b4235a7ea79424ab0b727b338b7d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 18:51:01 +0000 Subject: [PATCH 25/25] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/codespell-project/codespell: v2.4.1 → v2.4.2](https://github.com/codespell-project/codespell/compare/v2.4.1...v2.4.2) - [github.com/astral-sh/ruff-pre-commit: v0.14.10 → v0.15.20](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.10...v0.15.20) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6d8d4e78b..4f9e5df7f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/codespell-project/codespell - rev: v2.4.1 + rev: v2.4.2 hooks: - id: codespell args: ["-L", "ned,ist,oder", "--skip", "*.po"] @@ -37,7 +37,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.10 + rev: v0.15.20 hooks: - id: ruff-check - id: ruff-format