Skip to content

Commit

Permalink
Support build constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
blueraft committed Jul 30, 2024
1 parent c0d3da8 commit 0cd5905
Show file tree
Hide file tree
Showing 17 changed files with 337 additions and 4 deletions.
2 changes: 2 additions & 0 deletions crates/bench/benches/uv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,12 @@ mod resolver {
let python_requirement = PythonRequirement::from_interpreter(interpreter);

let options = OptionsBuilder::new().exclude_newer(exclude_newer).build();
let build_constraints = [];

let build_context = BuildDispatch::new(
client,
&cache,
&build_constraints,
interpreter,
&index_locations,
&flat_index,
Expand Down
24 changes: 24 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,14 @@ pub struct PipCompileArgs {
#[arg(long, env = "UV_OVERRIDE", value_delimiter = ' ', value_parser = parse_maybe_file_path)]
pub r#override: Vec<Maybe<PathBuf>>,

/// Constrain build requirement versions using the given requirements files.
///
/// Constraints files are `requirements.txt`-like files that only control the _version_ of a
/// requirement that's installed. However, including a package in a constraints file will _not_
/// trigger the installation of that package.
#[arg(long, short, env = "UV_BUILD_CONSTRAINT", value_delimiter = ' ', value_parser = parse_maybe_file_path)]
pub build_constraint: Vec<Maybe<PathBuf>>,

/// Include optional dependencies from the extra group name; may be provided more than once.
///
/// Only applies to `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
Expand Down Expand Up @@ -817,6 +825,14 @@ pub struct PipSyncArgs {
#[arg(long, short, env = "UV_CONSTRAINT", value_delimiter = ' ', value_parser = parse_maybe_file_path)]
pub constraint: Vec<Maybe<PathBuf>>,

/// Constrain build requirement versions using the given requirements files.
///
/// Constraints files are `requirements.txt`-like files that only control the _version_ of a
/// requirement that's installed. However, including a package in a constraints file will _not_
/// trigger the installation of that package.
#[arg(long, short, env = "UV_BUILD_CONSTRAINT", value_delimiter = ' ', value_parser = parse_maybe_file_path)]
pub build_constraint: Vec<Maybe<PathBuf>>,

#[command(flatten)]
pub installer: InstallerArgs,

Expand Down Expand Up @@ -1084,6 +1100,14 @@ pub struct PipInstallArgs {
#[arg(long, env = "UV_OVERRIDE", value_delimiter = ' ', value_parser = parse_maybe_file_path)]
pub r#override: Vec<Maybe<PathBuf>>,

/// Constrain build requirement versions using the given requirements files.
///
/// Constraints files are `requirements.txt`-like files that only control the _version_ of a
/// requirement that's installed. However, including a package in a constraints file will _not_
/// trigger the installation of that package.
#[arg(long, short, env = "UV_BUILD_CONSTRAINT", value_delimiter = ' ', value_parser = parse_maybe_file_path)]
pub build_constraint: Vec<Maybe<PathBuf>>,

/// Include optional dependencies from the extra group name; may be provided more than once.
///
/// Only applies to `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
Expand Down
4 changes: 4 additions & 0 deletions crates/uv-dev/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,13 @@ pub(crate) async fn build(args: BuildArgs) -> Result<PathBuf> {
)?;
let build_options = BuildOptions::default();

// TODO: support build constraints
let build_constraints = [];

let build_dispatch = BuildDispatch::new(
&client,
&cache,
&build_constraints,
python.interpreter(),
&index_urls,
&flat_index,
Expand Down
23 changes: 19 additions & 4 deletions crates/uv-dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ use uv_build::{SourceBuild, SourceBuildContext};
use uv_cache::Cache;
use uv_client::RegistryClient;
use uv_configuration::{
BuildKind, BuildOptions, ConfigSettings, IndexStrategy, Reinstall, SetupPyStrategy,
BuildKind, BuildOptions, ConfigSettings, Constraints, IndexStrategy, Overrides, Reinstall,
SetupPyStrategy,
};
use uv_configuration::{Concurrency, PreviewMode};
use uv_distribution::DistributionDatabase;
use uv_git::GitResolver;
use uv_installer::{Installer, Plan, Planner, Preparer, SitePackages};
use uv_python::{Interpreter, PythonEnvironment};
use uv_resolver::{
ExcludeNewer, FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, Resolver,
ResolverMarkers,
ExcludeNewer, Exclusions, FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, Preferences,
PythonRequirement, Resolver, ResolverMarkers,
};
use uv_types::{BuildContext, BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};

Expand All @@ -35,6 +36,7 @@ use uv_types::{BuildContext, BuildIsolation, EmptyInstalledPackages, HashStrateg
pub struct BuildDispatch<'a> {
client: &'a RegistryClient,
cache: &'a Cache,
constraints: Constraints,
interpreter: &'a Interpreter,
index_locations: &'a IndexLocations,
index_strategy: IndexStrategy,
Expand All @@ -58,6 +60,7 @@ impl<'a> BuildDispatch<'a> {
pub fn new(
client: &'a RegistryClient,
cache: &'a Cache,
constraints: &'a [Requirement],
interpreter: &'a Interpreter,
index_locations: &'a IndexLocations,
flat_index: &'a FlatIndex,
Expand All @@ -77,6 +80,7 @@ impl<'a> BuildDispatch<'a> {
Self {
client,
cache,
constraints: Constraints::from_requirements(constraints.iter().cloned()),
interpreter,
index_locations,
flat_index,
Expand Down Expand Up @@ -140,8 +144,19 @@ impl<'a> BuildContext for BuildDispatch<'a> {
let python_requirement = PythonRequirement::from_interpreter(self.interpreter);
let markers = self.interpreter.markers();
let tags = self.interpreter.tags()?;
let manifest = Manifest::new(
requirements.to_vec(),
self.constraints.clone(),
Overrides::default(),
Vec::new(),
Preferences::default(),
None,
Exclusions::default(),
Vec::new(),
);

let resolver = Resolver::new(
Manifest::simple(requirements.to_vec()),
manifest,
OptionsBuilder::new()
.exclude_newer(self.exclude_newer)
.index_strategy(self.index_strategy)
Expand Down
16 changes: 16 additions & 0 deletions crates/uv/src/commands/pip/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub(crate) async fn pip_compile(
requirements: &[RequirementsSource],
constraints: &[RequirementsSource],
overrides: &[RequirementsSource],
build_constraints: &[RequirementsSource],
constraints_from_workspace: Vec<Requirement>,
overrides_from_workspace: Vec<Requirement>,
extras: ExtrasSpecification,
Expand Down Expand Up @@ -143,6 +144,20 @@ pub(crate) async fn pip_compile(
)
.collect();

// Read build constraints and overrides
let RequirementsSpecification {
constraints: build_constraints,
overrides: _build_overrides,
..
} = operations::read_requirements(
&[],
build_constraints,
&[],
&ExtrasSpecification::None,
&client_builder,
)
.await?;

// If all the metadata could be statically resolved, validate that every extra was used. If we
// need to resolve metadata via PEP 517, we don't know which extras are used until much later.
if source_trees.is_empty() {
Expand Down Expand Up @@ -304,6 +319,7 @@ pub(crate) async fn pip_compile(
let build_dispatch = BuildDispatch::new(
&client,
&cache,
&build_constraints,
&interpreter,
&index_locations,
&flat_index,
Expand Down
16 changes: 16 additions & 0 deletions crates/uv/src/commands/pip/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub(crate) async fn pip_install(
requirements: &[RequirementsSource],
constraints: &[RequirementsSource],
overrides: &[RequirementsSource],
build_constraints: &[RequirementsSource],
constraints_from_workspace: Vec<Requirement>,
overrides_from_workspace: Vec<Requirement>,
extras: &ExtrasSpecification,
Expand Down Expand Up @@ -105,6 +106,20 @@ pub(crate) async fn pip_install(
)
.await?;

// Read build constraints and overrides
let RequirementsSpecification {
constraints: build_constraints,
overrides: _build_overrides,
..
} = operations::read_requirements(
&[],
build_constraints,
&[],
&ExtrasSpecification::None,
&client_builder,
)
.await?;

let constraints: Vec<Requirement> = constraints
.iter()
.cloned()
Expand Down Expand Up @@ -294,6 +309,7 @@ pub(crate) async fn pip_install(
let build_dispatch = BuildDispatch::new(
&client,
&cache,
&build_constraints,
interpreter,
&index_locations,
&flat_index,
Expand Down
16 changes: 16 additions & 0 deletions crates/uv/src/commands/pip/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use crate::printer::Printer;
pub(crate) async fn pip_sync(
requirements: &[RequirementsSource],
constraints: &[RequirementsSource],
build_constraints: &[RequirementsSource],
reinstall: Reinstall,
link_mode: LinkMode,
compile: bool,
Expand Down Expand Up @@ -103,6 +104,20 @@ pub(crate) async fn pip_sync(
)
.await?;

// Read build constraints and overrides
let RequirementsSpecification {
constraints: build_constraints,
overrides: _build_overrides,
..
} = operations::read_requirements(
&[],
build_constraints,
&[],
&ExtrasSpecification::None,
&client_builder,
)
.await?;

// Validate that the requirements are non-empty.
if !allow_empty_requirements {
let num_requirements = requirements.len() + source_trees.len();
Expand Down Expand Up @@ -240,6 +255,7 @@ pub(crate) async fn pip_sync(
let build_dispatch = BuildDispatch::new(
&client,
&cache,
&build_constraints,
interpreter,
&index_locations,
&flat_index,
Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/commands/project/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,14 @@ pub(crate) async fn add(
FlatIndex::from_entries(entries, Some(&tags), &hasher, &settings.build_options)
};

// TODO: read locked build constraints
let build_constraints = [];

// Create a build dispatch.
let build_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
venv.interpreter(),
&settings.index_locations,
&flat_index,
Expand Down
6 changes: 6 additions & 0 deletions crates/uv/src/commands/project/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,13 @@ async fn do_lock(
// Prefill the index with the lockfile metadata.
let index = lock.to_index(workspace.install_path(), upgrade)?;

// TODO: read locked build constraints
let build_constraints = [];
// Create a build dispatch.
let build_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
interpreter,
index_locations,
&flat_index,
Expand Down Expand Up @@ -472,10 +475,13 @@ async fn do_lock(
None => {
debug!("Starting clean resolution");

// TODO: read locked build constraints
let build_constraints = [];
// Create a build dispatch.
let build_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
interpreter,
index_locations,
&flat_index,
Expand Down
13 changes: 13 additions & 0 deletions crates/uv/src/commands/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,10 +371,13 @@ pub(crate) async fn resolve_names(
let setup_py = SetupPyStrategy::default();
let flat_index = FlatIndex::default();

// TODO: read locked build constraints
let build_constraints = [];
// Create a build dispatch.
let build_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
interpreter,
index_locations,
&flat_index,
Expand Down Expand Up @@ -491,10 +494,13 @@ pub(crate) async fn resolve_environment<'a>(
FlatIndex::from_entries(entries, Some(tags), &hasher, build_options)
};

// TODO: read locked build constraints
let build_constraints = [];
// Create a build dispatch.
let resolve_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
interpreter,
index_locations,
&flat_index,
Expand Down Expand Up @@ -604,10 +610,13 @@ pub(crate) async fn sync_environment(
FlatIndex::from_entries(entries, Some(tags), &hasher, build_options)
};

// TODO: read locked build constraints
let build_constraints = [];
// Create a build dispatch.
let build_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
interpreter,
index_locations,
&flat_index,
Expand Down Expand Up @@ -765,10 +774,14 @@ pub(crate) async fn update_environment(
FlatIndex::from_entries(entries, Some(tags), &hasher, build_options)
};

// TODO: read locked build constraints
let build_constraints = [];

// Create a build dispatch.
let build_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
interpreter,
index_locations,
&flat_index,
Expand Down
3 changes: 3 additions & 0 deletions crates/uv/src/commands/project/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,13 @@ pub(super) async fn do_sync(
FlatIndex::from_entries(entries, Some(tags), &hasher, build_options)
};

// TODO: read locked build constraints
let build_constraints = [];
// Create a build dispatch.
let build_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
venv.interpreter(),
index_locations,
&flat_index,
Expand Down
3 changes: 3 additions & 0 deletions crates/uv/src/commands/venv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,13 @@ async fn venv_impl(
// Do not allow builds
let build_options = BuildOptions::new(NoBinary::None, NoBuild::All);

let build_constraints = [];

// Prep the build context.
let build_dispatch = BuildDispatch::new(
&client,
cache,
&build_constraints,
interpreter,
index_locations,
&flat_index,
Expand Down
Loading

0 comments on commit 0cd5905

Please sign in to comment.