Treat workspace members with an intermediate pyproject.toml as standalone#19924
Treat workspace members with an intermediate pyproject.toml as standalone#19924konstin wants to merge 1 commit into
pyproject.toml as standalone#19924Conversation
…dalone Handle the case where a `pyproject.toml` sits between a member and its workspace root. This unintentionally supported case regressed when adding workspace caching, which memorizes which projects are workspace members without traversing upwards, ignoring the `pyproject.toml` in the middle. Before caching, workspace discovery for this project starting from the project itself would terminate at the intermediate `pyroject.toml` and treat it as standalone project, which this hack restores. Fixes #19916
ec0a2ed to
8d69795
Compare
uv test inventory changesThis PR changes the tests when compared with the latest
|
EliteTK
left a comment
There was a problem hiding this comment.
I think fundamentally this doesn't actually change which workspace a package sees. Which lets things leak in from the outer workspace like so:
#!/usr/bin/env bash
cargo build --profile fast-build --bin uv || exit 125
uv=$PWD/target/fast-build/uv
tmpdir=$(mktemp -d) || exit 125
trap 'rm -rf "$tmpdir"' exit
cd "$tmpdir" || exit 125
mkdir -p packages/{app,lib} || exit 125
cat <<EOF >pyproject.toml || exit 125
[tool.uv.workspace]
members = [
"packages/app",
"packages/lib",
]
EOF
cat <<EOF >packages/pyproject.toml || exit 125
[project]
name = "packages"
version = "0.1.0"
EOF
cat <<EOF >packages/app/pyproject.toml || exit 125
[project]
name = "app"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["lib"]
[tool.uv.sources]
lib = { workspace = true }
EOF
cat <<EOF >packages/lib/pyproject.toml || exit 125
[project]
name = "lib"
version = "0.1.0"
EOF
output=$tmpdir/output
# Should fail to lock with an error
"$uv" lock --offline && exit 1
exit 0I think this is maybe acceptable as it shouldn't break things? I'm not sure.
But I think a cleaner, possibly similarly simple fix would be to avoid inserting the member-root → outer-workspace cache entry when there is an intermediate pyproject.toml between that member and the workspace root.
| project_dir | ||
| .ancestors() | ||
| .skip(1) | ||
| .take_while(|ancestor| *ancestor != workspace_root) | ||
| .any(|ancestor| ancestor.join("pyproject.toml").is_file()) |
There was a problem hiding this comment.
This I believe is actually broader than it used to be. We'd parse the intermediate files to check for certain qualities, not merely check they exist.
| // starting from the project itself would terminate at the intermediate `pyroject.toml` and | ||
| // treat it as standalone project, which this hack restores. | ||
| // <https://github.com/astral-sh/uv/issues/19916> | ||
| let treat_as_standalone_project = |
There was a problem hiding this comment.
Given the limitations of this approach, I am not sure if we should use this name.
| // This unintentionally supported case regressed when adding workspace caching, which | ||
| // memorizes which projects are workspace members without traversing upwards, ignoring the | ||
| // `pyproject.toml` in the middle. Before caching, workspace discovery for this project | ||
| // starting from the project itself would terminate at the intermediate `pyroject.toml` and |
There was a problem hiding this comment.
| // starting from the project itself would terminate at the intermediate `pyroject.toml` and | |
| // starting from the project itself would terminate at the intermediate `pyproject.toml` and |
…dalone (#19926) ## Summary Based on #19924. Handle the case where a `pyproject.toml` sits between a member and its workspace root. This unintentionally supported case regressed when adding workspace caching, which memorises which projects are members of a workspace without requiring re-discovery, ignoring a `pyproject.toml` in the middle. Before caching, workspace discovery for this project starting from the project itself would terminate at the intermediate `pyroject.toml` and treat it as standalone project, which this hack restores. Fixes #19916 ## Test Plan Added a regression test, unlike for Konsti's version of the PR, we have existing coverage for the case where we mess this up so we don't need a second test to cover it. Co-authored-by: konstin <konstin@mailbox.org>
Handle the case where a
pyproject.tomlsits between a member and its workspace root.This unintentionally supported case regressed when adding workspace caching, which
memorizes which projects are workspace members without traversing upwards, ignoring the
pyproject.tomlin the middle. Before caching, workspace discovery for this projectstarting from the project itself would terminate at the intermediate
pyroject.tomlandtreat it as standalone project, which this hack restores.
Fixes #19916