Skip to content

Commit

Permalink
Support no-build-isolation-package (#5894)
Browse files Browse the repository at this point in the history
## Summary

Resolves #5831 

## Test Plan

`cargo test`
  • Loading branch information
blueraft committed Aug 8, 2024
1 parent f7110e0 commit acbd367
Show file tree
Hide file tree
Showing 18 changed files with 468 additions and 16 deletions.
15 changes: 9 additions & 6 deletions crates/uv-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,22 +434,25 @@ impl SourceBuild {
Self::extract_pep517_backend(&source_tree, setup_py, &default_backend)
.map_err(|err| *err)?;

let package_name = project.clone().map(|p| p.name);

// Create a virtual environment, or install into the shared environment if requested.
let venv = match build_isolation {
BuildIsolation::Isolated => uv_virtualenv::create_venv(
let venv = if let Some(venv) = build_isolation.shared_environment(package_name.as_ref()) {
venv.clone()
} else {
uv_virtualenv::create_venv(
temp_dir.path(),
interpreter.clone(),
uv_virtualenv::Prompt::None,
false,
false,
false,
)?,
BuildIsolation::Shared(venv) => venv.clone(),
)?
};

// Setup the build environment. If build isolation is disabled, we assume the build
// environment is already setup.
if build_isolation.is_isolated() {
if build_isolation.is_isolated(package_name.as_ref()) {
let resolved_requirements = Self::get_resolved_requirements(
build_context,
source_build_context,
Expand Down Expand Up @@ -499,7 +502,7 @@ impl SourceBuild {
// Create the PEP 517 build environment. If build isolation is disabled, we assume the build
// environment is already setup.
let runner = PythonRunner::new(concurrent_builds);
if build_isolation.is_isolated() {
if build_isolation.is_isolated(package_name.as_ref()) {
if let Some(pep517_backend) = &pep517_backend {
create_pep517_build_environment(
&runner,
Expand Down
12 changes: 12 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3106,6 +3106,12 @@ pub struct ResolverArgs {
)]
pub no_build_isolation: bool,

/// Disable isolation when building source distributions for a specific package.
///
/// Assumes that the packages' build dependencies specified by PEP 518 are already installed.
#[arg(long, help_heading = "Build options")]
pub no_build_isolation_package: Vec<PackageName>,

#[arg(
long,
overrides_with("no_build_isolation"),
Expand Down Expand Up @@ -3271,6 +3277,12 @@ pub struct ResolverInstallerArgs {
)]
pub no_build_isolation: bool,

/// Disable isolation when building source distributions for a specific package.
///
/// Assumes that the packages' build dependencies specified by PEP 518 are already installed.
#[arg(long, help_heading = "Build options")]
pub no_build_isolation_package: Vec<PackageName>,

#[arg(
long,
overrides_with("no_build_isolation"),
Expand Down
8 changes: 8 additions & 0 deletions crates/uv-cli/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl From<ResolverArgs> for PipOptions {
pre,
config_setting,
no_build_isolation,
no_build_isolation_package,
build_isolation,
exclude_newer,
link_mode,
Expand All @@ -63,6 +64,7 @@ impl From<ResolverArgs> for PipOptions {
config_settings: config_setting
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
no_build_isolation: flag(no_build_isolation, build_isolation),
no_build_isolation_package: Some(no_build_isolation_package),
exclude_newer,
link_mode,
no_sources: if no_sources { Some(true) } else { None },
Expand Down Expand Up @@ -124,6 +126,7 @@ impl From<ResolverInstallerArgs> for PipOptions {
pre,
config_setting,
no_build_isolation,
no_build_isolation_package,
build_isolation,
exclude_newer,
link_mode,
Expand All @@ -148,6 +151,7 @@ impl From<ResolverInstallerArgs> for PipOptions {
config_settings: config_setting
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
no_build_isolation: flag(no_build_isolation, build_isolation),
no_build_isolation_package: Some(no_build_isolation_package),
exclude_newer,
link_mode,
compile_bytecode: flag(compile_bytecode, no_compile_bytecode),
Expand Down Expand Up @@ -195,6 +199,7 @@ pub fn resolver_options(resolver_args: ResolverArgs, build_args: BuildArgs) -> R
pre,
config_setting,
no_build_isolation,
no_build_isolation_package,
build_isolation,
exclude_newer,
link_mode,
Expand Down Expand Up @@ -237,6 +242,7 @@ pub fn resolver_options(resolver_args: ResolverArgs, build_args: BuildArgs) -> R
config_settings: config_setting
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
no_build_isolation: flag(no_build_isolation, build_isolation),
no_build_isolation_package: Some(no_build_isolation_package),
exclude_newer,
link_mode,
no_build: flag(no_build, build),
Expand Down Expand Up @@ -267,6 +273,7 @@ pub fn resolver_installer_options(
pre,
config_setting,
no_build_isolation,
no_build_isolation_package,
build_isolation,
exclude_newer,
link_mode,
Expand Down Expand Up @@ -313,6 +320,7 @@ pub fn resolver_installer_options(
config_settings: config_setting
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
no_build_isolation: flag(no_build_isolation, build_isolation),
no_build_isolation_package: Some(no_build_isolation_package),
exclude_newer,
link_mode,
compile_bytecode: flag(compile_bytecode, no_compile_bytecode),
Expand Down
25 changes: 25 additions & 0 deletions crates/uv-settings/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ pub struct ResolverOptions {
pub no_binary: Option<bool>,
pub no_binary_package: Option<Vec<PackageName>>,
pub no_build_isolation: Option<bool>,
pub no_build_isolation_package: Option<Vec<PackageName>>,
pub no_sources: Option<bool>,
}

Expand Down Expand Up @@ -350,6 +351,18 @@ pub struct ResolverInstallerOptions {
"#
)]
pub no_build_isolation: Option<bool>,
/// Disable isolation when building source distributions for a specific package.
///
/// Assumes that the packages' build dependencies specified by [PEP 518](https://peps.python.org/pep-0518/)
/// are already installed.
#[option(
default = "[]",
value_type = "Vec<PackageName>",
example = r#"
no-build-isolation-package = ["package1", "package2"]
"#
)]
pub no_build_isolation_package: Option<Vec<PackageName>>,
/// Limit candidate packages to those that were uploaded prior to the given date.
///
/// Accepts both [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) timestamps (e.g.,
Expand Down Expand Up @@ -717,6 +730,18 @@ pub struct PipOptions {
"#
)]
pub no_build_isolation: Option<bool>,
/// Disable isolation when building source distributions for a specific package.
///
/// Assumes that the packages' build dependencies specified by [PEP 518](https://peps.python.org/pep-0518/)
/// are already installed.
#[option(
default = "[]",
value_type = "Vec<PackageName>",
example = r#"
no-build-isolation-package = ["package1", "package2"]
"#
)]
pub no_build_isolation_package: Option<Vec<PackageName>>,
/// Validate the Python environment, to detect packages with missing dependencies and other
/// issues.
#[option(
Expand Down
29 changes: 26 additions & 3 deletions crates/uv-types/src/builds.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use pep508_rs::PackageName;
use uv_python::PythonEnvironment;

/// Whether to enforce build isolation when building source distributions.
Expand All @@ -6,11 +7,33 @@ pub enum BuildIsolation<'a> {
#[default]
Isolated,
Shared(&'a PythonEnvironment),
SharedPackage(&'a PythonEnvironment, &'a [PackageName]),
}

impl<'a> BuildIsolation<'a> {
/// Returns `true` if build isolation is enforced.
pub fn is_isolated(&self) -> bool {
matches!(self, Self::Isolated)
/// Returns `true` if build isolation is enforced for the given package name.
pub fn is_isolated(&self, package: Option<&PackageName>) -> bool {
match self {
Self::Isolated => true,
Self::Shared(_) => false,
Self::SharedPackage(_, packages) => {
package.map_or(true, |package| !packages.iter().any(|p| p == package))
}
}
}

/// Returns the shared environment for a given package, if build isolation is not enforced.
pub fn shared_environment(&self, package: Option<&PackageName>) -> Option<&PythonEnvironment> {
match self {
Self::Isolated => None,
Self::Shared(env) => Some(env),
Self::SharedPackage(env, packages) => {
if package.is_some_and(|package| packages.iter().any(|p| p == package)) {
Some(env)
} else {
None
}
}
}
}
}
6 changes: 5 additions & 1 deletion crates/uv/src/commands/pip/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub(crate) async fn pip_compile(
config_settings: ConfigSettings,
connectivity: Connectivity,
no_build_isolation: bool,
no_build_isolation_package: Vec<PackageName>,
build_options: BuildOptions,
python_version: Option<PythonVersion>,
python_platform: Option<TargetTriple>,
Expand Down Expand Up @@ -303,8 +304,11 @@ pub(crate) async fn pip_compile(
let build_isolation = if no_build_isolation {
environment = PythonEnvironment::from_interpreter(interpreter.clone());
BuildIsolation::Shared(&environment)
} else {
} else if no_build_isolation_package.is_empty() {
BuildIsolation::Isolated
} else {
environment = PythonEnvironment::from_interpreter(interpreter.clone());
BuildIsolation::SharedPackage(&environment, &no_build_isolation_package)
};

let build_dispatch = BuildDispatch::new(
Expand Down
6 changes: 5 additions & 1 deletion crates/uv/src/commands/pip/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::fmt::Write;
use anstream::eprint;
use itertools::Itertools;
use owo_colors::OwoColorize;
use pep508_rs::PackageName;
use tracing::{debug, enabled, Level};

use distribution_types::{IndexLocations, Resolution, UnresolvedRequirementSpecification};
Expand Down Expand Up @@ -59,6 +60,7 @@ pub(crate) async fn pip_install(
connectivity: Connectivity,
config_settings: &ConfigSettings,
no_build_isolation: bool,
no_build_isolation_package: Vec<PackageName>,
build_options: BuildOptions,
python_version: Option<PythonVersion>,
python_platform: Option<TargetTriple>,
Expand Down Expand Up @@ -289,8 +291,10 @@ pub(crate) async fn pip_install(
// Determine whether to enable build isolation.
let build_isolation = if no_build_isolation {
BuildIsolation::Shared(&environment)
} else {
} else if no_build_isolation_package.is_empty() {
BuildIsolation::Isolated
} else {
BuildIsolation::SharedPackage(&environment, &no_build_isolation_package)
};

// Initialize any shared state.
Expand Down
6 changes: 5 additions & 1 deletion crates/uv/src/commands/pip/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::fmt::Write;
use anstream::eprint;
use anyhow::Result;
use owo_colors::OwoColorize;
use pep508_rs::PackageName;
use tracing::debug;

use distribution_types::{IndexLocations, Resolution};
Expand Down Expand Up @@ -51,6 +52,7 @@ pub(crate) async fn pip_sync(
connectivity: Connectivity,
config_settings: &ConfigSettings,
no_build_isolation: bool,
no_build_isolation_package: Vec<PackageName>,
build_options: BuildOptions,
python_version: Option<PythonVersion>,
python_platform: Option<TargetTriple>,
Expand Down Expand Up @@ -229,8 +231,10 @@ pub(crate) async fn pip_sync(
// Determine whether to enable build isolation.
let build_isolation = if no_build_isolation {
BuildIsolation::Shared(&environment)
} else {
} else if no_build_isolation_package.is_empty() {
BuildIsolation::Isolated
} else {
BuildIsolation::SharedPackage(&environment, &no_build_isolation_package)
};

// Initialize any shared state.
Expand Down
6 changes: 5 additions & 1 deletion crates/uv/src/commands/project/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ async fn do_lock(
prerelease,
config_setting,
no_build_isolation,
no_build_isolation_package,
exclude_newer,
link_mode,
upgrade,
Expand Down Expand Up @@ -298,8 +299,11 @@ async fn do_lock(
let build_isolation = if no_build_isolation {
environment = PythonEnvironment::from_interpreter(interpreter.clone());
BuildIsolation::Shared(&environment)
} else {
} else if no_build_isolation_package.is_empty() {
BuildIsolation::Isolated
} else {
environment = PythonEnvironment::from_interpreter(interpreter.clone());
BuildIsolation::SharedPackage(&environment, no_build_isolation_package)
};

let options = OptionsBuilder::new()
Expand Down
17 changes: 14 additions & 3 deletions crates/uv/src/commands/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ pub(crate) async fn resolve_names(
prerelease: _,
config_setting,
no_build_isolation,
no_build_isolation_package,
exclude_newer,
link_mode,
compile_bytecode: _,
Expand Down Expand Up @@ -436,8 +437,11 @@ pub(crate) async fn resolve_names(
let build_isolation = if *no_build_isolation {
environment = PythonEnvironment::from_interpreter(interpreter.clone());
BuildIsolation::Shared(&environment)
} else {
} else if no_build_isolation_package.is_empty() {
BuildIsolation::Isolated
} else {
environment = PythonEnvironment::from_interpreter(interpreter.clone());
BuildIsolation::SharedPackage(&environment, no_build_isolation_package)
};

// TODO(charlie): These are all default values. We should consider whether we want to make them
Expand Down Expand Up @@ -505,6 +509,7 @@ pub(crate) async fn resolve_environment<'a>(
prerelease,
config_setting,
no_build_isolation,
no_build_isolation_package,
exclude_newer,
link_mode,
upgrade: _,
Expand Down Expand Up @@ -548,8 +553,11 @@ pub(crate) async fn resolve_environment<'a>(
let build_isolation = if no_build_isolation {
environment = PythonEnvironment::from_interpreter(interpreter.clone());
BuildIsolation::Shared(&environment)
} else {
} else if no_build_isolation_package.is_empty() {
BuildIsolation::Isolated
} else {
environment = PythonEnvironment::from_interpreter(interpreter.clone());
BuildIsolation::SharedPackage(&environment, no_build_isolation_package)
};

let options = OptionsBuilder::new()
Expand Down Expand Up @@ -780,6 +788,7 @@ pub(crate) async fn update_environment(
prerelease,
config_setting,
no_build_isolation,
no_build_isolation_package,
exclude_newer,
link_mode,
compile_bytecode,
Expand Down Expand Up @@ -848,8 +857,10 @@ pub(crate) async fn update_environment(
// Determine whether to enable build isolation.
let build_isolation = if *no_build_isolation {
BuildIsolation::Shared(&venv)
} else {
} else if no_build_isolation_package.is_empty() {
BuildIsolation::Isolated
} else {
BuildIsolation::SharedPackage(&venv, no_build_isolation_package)
};

let options = OptionsBuilder::new()
Expand Down
Loading

0 comments on commit acbd367

Please sign in to comment.