Use it with setuptools

python-sbom ships a setuptools plugin, registered in setuptools’ setuptools.finalize_distribution_options entry point group, the one setuptools-scm uses. Add python-sbom to the build requirements, with the setuptools extra, and add a [tool.python-sbom] table, empty or not:

pyproject.toml
[build-system]
build-backend = "setuptools.build_meta"
requires = [ "python-sbom[setuptools]>=0.3", "setuptools>=77" ]

[project]
name = "greet"
version = "1.0"
description = "says hello"
license = "MIT"
requires-python = ">=3.11"
classifiers = [
  "Programming Language :: Python :: 3 :: Only",
  "Programming Language :: Python :: 3.11",
  "Programming Language :: Python :: 3.12",
  "Programming Language :: Python :: 3.13",
  "Programming Language :: Python :: 3.14",
  "Programming Language :: Python :: 3.15",
]
dependencies = [ "packaging>=24" ]

[tool.python-sbom]
supplier = { name = "You", url = [ "https://github.com/you" ] }

Every wheel you build now carries the SBOM, and every sdist the source revision. An editable wheel carries none. Build one and check it:

$ python -m build --wheel
$ python-sbom validate dist/
SBOM in greet-1.0-py3-none-any.whl is valid

docs/examples/setuptools holds the whole project.

setuptools calls the plugin for every build in an environment where python-sbom is installed, so the table is what turns it on: a project without [tool.python-sbom], or without a pyproject.toml, builds as before.

The plugin wraps the bdist_wheel and sdist commands the project uses, including subclasses it passes to setup() as cmdclass, and writes the SBOM once the wheel is written.

Pitfall: commands set in pyproject.toml

setuptools applies [tool.setuptools.cmdclass] after the plugin runs, so a bdist_wheel or sdist named there would replace the plugin’s and the wheel would get no SBOM. The plugin stops such a build with an error instead. Move that command to setup.py’s cmdclass, or wrap the backend instead, as Use it with any other backend shows with build-backend = 'setuptools.build_meta'.

Pitfall: build output in the checkout

setuptools writes build/ and <name>.egg-info/ into the project directory, and frontends run egg_info before they ask for the wheel or sdist. python-sbom counts untracked files as changes, so unless git ignores both, every build reads the checkout as modified: the wheel’s SBOM names no exact commit, and the sdist carries no source revision. Ignore them:

build/
dist/
*.egg-info/