From 7fbb1380f004b51d6064760d2612047a72a96c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Mon, 9 Nov 2026 07:42:31 -0800 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=93=A6=20build(sbom):=20ship=20a=20PE?= =?UTF-8?q?P=20770=20SBOM=20in=20wheels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/changelog/+python-sbom.packaging.rst | 2 + pylock.toml | 108 +++++++++++++++++++++- pyproject.toml | 9 ++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/+python-sbom.packaging.rst diff --git a/docs/changelog/+python-sbom.packaging.rst b/docs/changelog/+python-sbom.packaging.rst new file mode 100644 index 0000000..8639e06 --- /dev/null +++ b/docs/changelog/+python-sbom.packaging.rst @@ -0,0 +1,2 @@ +Every wheel now carries a `PEP 770 `_ CycloneDX SBOM in its +``.dist-info/sboms`` directory, written at build time by `python-sbom `_. diff --git a/pylock.toml b/pylock.toml index b15d24b..07c8522 100644 --- a/pylock.toml +++ b/pylock.toml @@ -798,6 +798,31 @@ size = 7552 [packages.wheels.hashes] sha256 = "9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7" +[[packages]] +name = "installer" +version = "1.1.0" +marker = "\"build\" in dependency_groups" +requires-python = ">=3.10" +index = "https://pypi.org/simple/" + +[packages.sdist] +name = "installer-1.1.0.tar.gz" +upload-time = 2026-10-12 19:35:52.851170+00:00 +url = "https://files.pythonhosted.org/packages/56/d3/2fab33d15004d41ae8e7b5d3e310510f7f34a7e1dd032a3e60d8b38d8fba/installer-1.1.0.tar.gz" +size = 481257 + +[packages.sdist.hashes] +sha256 = "5adc0c01ce62d809989e246987cd68944fe5df8af562d0358f65b2ab15cb5de7" + +[[packages.wheels]] +name = "installer-1.1.0-py3-none-any.whl" +upload-time = 2026-10-12 19:35:51.096942+00:00 +url = "https://files.pythonhosted.org/packages/d7/7a/63547a792a12148882205d79e07644091d5b7690f40c2bb9d41452a8bdc2/installer-1.1.0-py3-none-any.whl" +size = 464466 + +[packages.wheels.hashes] +sha256 = "f55f5728ff61d3dd54dbc5a397cf3f7307cb64b180c20b72afbebf01c9e2c8a0" + [[packages]] name = "jaraco-classes" version = "3.4.0" @@ -1179,6 +1204,31 @@ size = 832161 [packages.wheels.hashes] sha256 = "70f5ac8626e899a4bab0ef74ca2f5bd602f49c7b739e6e5026b4afc6d63dac42" +[[packages]] +name = "packageurl-python" +version = "0.17.6" +marker = "\"build\" in dependency_groups" +requires-python = ">=3.8" +index = "https://pypi.org/simple/" + +[packages.sdist] +name = "packageurl_python-0.17.6.tar.gz" +upload-time = 2025-11-24 15:20:17.998933+00:00 +url = "https://files.pythonhosted.org/packages/f5/d6/3b5a4e3cfaef7a53869a26ceb034d1ff5e5c27c814ce77260a96d50ab7bb/packageurl_python-0.17.6.tar.gz" +size = 50618 + +[packages.sdist.hashes] +sha256 = "1252ce3a102372ca6f86eb968e16f9014c4ba511c5c37d95a7f023e2ca6e5c25" + +[[packages.wheels]] +name = "packageurl_python-0.17.6-py3-none-any.whl" +upload-time = 2025-11-24 15:20:16.962118+00:00 +url = "https://files.pythonhosted.org/packages/b1/2f/c7277b7615a93f51b5fbc1eacfc1b75e8103370e786fd8ce2abf6e5c04ab/packageurl_python-0.17.6-py3-none-any.whl" +size = 36776 + +[packages.wheels.hashes] +sha256 = "31a85c2717bc41dd818f3c62908685ff9eebcb68588213745b14a6ee9e7df7c9" + [[packages]] name = "packaging" version = "26.3" @@ -1447,6 +1497,38 @@ size = 11248 [packages.wheels.hashes] sha256 = "1b82aa4b37137248bd687055e109723debeb07b489de1565297dc9589c5f2d6b" +[[packages]] +name = "python-sbom" +version = "0.1.2" +marker = "\"build\" in dependency_groups" +requires-python = ">=3.11" +dependencies = [ + { name = "hatchling" }, + { name = "installer" }, + { name = "packageurl-python" }, + { name = "packaging" }, + { name = "zipremove" }, +] +index = "https://pypi.org/simple/" + +[packages.sdist] +name = "python_sbom-0.1.2.tar.gz" +upload-time = 2026-11-08 17:49:13.751304+00:00 +url = "https://files.pythonhosted.org/packages/65/a7/abd61bb6e6cf681fc9bf1ff02f2357caf0ae958e9613e1a0f2fe00672726/python_sbom-0.1.2.tar.gz" +size = 245685 + +[packages.sdist.hashes] +sha256 = "5b611b565d6946926c8a1f6ec635beeea49887459f0a542f5350b77baafb2281" + +[[packages.wheels]] +name = "python_sbom-0.1.2-py3-none-any.whl" +upload-time = 2026-11-08 17:49:12.072616+00:00 +url = "https://files.pythonhosted.org/packages/5f/19/8c21420f27fcb14995e9b1c6cb451edaf341070d18996c42a96d77b80e64/python_sbom-0.1.2-py3-none-any.whl" +size = 196051 + +[packages.wheels.hashes] +sha256 = "d831293bc389cbb9c444b30141692866d3c54f64e3c50a74fe6d74bd8517474a" + [[packages]] name = "pyyaml" version = "6.0.3" @@ -2519,6 +2601,31 @@ size = 6195 [packages.wheels.hashes] sha256 = "3fa599046443d4ca830d06e3d180cd0a675d5871af0a68daa5623318bb4d17e3" +[[packages]] +name = "zipremove" +version = "0.10.0" +marker = "\"build\" in dependency_groups" +requires-python = "~=3.7" +index = "https://pypi.org/simple/" + +[packages.sdist] +name = "zipremove-0.10.0.tar.gz" +upload-time = 2026-07-17 15:50:45.516180+00:00 +url = "https://files.pythonhosted.org/packages/92/30/47d65b9213f52df8a51f603cb0a2e5ef02c22172a8a17805e46c3beabb0d/zipremove-0.10.0.tar.gz" +size = 25448 + +[packages.sdist.hashes] +sha256 = "3c5957c115447b54299d3a23128764b59c4558fc98c4b878ff2dbc5db8a62021" + +[[packages.wheels]] +name = "zipremove-0.10.0-py3-none-any.whl" +upload-time = 2026-07-17 15:50:44.653422+00:00 +url = "https://files.pythonhosted.org/packages/0a/e4/2225c1890ce6e239ca23efabb80a3481229a14a2deaa489f5e89723a5aa6/zipremove-0.10.0-py3-none-any.whl" +size = 11280 + +[packages.wheels.hashes] +sha256 = "04e15df7083642d5b791e51f597cffef8a92d770ecf5160c529b5a7b53b40100" + [tool.nab] nab-version = "0.0.23" created-at = 2026-11-03 15:38:15.600801+00:00 @@ -2528,7 +2635,6 @@ command-line = [ "--all-groups", "--all-extras", "--no-cache", - "--upgrade", ] input-path = "pyproject.toml" mode = "universal" diff --git a/pyproject.toml b/pyproject.toml index 48af5e2..7ce0b62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ requires = [ "hatch-vcs>=0.5", "hatchling>=1.27; python_version<'3.10'", "hatchling>=1.28; python_version>='3.10'", + "python-sbom[hatch]>=0.1.2; python_version>='3.11'", ] [project] @@ -79,6 +80,7 @@ build = [ "hatch-vcs>=0.5", "hatchling>=1.27; python_version<'3.10'", "hatchling>=1.28; python_version>='3.10'", + "python-sbom[hatch]>=0.1.2; python_version>='3.11'", "setuptools>=80", ] pkg-meta = [ @@ -103,6 +105,7 @@ release-prepare = [ version.source = "vcs" metadata.hooks.fancy-pypi-readme.content-type = "text/markdown" metadata.hooks.fancy-pypi-readme.fragments = [ { path = "README.md" } ] +build.hooks.python-sbom = {} [tool.uv] dependency-groups.docs = { requires-python = ">=3.12" } @@ -270,6 +273,9 @@ type = [ { directory = "packaging", name = "Packaging", showcontent = true }, ] +[tool.python-sbom] +supplier = { name = "tox-dev", url = [ "https://github.com/tox-dev" ] } + [tool.nab] mode = "universal" base-group = "project-runtime" @@ -280,6 +286,9 @@ matrix.platforms = [ "linux_x86_64" ] # release-creator 4.4.0 needs a seven-day cutoff exception. # expires 2026-11-09 packages.release-creator.uploaded-prior-to = 2026-11-02T21:45:00Z +# python-sbom 0.1.2 needs a seven-day cutoff exception. +# expires 2026-11-15 +packages.python-sbom.uploaded-prior-to = 2026-11-08T17:54:00Z [tool.simplint] docstring-style = "rst" From 5ae7186867fbaa814b8077e01d5ffc02749dbbe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Mon, 9 Nov 2026 08:10:16 -0800 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=90=9B=20fix(build):=20keep=203.10=20?= =?UTF-8?q?builds=20working?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit python-sbom needs Python 3.11, and hatchling rejects a configured hook whose plugin is absent, so building on 3.10 failed. Load the hook from hatch_build.py, which falls back to a no-op hook before 3.11. --- hatch_build.py | 14 ++++++++++++++ pyproject.toml | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 hatch_build.py diff --git a/hatch_build.py b/hatch_build.py new file mode 100644 index 0000000..32b4b1d --- /dev/null +++ b/hatch_build.py @@ -0,0 +1,14 @@ +"""Ship a PEP 770 SBOM in wheels built on Python 3.11 or later.""" + +from __future__ import annotations + +import sys + +if sys.version_info >= (3, 11): + from python_sbom.hatch import SbomBuildHook +else: # python-sbom needs Python 3.11, so builds on older interpreters carry no SBOM + from hatchling.builders.hooks.plugin.interface import BuildHookInterface as SbomBuildHook + + +def get_build_hook() -> type[SbomBuildHook]: + return SbomBuildHook diff --git a/pyproject.toml b/pyproject.toml index 7ce0b62..6463ace 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,7 +105,7 @@ release-prepare = [ version.source = "vcs" metadata.hooks.fancy-pypi-readme.content-type = "text/markdown" metadata.hooks.fancy-pypi-readme.fragments = [ { path = "README.md" } ] -build.hooks.python-sbom = {} +build.hooks.custom.path = "hatch_build.py" [tool.uv] dependency-groups.docs = { requires-python = ">=3.12" } From 93759914ca5a20730cb5d84c9f7b54eb052608ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Mon, 9 Nov 2026 08:13:58 -0800 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=90=9B=20fix(type):=20resolve=20hatch?= =?UTF-8?q?=5Fbuild.py=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ty checks the whole tree, so the type envs need hatchling and, from 3.11 on, python-sbom. --- tox.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tox.toml b/tox.toml index d95af14..6fb8b79 100644 --- a/tox.toml +++ b/tox.toml @@ -33,12 +33,12 @@ default_base_python = [ "3.15" ] [env."type-3.15"] description = "run type check on code base (3.15)" -deps = [ "gitpython>=3.2", "packaging>=26.2", "ty==0.0.84" ] +deps = [ "gitpython>=3.2", "hatchling>=1.27", "packaging>=26.2", "python-sbom[hatch]>=0.1.2; python_version>='3.11'", "ty==0.0.84" ] commands = [ [ "ty", "check", "--output-format", "concise", "--error-on-warning", "--python-version", "3.15", "." ] ] [env."type-3.9"] description = "run type check on code base (3.9)" -deps = [ "gitpython>=3.2", "packaging>=26.2", "ty==0.0.84" ] +deps = [ "gitpython>=3.2", "hatchling>=1.27", "packaging>=26.2", "python-sbom[hatch]>=0.1.2; python_version>='3.11'", "ty==0.0.84" ] commands = [ [ "ty", "check", "--output-format", "concise", "--error-on-warning", "--python-version", "3.9", "." ] ] [env.docs]