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
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",
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
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:
diff --git a/source/shared/build-backend-tabs.rst b/source/shared/build-backend-tabs.rst
index 8b5c9e91f..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
@@ -38,5 +38,5 @@
.. code-block:: toml
[build-system]
- requires = ["uv_build >= 0.11.7, <0.12.0"]
+ requires = ["uv_build >= 0.12.1, <0.13.0"]
build-backend = "uv_build"
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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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/dependency-groups.rst b/source/specifications/dependency-groups.rst
index 2fa82cd90..2fa758f7e 100644
--- a/source/specifications/dependency-groups.rst
+++ b/source/specifications/dependency-groups.rst
@@ -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
=======
diff --git a/source/specifications/inline-script-metadata.rst b/source/specifications/inline-script-metadata.rst
index 6fa832a3e..f9df2f0f5 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.
+* 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
-----------
diff --git a/source/specifications/pyproject-toml.rst b/source/specifications/pyproject-toml.rst
index 60c7218f9..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.
@@ -215,7 +222,7 @@ If the file path ends in a case-insensitive ``.md`` suffix, then tools
MUST assume the content-type is ``text/markdown``. If the file path
ends in a case-insensitive ``.rst``, then tools MUST assume the
content-type is ``text/x-rst``. If a tool recognizes more extensions
-than this PEP, they MAY infer the content-type for the user without
+than this specification, it MAY infer the content-type for the user without
specifying this key as ``dynamic``. For all unrecognized suffixes
when a content-type is not provided, tools MUST raise an error.
@@ -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
diff --git a/source/specifications/simple-repository-api.rst b/source/specifications/simple-repository-api.rst
index d317db6f7..d7e14a4d3 100644
--- a/source/specifications/simple-repository-api.rst
+++ b/source/specifications/simple-repository-api.rst
@@ -122,6 +122,15 @@ HTML Serialization
.. _simple-repository-html-project-list:
+.. important::
+
+ The HTML representation is considered "frozen" and is not expected
+ to be updated. Producers and consumers of the simple API
+ should prefer the :ref:`JSON representation `.
+
+ See :pep:`833` for additional information about the HTML representation's
+ status.
+
The following constraints apply to all HTML serialized responses described in
this spec:
@@ -989,3 +998,4 @@ History
* November 2024: provenance metadata in the HTML and JSON formats, in :pep:`740`
* July 2025: project status markers in the HTML and JSON formats, in :pep:`792`
* July 2025: layout changes (dedicated page for file yanking, introduce concepts before API details)
+* June 2026: :pep:`833` formally "freezes" the HTML representation of the simple API