Skip to content

Commit

Permalink
Add --emit-build-options flag to uv pip compile interface (#4463)
Browse files Browse the repository at this point in the history
## Summary

Closes #4420.
  • Loading branch information
charliermarsh authored Jun 24, 2024
1 parent cba270f commit f073088
Show file tree
Hide file tree
Showing 14 changed files with 148 additions and 13 deletions.
4 changes: 4 additions & 0 deletions PIP_COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,3 +385,7 @@ By default, uv does not write any index URLs to the output file, while `pip-comp
`--index-url` or `--extra-index-url` that does not match the default (PyPI). To include index URLs
in the output file, pass the `--emit-index-url` flag to `uv pip compile`. Unlike `pip-compile`,
uv will include all index URLs when `--emit-index-url` is passed, including the default index URL.

By default, uv does not write any `--no-build` or `--only-binary` options to the output file, unlike
`pip-compile`. To include these options in the output file, pass the `--emit-build-options` flag to
`uv pip compile`.
2 changes: 1 addition & 1 deletion crates/requirements-txt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ enum RequirementsTxtStatement {
NoIndex,
/// `--no-binary`
NoBinary(NoBinary),
/// `only-binary`
/// `--only-binary`
OnlyBinary(NoBuild),
}

Expand Down
7 changes: 7 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,13 @@ pub struct PipCompileArgs {
#[arg(long, overrides_with("emit_find_links"), hide = true)]
pub no_emit_find_links: bool,

/// Include `--no-binary` and `--only-binary` entries in the generated output file.
#[arg(long, overrides_with("no_emit_build_options"))]
pub emit_build_options: bool,

#[arg(long, overrides_with("emit_build_options"), hide = true)]
pub no_emit_build_options: bool,

/// Whether to emit a marker string indicating when it is known that the
/// resulting set of pinned dependencies is valid.
///
Expand Down
14 changes: 12 additions & 2 deletions crates/uv-configuration/src/build_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ impl BuildOptions {
}
}

pub fn no_build(&self, package_name: Option<&PackageName>) -> bool {
pub fn no_build_requirement(&self, package_name: Option<&PackageName>) -> bool {
match package_name {
Some(name) => self.no_build_package(name),
None => self.no_build_all(),
}
}

pub fn no_binary(&self, package_name: Option<&PackageName>) -> bool {
pub fn no_binary_requirement(&self, package_name: Option<&PackageName>) -> bool {
match package_name {
Some(name) => self.no_binary_package(name),
None => self.no_binary_all(),
Expand All @@ -99,6 +99,16 @@ impl BuildOptions {
pub fn no_binary_all(&self) -> bool {
matches!(self.no_binary, NoBinary::All)
}

/// Return the [`NoBuild`] strategy to use.
pub fn no_build(&self) -> &NoBuild {
&self.no_build
}

/// Return the [`NoBinary`] strategy to use.
pub fn no_binary(&self) -> &NoBinary {
&self.no_binary
}
}

#[derive(Debug, Default, Clone, PartialEq, Eq)]
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
// unless all builds are disabled.
if self
.build_options
.no_build(dist.map(distribution_types::Name::name))
.no_build_requirement(dist.map(distribution_types::Name::name))
// We always allow editable builds
&& !matches!(build_kind, BuildKind::Editable)
{
Expand Down
6 changes: 5 additions & 1 deletion crates/uv-distribution/src/distribution_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,11 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
hashes: HashPolicy<'_>,
) -> Result<ArchiveMetadata, Error> {
// Optimization: Skip source dist download when we must not build them anyway.
if self.build_context.build_options().no_build(source.name()) {
if self
.build_context
.build_options()
.no_build_requirement(source.name())
{
if source.is_editable() {
debug!("Allowing build for editable source distribution: {source}");
} else {
Expand Down
6 changes: 5 additions & 1 deletion crates/uv-distribution/src/source/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
debug!("Building: {source}");

// Guard against build of source distributions when disabled.
if self.build_context.build_options().no_build(source.name()) {
if self
.build_context
.build_options()
.no_build_requirement(source.name())
{
if source.is_editable() {
debug!("Allowing build for editable source distribution: {source}");
} else {
Expand Down
1 change: 1 addition & 0 deletions crates/uv-settings/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ pub struct PipOptions {
pub no_emit_package: Option<Vec<PackageName>>,
pub emit_index_url: Option<bool>,
pub emit_find_links: Option<bool>,
pub emit_build_options: Option<bool>,
pub emit_marker_expression: Option<bool>,
pub emit_index_annotation: Option<bool>,
pub annotation_style: Option<AnnotationStyle>,
Expand Down
44 changes: 37 additions & 7 deletions crates/uv/src/commands/pip/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use uv_cache::Cache;
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
use uv_configuration::{
BuildOptions, Concurrency, ConfigSettings, Constraints, ExtrasSpecification, IndexStrategy,
Overrides, PreviewMode, SetupPyStrategy, Upgrade,
NoBinary, NoBuild, Overrides, PreviewMode, SetupPyStrategy, Upgrade,
};
use uv_configuration::{KeyringProviderType, TargetTriple};
use uv_dispatch::BuildDispatch;
Expand Down Expand Up @@ -71,6 +71,7 @@ pub(crate) async fn pip_compile(
custom_compile_command: Option<String>,
include_index_url: bool,
include_find_links: bool,
include_build_options: bool,
include_marker_expression: bool,
include_index_annotation: bool,
index_locations: IndexLocations,
Expand Down Expand Up @@ -539,31 +540,60 @@ pub(crate) async fn pip_compile(
writeln!(writer, "{}", format!("# {relevant_markers}").green())?;
}

// Write the index locations to the output channel.
let mut wrote_index = false;
let mut wrote_preamble = false;

// If necessary, include the `--index-url` and `--extra-index-url` locations.
if include_index_url {
if let Some(index) = index_locations.index() {
writeln!(writer, "--index-url {}", index.verbatim())?;
wrote_index = true;
wrote_preamble = true;
}
for extra_index in index_locations.extra_index() {
writeln!(writer, "--extra-index-url {}", extra_index.verbatim())?;
wrote_index = true;
wrote_preamble = true;
}
}

// If necessary, include the `--find-links` locations.
if include_find_links {
for flat_index in index_locations.flat_index() {
writeln!(writer, "--find-links {flat_index}")?;
wrote_index = true;
wrote_preamble = true;
}
}

// If necessary, include the `--no-binary` and `--only-binary` options.
if include_build_options {
match build_options.no_binary() {
NoBinary::None => {}
NoBinary::All => {
writeln!(writer, "--no-binary :all:")?;
wrote_preamble = true;
}
NoBinary::Packages(packages) => {
for package in packages {
writeln!(writer, "--no-binary {package}")?;
wrote_preamble = true;
}
}
}
match build_options.no_build() {
NoBuild::None => {}
NoBuild::All => {
writeln!(writer, "--only-binary :all:")?;
wrote_preamble = true;
}
NoBuild::Packages(packages) => {
for package in packages {
writeln!(writer, "--only-binary {package}")?;
wrote_preamble = true;
}
}
}
}

// If we wrote an index, add a newline to separate it from the requirements
if wrote_index {
if wrote_preamble {
writeln!(writer)?;
}

Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ async fn run() -> Result<ExitStatus> {
args.settings.custom_compile_command,
args.settings.emit_index_url,
args.settings.emit_find_links,
args.settings.emit_build_options,
args.settings.emit_marker_expression,
args.settings.emit_index_annotation,
args.settings.index_locations,
Expand Down
9 changes: 9 additions & 0 deletions crates/uv/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ impl PipCompileSettings {
no_emit_index_url,
emit_find_links,
no_emit_find_links,
emit_build_options,
no_emit_build_options,
emit_marker_expression,
no_emit_marker_expression,
emit_index_annotation,
Expand Down Expand Up @@ -581,6 +583,7 @@ impl PipCompileSettings {
no_emit_package,
emit_index_url: flag(emit_index_url, no_emit_index_url),
emit_find_links: flag(emit_find_links, no_emit_find_links),
emit_build_options: flag(emit_build_options, no_emit_build_options),
emit_marker_expression: flag(emit_marker_expression, no_emit_marker_expression),
emit_index_annotation: flag(emit_index_annotation, no_emit_index_annotation),
annotation_style,
Expand Down Expand Up @@ -1406,6 +1409,7 @@ pub(crate) struct PipSettings {
pub(crate) no_emit_package: Vec<PackageName>,
pub(crate) emit_index_url: bool,
pub(crate) emit_find_links: bool,
pub(crate) emit_build_options: bool,
pub(crate) emit_marker_expression: bool,
pub(crate) emit_index_annotation: bool,
pub(crate) annotation_style: AnnotationStyle,
Expand Down Expand Up @@ -1460,6 +1464,7 @@ impl PipSettings {
no_emit_package,
emit_index_url,
emit_find_links,
emit_build_options,
emit_marker_expression,
emit_index_annotation,
annotation_style,
Expand Down Expand Up @@ -1595,6 +1600,10 @@ impl PipSettings {
.emit_find_links
.combine(emit_find_links)
.unwrap_or_default(),
emit_build_options: args
.emit_build_options
.combine(emit_build_options)
.unwrap_or_default(),
emit_marker_expression: args
.emit_marker_expression
.combine(emit_marker_expression)
Expand Down
43 changes: 43 additions & 0 deletions crates/uv/tests/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5116,6 +5116,49 @@ fn emit_find_links() -> Result<()> {
Ok(())
}

/// Emit the `--no-binary` and `--only-binary` options.
#[test]
fn emit_build_options() -> Result<()> {
let context = TestContext::new("3.12");
let requirements_in = context.temp_dir.child("requirements.in");
requirements_in.write_str("black==23.10.1")?;

uv_snapshot!(context.compile()
.arg("requirements.in")
.arg("--emit-build-options")
.arg("--only-binary")
.arg("black")
.arg("--no-binary")
.arg(":all:"), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --emit-build-options --only-binary black --no-binary :all:
--no-binary :all:
--only-binary black
black==23.10.1
# via -r requirements.in
click==8.1.7
# via black
mypy-extensions==1.0.0
# via black
packaging==24.0
# via black
pathspec==0.12.1
# via black
platformdirs==4.2.0
# via black
----- stderr -----
Resolved 6 packages in [TIME]
"###
);

Ok(())
}

/// Respect the `--no-index` flag in a `requirements.txt` file.
#[test]
fn no_index_requirements_txt() -> Result<()> {
Expand Down
Loading

0 comments on commit f073088

Please sign in to comment.