Support parent-relative pyproject metadata in sdists#3182
Merged
Conversation
2 tasks
Copilot
AI
changed the title
[WIP] Fix sdist installation issue in maturin project
Include May 11, 2026
[project.readme] table-form file at sdist root
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Fixes maturin sdist for Cargo workspace members where pyproject.toml is elevated to the sdist root and [project.readme] uses the PEP 621 table form, ensuring the referenced README is also copied to the sdist root so metadata generation doesn’t fail.
Changes:
- Extend
add_pyproject_metadatato also handleReadMe::Table { file: Some(...) }when copying README into the sdist root. - Add a regression test covering workspace-member
pyproject.tomlwith table-form[project.readme].
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/source_distribution/pyproject.rs | Adds support for table-form [project.readme] so the README is included at the sdist root when pyproject.toml is elevated. |
| tests/run/sdist.rs | Adds a regression test asserting README is present at the archive root for the table-form readme case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
da61e08 to
6c6b9da
Compare
6c6b9da to
db4c966
Compare
db4c966 to
06dad83
Compare
[project.readme] table-form file at sdist root06dad83 to
464e8c4
Compare
When `pyproject.toml` lives in a subdirectory of a Cargo workspace,
`add_pyproject_metadata` only elevated the readme to the sdist root for
the string form (`readme = "README.md"`). The table form
(`[project.readme]` with `file = "README.md"`) was silently ignored, so
the file remained under the workspace-member subdirectory and `pip
install` of the sdist failed when generating metadata.
Handle the `ReadMe::Table { file, .. }` variant alongside
`ReadMe::RelativePath` so the readme is copied next to `pyproject.toml`
in either case.
Agent-Logs-Url: https://github.com/PyO3/maturin/sessions/c75f929a-fc52-412b-908c-644c020e442b
Co-authored-by: messense <1556054+messense@users.noreply.github.com>
Agent-Logs-Url: https://github.com/PyO3/maturin/sessions/c75f929a-fc52-412b-908c-644c020e442b Co-authored-by: messense <1556054+messense@users.noreply.github.com>
Reject absolute paths and `..` traversal in the `file` values of `[project.readme]` and `[project.license]` before adding them to the sdist. Otherwise such paths could place files at surprising locations in the archive or read files outside the project directory when the sdist copies them next to `pyproject.toml`. Agent-Logs-Url: https://github.com/PyO3/maturin/sessions/304ac3d5-d758-482b-9beb-8d13060340e7 Co-authored-by: messense <1556054+messense@users.noreply.github.com>
Combine the validate/dedupe/add steps for files referenced from
`pyproject.toml` (`project.readme.file`, `project.license.file`) into a
single `add_pyproject_relative_file` helper. Previously the call sites
duplicated the `root_dir.join` / `writer.contains_target` / `writer.add_file`
sequence, and a separate `check_pyproject_relative_path` only validated
the path.
Also collapse the `pyproject_toml::ReadMe` match into a single or-pattern
covering both `RelativePath(file)` and `Table { file: Some(file), .. }`,
and let the helper take `impl AsRef<Path>` so it accepts the readme's
`String` and the license's `PathBuf` without per-call-site conversions.
No behavior change.
Allow Cargo-generated sdists to include pyproject readme and license files that live above a workspace member, rewriting the root pyproject.toml paths to their archive locations. Reject those parent-relative metadata paths for the git sdist generator so its output remains faithful to git ls-files.
464e8c4 to
2bdb8d4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3181.
When
pyproject.tomllives in a Cargo workspace member,maturin sdistplacespyproject.tomlat the sdist root as required by the source distribution format. If PEP 621 metadata such as[project.readme] file = "../README.md"orlicense = { file = "../LICENSE" }points outside the member directory, the elevatedpyproject.tomlused to keep paths that no longer resolved from the sdist root, causingpip install <sdist>metadata generation to fail.Changes
project.readmeandproject.license.filemetadata files referenced frompyproject.toml, including parent-relative paths that stay within the Cargo workspace.pyproject.tomlso they point at the files' archive locations.PKG-INFO/License-Filemetadata aligned with the rewritten sdist layout for parent-relativeproject.license.file.git ls-files.pyproject.tomlreferences parent metadata files, and for the Git-generator rejection case.Notes
The Cargo sdist path is intentionally allowed to copy and rewrite these metadata files because it already constructs an archive layout around Cargo workspace membership and path dependencies. The Git sdist path intentionally does not do this: it should package exactly what
git ls-filesreports from thepyproject.tomldirectory, so parent-relative metadata paths are reported as unsupported there.