Skip to content

Commit

Permalink
Avoid un-strict syncing by-default for build isolation (astral-sh#6606)
Browse files Browse the repository at this point in the history
## Summary

Closes astral-sh#6580.

Closes astral-sh#6599.
  • Loading branch information
charliermarsh authored Aug 26, 2024
1 parent a7850d2 commit 023acbe
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 18 deletions.
5 changes: 1 addition & 4 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2261,10 +2261,7 @@ pub struct SyncArgs {
/// Do not remove extraneous packages present in the environment.
///
/// When enabled, uv will make the minimum necessary changes to satisfy the requirements.
///
/// By default, syncing will remove any extraneous packages from the environment, unless
/// `--no-build-isolation` is enabled, in which case extra packages are considered necessary for
/// builds.
/// By default, syncing will remove any extraneous packages from the environment
#[arg(long, overrides_with("exact"), alias = "no-exact")]
pub inexact: bool,

Expand Down
17 changes: 6 additions & 11 deletions crates/uv/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ impl PythonPinSettings {
}
}
}

/// The resolved settings to use for a `sync` invocation.
#[allow(clippy::struct_excessive_bools, dead_code)]
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -668,16 +669,6 @@ impl SyncSettings {
filesystem,
);

let exact = flag(exact, inexact).unwrap_or(true);

// By default, sync with exact semantics, unless the user set `--no-build-isolation`;
// otherwise, we'll end up removing build dependencies.
let modifications = if !exact || settings.no_build_isolation {
Modifications::Sufficient
} else {
Modifications::Exact
};

Self {
locked,
frozen,
Expand All @@ -689,7 +680,11 @@ impl SyncSettings {
no_install_project,
no_install_workspace,
no_install_package,
modifications,
modifications: if flag(exact, inexact).unwrap_or(true) {
Modifications::Exact
} else {
Modifications::Sufficient
},
package,
python,
refresh: Refresh::from(refresh),
Expand Down
122 changes: 122 additions & 0 deletions crates/uv/tests/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ fn virtual_workspace_dev_dependencies() -> Result<()> {
Ok(())
}

/// Use a `pip install` step to pre-install build dependencies for `--no-build-isolation`.
#[test]
fn sync_build_isolation() -> Result<()> {
let context = TestContext::new("3.12");
Expand Down Expand Up @@ -479,16 +480,25 @@ fn sync_build_isolation() -> Result<()> {
----- stderr -----
Resolved 2 packages in [TIME]
Prepared 2 packages in [TIME]
Uninstalled 7 packages in [TIME]
Installed 2 packages in [TIME]
- hatchling==1.22.4
- packaging==24.0
- pathspec==0.12.1
- pluggy==1.4.0
+ project==0.1.0 (from file://[TEMP_DIR]/)
- setuptools==69.2.0
+ source-distribution==0.0.1 (from https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz)
- trove-classifiers==2024.3.3
- wheel==0.43.0
"###);

assert!(context.temp_dir.child("uv.lock").exists());

Ok(())
}

/// Use a `pip install` step to pre-install build dependencies for `--no-build-isolation-package`.
#[test]
fn sync_build_isolation_package() -> Result<()> {
let context = TestContext::new("3.12");
Expand Down Expand Up @@ -575,6 +585,118 @@ fn sync_build_isolation_package() -> Result<()> {
Ok(())
}

/// Use dedicated extra groups to install dependencies for `--no-build-isolation-package`.
#[test]
fn sync_build_isolation_extra() -> Result<()> {
let context = TestContext::new("3.12");

let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[project.optional-dependencies]
build = ["hatchling"]
compile = ["source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz"]
[build-system]
requires = ["setuptools >= 40.9.0"]
build-backend = "setuptools.build_meta"
[tool.uv]
no-build-isolation-package = ["source-distribution"]
"#,
)?;

// Running `uv sync` should fail for the `compile` extra.
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(&filters, context.sync().arg("--extra").arg("compile"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
error: Failed to prepare distributions
Caused by: Failed to fetch wheel: source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz
Caused by: Build backend failed to build wheel through `build_wheel()` with exit status: 1
--- stdout:
--- stderr:
Traceback (most recent call last):
File "<string>", line 8, in <module>
ModuleNotFoundError: No module named 'hatchling'
---
"###);

// Running `uv sync` with `--all-extras` should also fail.
uv_snapshot!(&filters, context.sync().arg("--all-extras"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
error: Failed to prepare distributions
Caused by: Failed to fetch wheel: source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz
Caused by: Build backend failed to build wheel through `build_wheel()` with exit status: 1
--- stdout:
--- stderr:
Traceback (most recent call last):
File "<string>", line 8, in <module>
ModuleNotFoundError: No module named 'hatchling'
---
"###);

// Install the build dependencies.
uv_snapshot!(context.filters(), context.sync().arg("--extra").arg("build"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
Prepared 6 packages in [TIME]
Installed 6 packages in [TIME]
+ hatchling==1.22.4
+ packaging==24.0
+ pathspec==0.12.1
+ pluggy==1.4.0
+ project==0.1.0 (from file://[TEMP_DIR]/)
+ trove-classifiers==2024.3.3
"###);

// Running `uv sync` for the `compile` extra should succeed, and remove the build dependencies.
uv_snapshot!(context.filters(), context.sync().arg("--extra").arg("compile"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
Prepared 1 package in [TIME]
Uninstalled 5 packages in [TIME]
Installed 1 package in [TIME]
- hatchling==1.22.4
- packaging==24.0
- pathspec==0.12.1
- pluggy==1.4.0
+ source-distribution==0.0.1 (from https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz)
- trove-classifiers==2024.3.3
"###);

assert!(context.temp_dir.child("uv.lock").exists());

Ok(())
}

/// Avoid using incompatible versions for build dependencies that are also part of the resolved
/// environment. This is a very subtle issue, but: when locking, we don't enforce platform
/// compatibility. So, if we reuse the resolver state to install, and the install itself has to
Expand Down
4 changes: 1 addition & 3 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -1098,9 +1098,7 @@ uv sync [OPTIONS]

</dd><dt><code>--inexact</code></dt><dd><p>Do not remove extraneous packages present in the environment.</p>

<p>When enabled, uv will make the minimum necessary changes to satisfy the requirements.</p>

<p>By default, syncing will remove any extraneous packages from the environment, unless <code>--no-build-isolation</code> is enabled, in which case extra packages are considered necessary for builds.</p>
<p>When enabled, uv will make the minimum necessary changes to satisfy the requirements. By default, syncing will remove any extraneous packages from the environment</p>

</dd><dt><code>--keyring-provider</code> <i>keyring-provider</i></dt><dd><p>Attempt to use <code>keyring</code> for authentication for index URLs.</p>

Expand Down

0 comments on commit 023acbe

Please sign in to comment.