Skip to content

🐛 fix(build): carry toml-fmt-common in the sdist - #451

Merged
gaborbernat merged 1 commit into
tox-dev:mainfrom
gaborbernat:fix-sdist-vendoring
Aug 31, 2026
Merged

gaborbernat merged 1 commit into
tox-dev:mainfrom
gaborbernat:fix-sdist-vendoring

Conversation

@gaborbernat

Copy link
Copy Markdown
Member

What broke

pyproject-fmt 2.29.0 and tox-toml-fmt 1.10.0 ship an sdist that declares Requires-Dist: toml-fmt-common. A build from it (a distro packager, pip install --no-binary, pip install -e .) resolves that name from PyPI, where the last upload is 1.3.5 from 2026-05-29. This tree's copy carries the same version number and over 400 different lines, so the install runs May's settings reader against August's formatter. #450 reports the 26 test failures that follow.

Vendoring ran in build_wheel alone, and only where ../toml-fmt-common/src/toml_fmt_common sat beside the package:

if not (_COMMON / "src" / _VENDOR).is_dir():  # no workspace (e.g. building from sdist)
    return maturin.build_wheel(...)

The sdist shipped the Rust common/ crate without the Python sibling, so a build from it took that escape hatch and wrote an unvendored wheel. build_editable vendored nothing.

Changes

  • build_sdist writes toml-fmt-common's Python sources and its pyproject.toml into the tarball, so a wheel built from the sdist vendors like any other.
  • build_editable adds a .pth naming toml-fmt-common's source directory, so an editable install reads the live sources rather than a published snapshot.
  • _MODULE and _COMMON resolve in the sdist layout, where the backend sits at the tarball root rather than beside the package. _MODULE now reads the project name instead of the directory name, which in an sdist is pyproject_fmt-2.29.0.
  • Both packages drop dependencies = ["toml-fmt-common"], and the workspace drops the uv source that pointed it at the local member. Nothing resolves the published distribution now, and a vendor step that goes missing raises an ImportError instead of installing four-month-old code.

Why CI missed it

The test environments install a wheel built from the working tree, where the sibling is present, so vendoring ran. pkg_meta built an sdist and then only linted its metadata with twine check. The dev environment built an editable install and never imported through it.

  • pkg_sdist builds the sdist, builds a wheel from it, and fails if that wheel holds no _vendor/toml_fmt_common or still requires toml-fmt-common. It runs in the check matrix of both packages.
  • dev runs import toml_fmt_common.

Fixes #450

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (f089730) to head (9924565).

Additional details and impacted files
Flag Coverage Δ
pyproject-fmt 100.00% <ø> (?)
tox-rules 100.00% <ø> (?)
tox-toml-fmt 100.00% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 43 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The sdist declared Requires-Dist: toml-fmt-common, so a build from it
resolved that name from PyPI, where the last upload is 1.3.5 from
2026-05-29. The tree's copy carries the same version number and over 400
different lines, so the install ran May's settings reader against
August's formatter.

Vendoring ran in build_wheel alone, and only where the sibling Python
source sat beside the package. The sdist shipped the Rust crate without
it, and build_editable vendored nothing.

Fixes tox-dev#450
@gaborbernat
gaborbernat enabled auto-merge (squash) August 31, 2026 20:09
@gaborbernat
gaborbernat merged commit 39cf741 into tox-dev:main Aug 31, 2026
159 checks passed
gaborbernat added a commit that referenced this pull request Aug 31, 2026
pyproject-fmt 2.29.1 and tox-toml-fmt 1.10.1 ship an sdist that carries
no `toml-fmt-common` and no dependency naming one, so a wheel built from
either fails to import. The wheels on PyPI hold their vendored copy and
install as before.

#451 removed the dependency and vendored toml-fmt-common in the PEP 517
`build_sdist` hook. A release stops short of that hook, building the
sdist through maturin-action, the same bypass the wheel jobs work around
by running the backend's CLI afterwards (`_build.yaml:120`). The sdist
job had no such step, so what got published skipped the vendoring.

## Changes

- The backend CLI patches a tarball as well as a wheel, and exits where
the sources it vendors are missing rather than write an artifact that
imports nothing.
- The sdist job runs that CLI and then reads the tarball back to confirm
the sources landed.

## The gate

`pkg_sdist` built the sdist with `uv build`, which does reach the hook,
so it passed on a path no release takes. It now builds the sdist both
ways and runs the release one end to end:

```
maturin sdist → build_backend.py → wheel → empty venv, --no-index → pyproject-fmt --version
```

`--no-index` leaves nothing to fall back on, so a wheel whose common
went missing cannot install or import. Against the code this PR fixes,
the check fails at the first step.
gaborbernat added a commit that referenced this pull request Sep 1, 2026
`pytest` against an unpacked 2.29.2 sdist ends with eight errors, all of
them `FileNotFoundError` on `pyproject-fmt/pyproject.toml`
([#454](#454)).

maturin hoists the package's `pyproject.toml` to the root of the tarball
and ships a copy of `build_backend.py` under `pyproject-fmt/`, beside
the tests. #451 made the backend read that file from beside itself,
which holds in a checkout and in the tarball root, and holds nowhere in
the directory the tests load it from. The backend reads it from either
place.

## The check that surfaced it

`pkg_sdist` built the sdist, built a wheel from it, installed that with
`--no-index` and ran the console script. It proved the artifact
installs. It never ran the suite the sdist ships, which is what a
packager does and what the report in #450 spelled out.

It now ends with those steps: unpack the sdist, install it, run the
suite it carries. tox supplies the environment and the test group, so
the check installs into the interpreter it already runs under rather
than building an environment of its own.

Against the code this PR fixes the check ends:

```
======================== 73 passed, 8 errors in 0.79s ========================
```

the same eight ids #454 lists. With the fix, 81 pass, and 60 for
tox-toml-fmt.

Fixes #454
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lots of test failures in pyproject-fmt 2.29.0 release

1 participant