Skip to content

Treat workspace members with an intermediate pyproject.toml as standalone#19924

Closed
konstin wants to merge 1 commit into
mainfrom
konsti/intermediate-pyproject-toml-regression
Closed

Treat workspace members with an intermediate pyproject.toml as standalone#19924
konstin wants to merge 1 commit into
mainfrom
konsti/intermediate-pyproject-toml-regression

Conversation

@konstin

@konstin konstin commented Jun 19, 2026

Copy link
Copy Markdown
Member

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

@konstin konstin added the bug Something isn't working label Jun 19, 2026
…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
@konstin
konstin force-pushed the konsti/intermediate-pyproject-toml-regression branch from ec0a2ed to 8d69795 Compare June 19, 2026 15:02
@astral-sh-bot

astral-sh-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown

uv test inventory changes

This PR changes the tests when compared with the latest main baseline.

  • Added tests: 2
  • Removed tests: 0
  • Changed suites: 1
uv::lock: +2 / -0

Added:

  • uv::lock::lock::lock_no_workspace_source_nested_project
  • uv::lock::lock::lock_workspace_member_with_standalone_path_source

Removed: none

@EliteTK EliteTK left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 0

I 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.

Comment on lines +592 to +596
project_dir
.ancestors()
.skip(1)
.take_while(|ancestor| *ancestor != workspace_root)
.any(|ancestor| ancestor.join("pyproject.toml").is_file())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 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

Gankra pushed a commit that referenced this pull request Jun 19, 2026
…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>
@EliteTK EliteTK closed this Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression in workspace source override between uv 0.11.19 and 0.11.20

3 participants