Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions crates/uv/src/commands/project/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::sync::Arc;
use anyhow::Result;
use itertools::Itertools;
use owo_colors::OwoColorize;
use rustc_hash::FxHashSet;
use serde::Serialize;
use tracing::warn;
use uv_cache::Cache;
Expand Down Expand Up @@ -133,16 +134,6 @@ pub(crate) async fn sync(
project
};

// TODO(lucab): improve warning content
// <https://github.com/astral-sh/uv/issues/7428>
if project.workspace().pyproject_toml().has_scripts()
&& !project.workspace().pyproject_toml().is_package(true)
{
warn_user!(
"Skipping installation of entry points (`project.scripts`) because this project is not packaged; to install entry points, set `tool.uv.package = true` or define a `build-system`"
);
}

SyncTarget::Project(project)
};

Expand Down Expand Up @@ -394,6 +385,23 @@ pub(crate) async fn sync(
// Identify the installation target.
let sync_target = identify_installation_target(&target, outcome.lock(), all_packages, &package);

// TODO(lucab): improve warning content
// <https://github.com/astral-sh/uv/issues/7428>
if let SyncTarget::Project(project) = &target {
let roots = sync_target.roots().collect::<FxHashSet<_>>();
for (name, member) in project.workspace().packages() {
if roots.contains(name)
&& member.pyproject_toml().has_scripts()
&& !member.pyproject_toml().is_package(true)
{
warn_user!(
"Skipping installation of entry points (`project.scripts`) for package `{}` because this project is not packaged; to install entry points, set `tool.uv.package = true` or define a `build-system`",
name
);
}
}
}

let state = state.fork();

// Perform the sync operation.
Expand Down
104 changes: 102 additions & 2 deletions crates/uv/tests/it/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8318,8 +8318,8 @@ fn sync_scripts_without_build_system() -> Result<()> {
----- stdout -----

----- stderr -----
warning: Skipping installation of entry points (`project.scripts`) because this project is not packaged; to install entry points, set `tool.uv.package = true` or define a `build-system`
Resolved 1 package in [TIME]
warning: Skipping installation of entry points (`project.scripts`) for package `foo` because this project is not packaged; to install entry points, set `tool.uv.package = true` or define a `build-system`
Audited in [TIME]
");

Expand Down Expand Up @@ -8367,8 +8367,108 @@ fn sync_scripts_project_not_packaged() -> Result<()> {
----- stdout -----

----- stderr -----
warning: Skipping installation of entry points (`project.scripts`) because this project is not packaged; to install entry points, set `tool.uv.package = true` or define a `build-system`
Resolved 1 package in [TIME]
warning: Skipping installation of entry points (`project.scripts`) for package `foo` because this project is not packaged; to install entry points, set `tool.uv.package = true` or define a `build-system`
Audited in [TIME]
");

Ok(())
}

#[test]
/// Check warning message for <https://github.com/astral-sh/uv/issues/18388>
/// if a workspace member has scripts but no `build-system`.
fn sync_scripts_workspace_member_not_packaged() -> Result<()> {
let context = uv_test::test_context!("3.12");

let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "root"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []

[tool.uv.workspace]
members = ["member"]
"#,
)?;

let member = context.temp_dir.child("member");
fs_err::create_dir_all(&member)?;

let member_pyproject_toml = member.child("pyproject.toml");
member_pyproject_toml.write_str(
r#"
[project]
name = "member"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []

[project.scripts]
member = "main:main"
"#,
)?;

uv_snapshot!(context.filters(), context.sync().arg("--all-packages"), @"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 2 packages in [TIME]
warning: Skipping installation of entry points (`project.scripts`) for package `member` because this project is not packaged; to install entry points, set `tool.uv.package = true` or define a `build-system`
Audited in [TIME]
");

Ok(())
}

#[test]
/// Check that the warning is not emitted for workspace members that are not being synced.
fn sync_scripts_workspace_member_not_packaged_not_synced() -> Result<()> {
let context = uv_test::test_context!("3.12");

let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "root"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []

[tool.uv.workspace]
members = ["member"]
"#,
)?;

let member = context.temp_dir.child("member");
fs_err::create_dir_all(&member)?;

let member_pyproject_toml = member.child("pyproject.toml");
member_pyproject_toml.write_str(
r#"
[project]
name = "member"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []

[project.scripts]
member = "main:main"
"#,
)?;

uv_snapshot!(context.filters(), context.sync(), @"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 2 packages in [TIME]
Audited in [TIME]
");

Expand Down
Loading