From a068b5f9cacfe19aa8694554441905e50b4a2a38 Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Mon, 8 Apr 2024 22:00:49 -0400 Subject: [PATCH 01/12] add index in pip compile output --- crates/distribution-types/src/lib.rs | 22 ++++++++++++++++++++++ crates/distribution-types/src/resolved.rs | 7 +++++++ crates/uv-resolver/src/resolution.rs | 22 +++++++++++++++++++--- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/crates/distribution-types/src/lib.rs b/crates/distribution-types/src/lib.rs index 4b84e6e38a70..6ca5d8b3a0a0 100644 --- a/crates/distribution-types/src/lib.rs +++ b/crates/distribution-types/src/lib.rs @@ -371,6 +371,13 @@ impl Dist { } } + pub fn index(&self) -> Option { + match self { + Self::Built(dist) => dist.index(), + Self::Source(dist) => dist.index(), + } + } + /// Returns the [`File`] instance, if this dist is from a registry with simple json api support pub fn file(&self) -> Option<&File> { match self { @@ -388,6 +395,14 @@ impl Dist { } impl BuiltDist { + pub fn index(&self) -> Option { + match self { + Self::Registry(registry) => Some(registry.index.to_string()), + Self::DirectUrl(_) => None, + Self::Path(_) => None, + } + } + /// Returns the [`File`] instance, if this dist is from a registry with simple json api support pub fn file(&self) -> Option<&File> { match self { @@ -406,6 +421,13 @@ impl BuiltDist { } impl SourceDist { + pub fn index(&self) -> Option { + match self { + Self::Registry(registry) => Some(registry.index.to_string()), + Self::DirectUrl(_) | Self::Git(_) | Self::Path(_) => None, + } + } + /// Returns the [`File`] instance, if this dist is from a registry with simple json api support pub fn file(&self) -> Option<&File> { match self { diff --git a/crates/distribution-types/src/resolved.rs b/crates/distribution-types/src/resolved.rs index 91015e4f389d..8e5260a06eb1 100644 --- a/crates/distribution-types/src/resolved.rs +++ b/crates/distribution-types/src/resolved.rs @@ -31,6 +31,13 @@ impl ResolvedDist { Self::Installed(dist) => dist.is_editable(), } } + + pub fn index(&self) -> Option { + match self { + Self::Installable(dist) => dist.index(), + Self::Installed(_) => None, + } + } } impl ResolvedDistRef<'_> { diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index da93cce16334..096aa9b09e27 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -576,6 +576,13 @@ impl<'a> Node<'a> { Node::Distribution(name, _, _) => NodeKey::Distribution(name), } } + + fn index(&self) -> Option { + match self { + Node::Editable(_, _) => None, + Node::Distribution(_, dist, _) => dist.index(), + } + } } impl Verbatim for Node<'_> { @@ -670,6 +677,12 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { .collect::>(); edges.sort_unstable_by_key(|package| package.name()); + let index = node.index(); + let index_line = if index.is_some() { + format!("\n # from {}", index.unwrap()) + } else { + "".to_string() + }; match self.annotation_style { AnnotationStyle::Line => { if !edges.is_empty() { @@ -679,7 +692,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { .map(|dependency| dependency.name().to_string()) .collect::>() .join(", "); - let comment = format!("# via {deps}").green().to_string(); + let comment = format!("# via {deps}{index_line}").green().to_string(); annotation = Some((separator, comment)); } } @@ -687,7 +700,9 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { [] => {} [edge] => { let separator = "\n"; - let comment = format!(" # via {}", edge.name()).green().to_string(); + let comment = format!(" # via {}{index_line}", edge.name()) + .green() + .to_string(); annotation = Some((separator, comment)); } edges => { @@ -697,7 +712,8 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { .map(|dependency| format!(" # {}", dependency.name())) .collect::>() .join("\n"); - let comment = format!(" # via\n{deps}").green().to_string(); + let comment = + format!(" # via\n{deps}{index_line}").green().to_string(); annotation = Some((separator, comment)); } }, From 296000fc68e5cdf236da098ac49757a98e199553 Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Tue, 9 Apr 2024 20:20:42 -0400 Subject: [PATCH 02/12] clippy --- crates/uv-resolver/src/resolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index 096aa9b09e27..09101744b97e 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -681,7 +681,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { let index_line = if index.is_some() { format!("\n # from {}", index.unwrap()) } else { - "".to_string() + String::new() }; match self.annotation_style { AnnotationStyle::Line => { From d7ef99bd3a3d7965b61cc585a8fdda707e7ac19c Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Tue, 9 Apr 2024 20:36:57 -0400 Subject: [PATCH 03/12] index annotation gated behind a flag --- crates/uv-resolver/src/resolution.rs | 16 ++++++++++------ crates/uv/src/commands/pip_compile.rs | 2 ++ crates/uv/src/main.rs | 5 +++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index 09101744b97e..0984b339f2ff 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -505,6 +505,8 @@ pub struct DisplayResolutionGraph<'a> { /// Whether to include annotations in the output, to indicate which dependency or dependencies /// requested each package. include_annotations: bool, + /// Whether to include indices in the output, to indicate which index was used for each package. + include_indices: bool, /// The style of annotation comments, used to indicate the dependencies that requested each /// package. annotation_style: AnnotationStyle, @@ -518,6 +520,7 @@ impl<'a> From<&'a ResolutionGraph> for DisplayResolutionGraph<'a> { false, false, true, + false, AnnotationStyle::default(), ) } @@ -531,6 +534,7 @@ impl<'a> DisplayResolutionGraph<'a> { show_hashes: bool, include_extras: bool, include_annotations: bool, + include_indices: bool, annotation_style: AnnotationStyle, ) -> DisplayResolutionGraph<'a> { Self { @@ -539,6 +543,7 @@ impl<'a> DisplayResolutionGraph<'a> { show_hashes, include_extras, include_annotations, + include_indices, annotation_style, } } @@ -677,12 +682,11 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { .collect::>(); edges.sort_unstable_by_key(|package| package.name()); - let index = node.index(); - let index_line = if index.is_some() { - format!("\n # from {}", index.unwrap()) - } else { - String::new() - }; + let mut index_line = String::new(); + if self.include_indices && node.index().is_some() { + index_line = format!("\n # from {}", node.index().unwrap()); + } + match self.annotation_style { AnnotationStyle::Line => { if !edges.is_empty() { diff --git a/crates/uv/src/commands/pip_compile.rs b/crates/uv/src/commands/pip_compile.rs index a635c6ed008a..e71b23d09c76 100644 --- a/crates/uv/src/commands/pip_compile.rs +++ b/crates/uv/src/commands/pip_compile.rs @@ -63,6 +63,7 @@ pub(crate) async fn pip_compile( include_extras: bool, include_annotations: bool, include_header: bool, + include_indices: bool, custom_compile_command: Option, include_index_url: bool, include_find_links: bool, @@ -501,6 +502,7 @@ pub(crate) async fn pip_compile( generate_hashes, include_extras, include_annotations, + include_indices, annotation_style, ) )?; diff --git a/crates/uv/src/main.rs b/crates/uv/src/main.rs index 134e11a30f6c..473c2b5af2e7 100644 --- a/crates/uv/src/main.rs +++ b/crates/uv/src/main.rs @@ -335,6 +335,10 @@ struct PipCompileArgs { #[clap(long)] no_header: bool, + /// Include comment annotations indicating the index of each package. + #[clap(long)] + include_indices: bool, + /// Change header comment to reflect custom command wrapping `uv pip compile`. #[clap(long, env = "UV_CUSTOM_COMPILE_COMMAND")] custom_compile_command: Option, @@ -1583,6 +1587,7 @@ async fn run() -> Result { args.no_strip_extras, !args.no_annotate, !args.no_header, + args.include_indices, args.custom_compile_command, args.emit_index_url, args.emit_find_links, From da4fa226e43e1f7b6c27236039cdbee697c6a7dc Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Tue, 9 Apr 2024 20:54:04 -0400 Subject: [PATCH 04/12] ignore clippy --- crates/uv-resolver/src/resolution.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index 0984b339f2ff..b279c16e98fc 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -493,6 +493,7 @@ impl ResolutionGraph { /// A [`std::fmt::Display`] implementation for the resolution graph. #[derive(Debug)] +#[allow(clippy::struct_excessive_bools)] pub struct DisplayResolutionGraph<'a> { /// The underlying graph. resolution: &'a ResolutionGraph, @@ -528,6 +529,7 @@ impl<'a> From<&'a ResolutionGraph> for DisplayResolutionGraph<'a> { impl<'a> DisplayResolutionGraph<'a> { /// Create a new [`DisplayResolutionGraph`] for the given graph. + #[allow(clippy::fn_params_excessive_bools)] pub fn new( underlying: &'a ResolutionGraph, no_emit_packages: &'a [PackageName], From 94b87b3e4c438e8575418d55fe23656d13deaea9 Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Tue, 9 Apr 2024 22:39:33 -0400 Subject: [PATCH 05/12] add the simplest test case --- crates/uv/tests/pip_compile.rs | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 292d4507bdfe..4d459f1c40b7 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -7334,3 +7334,41 @@ fn compile_index_url_fallback_prefer_primary() -> Result<()> { Ok(()) } + +/// Ensure that `--include-indices` prints the index URL for each package. +#[test] +fn include_indices_pypi_org_simple() -> Result<()> { + let context = TestContext::new("3.12"); + + let requirements_in = context.temp_dir.child("requirements.in"); + requirements_in.write_str("requests")?; + + uv_snapshot!(context.compile() + .arg("requirements.in") + .arg("--include-indices"), @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 --include-indices + certifi==2024.2.2 + # via requests + # from https://pypi.org/simple + charset-normalizer==3.3.2 + # via requests + # from https://pypi.org/simple + idna==3.6 + # via requests + # from https://pypi.org/simple + requests==2.31.0 + urllib3==2.2.1 + # via requests + # from https://pypi.org/simple + + ----- stderr ----- + Resolved 5 packages in [TIME] + "### + ); + + Ok(()) +} From f528f617e7db3cffcf79e3147537e87f572575e7 Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Tue, 9 Apr 2024 23:11:38 -0400 Subject: [PATCH 06/12] cleanup + fix index annotation for top level requirement --- crates/uv-resolver/src/resolution.rs | 24 +++++++++++++----------- crates/uv/tests/pip_compile.rs | 1 + 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index b279c16e98fc..69f3eae69ec8 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -684,11 +684,6 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { .collect::>(); edges.sort_unstable_by_key(|package| package.name()); - let mut index_line = String::new(); - if self.include_indices && node.index().is_some() { - index_line = format!("\n # from {}", node.index().unwrap()); - } - match self.annotation_style { AnnotationStyle::Line => { if !edges.is_empty() { @@ -698,7 +693,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { .map(|dependency| dependency.name().to_string()) .collect::>() .join(", "); - let comment = format!("# via {deps}{index_line}").green().to_string(); + let comment = format!("# via {deps}").green().to_string(); annotation = Some((separator, comment)); } } @@ -706,9 +701,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { [] => {} [edge] => { let separator = "\n"; - let comment = format!(" # via {}{index_line}", edge.name()) - .green() - .to_string(); + let comment = format!(" # via {}", edge.name()).green().to_string(); annotation = Some((separator, comment)); } edges => { @@ -718,8 +711,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { .map(|dependency| format!(" # {}", dependency.name())) .collect::>() .join("\n"); - let comment = - format!(" # via\n{deps}{index_line}").green().to_string(); + let comment = format!(" # via\n{deps}").green().to_string(); annotation = Some((separator, comment)); } }, @@ -736,6 +728,16 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { // Write the line as is. writeln!(f, "{line}")?; } + + if self.include_indices && node.index().is_some() { + writeln!( + f, + "{}", + format!(" # from {}", node.index().unwrap()) + .green() + .to_string() + )?; + } } Ok(()) diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 4d459f1c40b7..3c24f1546d3c 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -7361,6 +7361,7 @@ fn include_indices_pypi_org_simple() -> Result<()> { # via requests # from https://pypi.org/simple requests==2.31.0 + # from https://pypi.org/simple urllib3==2.2.1 # via requests # from https://pypi.org/simple From dc0ecc9bfab8c00346e9dd21de35a46701e21430 Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Tue, 9 Apr 2024 23:13:59 -0400 Subject: [PATCH 07/12] clippy --- crates/uv-resolver/src/resolution.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index 69f3eae69ec8..2493c8da98f5 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -733,9 +733,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { writeln!( f, "{}", - format!(" # from {}", node.index().unwrap()) - .green() - .to_string() + format!(" # from {}", node.index().unwrap()).green() )?; } } From da83f301375a5a8df648dedcf4a3182c4c9ce9d4 Mon Sep 17 00:00:00 2001 From: chan Date: Wed, 10 Apr 2024 07:53:02 -0400 Subject: [PATCH 08/12] add another test with multiple indices --- crates/uv/tests/pip_compile.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 3c24f1546d3c..403fa81e500c 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -7373,3 +7373,34 @@ fn include_indices_pypi_org_simple() -> Result<()> { Ok(()) } + +/// `--include-indices` where packages are pulled from two distinct indices. +#[test] +fn include_indices_multiple_indices() -> Result<()> { + let context = TestContext::new("3.12"); + + let requirements_in = context.temp_dir.child("requirements.in"); + requirements_in.write_str("uv\nrequests")?; + + uv_snapshot!(context.compile() + .arg("requirements.in") + .arg("--extra-index-url") + .arg("https://test.pypi.org/simple") + .arg("--include-indices"), @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 --include-indices + requests==2.5.4.1 + # from https://test.pypi.org/simple + uv==0.1.24 + # from https://pypi.org/simple + + ----- stderr ----- + Resolved 2 packages in [TIME] + "### + ); + + Ok(()) +} From 2c50f896ce1cbb0f990e70b6ea554f6acbfcacad Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Wed, 10 Apr 2024 11:00:13 -0400 Subject: [PATCH 09/12] indices -> indexes --- crates/uv-resolver/src/resolution.rs | 10 +++++----- crates/uv/src/commands/pip_compile.rs | 4 ++-- crates/uv/src/main.rs | 4 ++-- crates/uv/tests/pip_compile.rs | 16 ++++++++-------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index 2493c8da98f5..5c4e32989779 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -506,8 +506,8 @@ pub struct DisplayResolutionGraph<'a> { /// Whether to include annotations in the output, to indicate which dependency or dependencies /// requested each package. include_annotations: bool, - /// Whether to include indices in the output, to indicate which index was used for each package. - include_indices: bool, + /// Whether to include indexes in the output, to indicate which index was used for each package. + include_indexes: bool, /// The style of annotation comments, used to indicate the dependencies that requested each /// package. annotation_style: AnnotationStyle, @@ -536,7 +536,7 @@ impl<'a> DisplayResolutionGraph<'a> { show_hashes: bool, include_extras: bool, include_annotations: bool, - include_indices: bool, + include_indexees: bool, annotation_style: AnnotationStyle, ) -> DisplayResolutionGraph<'a> { Self { @@ -545,7 +545,7 @@ impl<'a> DisplayResolutionGraph<'a> { show_hashes, include_extras, include_annotations, - include_indices, + include_indexes: include_indexees, annotation_style, } } @@ -729,7 +729,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { writeln!(f, "{line}")?; } - if self.include_indices && node.index().is_some() { + if self.include_indexes && node.index().is_some() { writeln!( f, "{}", diff --git a/crates/uv/src/commands/pip_compile.rs b/crates/uv/src/commands/pip_compile.rs index e71b23d09c76..0f1af134d345 100644 --- a/crates/uv/src/commands/pip_compile.rs +++ b/crates/uv/src/commands/pip_compile.rs @@ -63,7 +63,7 @@ pub(crate) async fn pip_compile( include_extras: bool, include_annotations: bool, include_header: bool, - include_indices: bool, + include_indexes: bool, custom_compile_command: Option, include_index_url: bool, include_find_links: bool, @@ -502,7 +502,7 @@ pub(crate) async fn pip_compile( generate_hashes, include_extras, include_annotations, - include_indices, + include_indexes, annotation_style, ) )?; diff --git a/crates/uv/src/main.rs b/crates/uv/src/main.rs index 473c2b5af2e7..5c3654f7951c 100644 --- a/crates/uv/src/main.rs +++ b/crates/uv/src/main.rs @@ -337,7 +337,7 @@ struct PipCompileArgs { /// Include comment annotations indicating the index of each package. #[clap(long)] - include_indices: bool, + include_indexes: bool, /// Change header comment to reflect custom command wrapping `uv pip compile`. #[clap(long, env = "UV_CUSTOM_COMPILE_COMMAND")] @@ -1587,7 +1587,7 @@ async fn run() -> Result { args.no_strip_extras, !args.no_annotate, !args.no_header, - args.include_indices, + args.include_indexes, args.custom_compile_command, args.emit_index_url, args.emit_find_links, diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 403fa81e500c..3ff7e0fc950d 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -7335,9 +7335,9 @@ fn compile_index_url_fallback_prefer_primary() -> Result<()> { Ok(()) } -/// Ensure that `--include-indices` prints the index URL for each package. +/// Ensure that `--include-indexes` prints the index URL for each package. #[test] -fn include_indices_pypi_org_simple() -> Result<()> { +fn include_indexes_pypi_org_simple() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); @@ -7345,12 +7345,12 @@ fn include_indices_pypi_org_simple() -> Result<()> { uv_snapshot!(context.compile() .arg("requirements.in") - .arg("--include-indices"), @r###" + .arg("--include-indexes"), @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 --include-indices + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --include-indexes certifi==2024.2.2 # via requests # from https://pypi.org/simple @@ -7374,9 +7374,9 @@ fn include_indices_pypi_org_simple() -> Result<()> { Ok(()) } -/// `--include-indices` where packages are pulled from two distinct indices. +/// `--include-indexes` where packages are pulled from two distinct indexes. #[test] -fn include_indices_multiple_indices() -> Result<()> { +fn include_indexes_multiple_indexes() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); @@ -7386,12 +7386,12 @@ fn include_indices_multiple_indices() -> Result<()> { .arg("requirements.in") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") - .arg("--include-indices"), @r###" + .arg("--include-indexes"), @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 --include-indices + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --include-indexes requests==2.5.4.1 # from https://test.pypi.org/simple uv==0.1.24 From 5c029735a61e72d040b93d4c051938d74a343cb1 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 10 Apr 2024 11:03:28 -0400 Subject: [PATCH 10/12] Use IndexUrl --- crates/distribution-types/src/lib.rs | 15 +++++++++------ crates/distribution-types/src/resolved.rs | 7 ++++--- crates/uv-resolver/src/resolution.rs | 5 +++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/crates/distribution-types/src/lib.rs b/crates/distribution-types/src/lib.rs index 6ca5d8b3a0a0..6c2ad6c81c45 100644 --- a/crates/distribution-types/src/lib.rs +++ b/crates/distribution-types/src/lib.rs @@ -371,7 +371,8 @@ impl Dist { } } - pub fn index(&self) -> Option { + /// Returns the [`IndexUrl`], if the distribution is from a registry. + pub fn index(&self) -> Option<&IndexUrl> { match self { Self::Built(dist) => dist.index(), Self::Source(dist) => dist.index(), @@ -395,15 +396,16 @@ impl Dist { } impl BuiltDist { - pub fn index(&self) -> Option { + /// Returns the [`IndexUrl`], if the distribution is from a registry. + pub fn index(&self) -> Option<&IndexUrl> { match self { - Self::Registry(registry) => Some(registry.index.to_string()), + Self::Registry(registry) => Some(®istry.index), Self::DirectUrl(_) => None, Self::Path(_) => None, } } - /// Returns the [`File`] instance, if this dist is from a registry with simple json api support + /// Returns the [`File`] instance, if this distribution is from a registry. pub fn file(&self) -> Option<&File> { match self { Self::Registry(registry) => Some(®istry.file), @@ -421,9 +423,10 @@ impl BuiltDist { } impl SourceDist { - pub fn index(&self) -> Option { + /// Returns the [`IndexUrl`], if the distribution is from a registry. + pub fn index(&self) -> Option<&IndexUrl> { match self { - Self::Registry(registry) => Some(registry.index.to_string()), + Self::Registry(registry) => Some(®istry.index), Self::DirectUrl(_) | Self::Git(_) | Self::Path(_) => None, } } diff --git a/crates/distribution-types/src/resolved.rs b/crates/distribution-types/src/resolved.rs index 8e5260a06eb1..1f72ba4a08de 100644 --- a/crates/distribution-types/src/resolved.rs +++ b/crates/distribution-types/src/resolved.rs @@ -3,8 +3,8 @@ use std::fmt::{Display, Formatter}; use pep508_rs::PackageName; use crate::{ - Dist, DistributionId, DistributionMetadata, Identifier, InstalledDist, Name, ResourceId, - VersionOrUrl, + Dist, DistributionId, DistributionMetadata, Identifier, IndexUrl, InstalledDist, Name, + ResourceId, VersionOrUrl, }; /// A distribution that can be used for resolution and installation. @@ -32,7 +32,8 @@ impl ResolvedDist { } } - pub fn index(&self) -> Option { + /// Returns the [`IndexUrl`], if the distribution is from a registry. + pub fn index(&self) -> Option<&IndexUrl> { match self { Self::Installable(dist) => dist.index(), Self::Installed(_) => None, diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index 5c4e32989779..9fda0609e14c 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -12,7 +12,7 @@ use pubgrub::type_aliases::SelectedDependencies; use rustc_hash::{FxHashMap, FxHashSet}; use distribution_types::{ - Dist, DistributionMetadata, LocalEditable, Name, PackageId, ResolvedDist, Verbatim, + Dist, DistributionMetadata, IndexUrl, LocalEditable, Name, PackageId, ResolvedDist, Verbatim, VersionOrUrl, }; use once_map::OnceMap; @@ -584,7 +584,8 @@ impl<'a> Node<'a> { } } - fn index(&self) -> Option { + /// Return the [`IndexUrl`] of the distribution, if any. + fn index(&self) -> Option<&IndexUrl> { match self { Node::Editable(_, _) => None, Node::Distribution(_, dist, _) => dist.index(), From 6305a768c3532be0314d8b638833485f98c2c275 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 10 Apr 2024 11:53:32 -0400 Subject: [PATCH 11/12] Rename flag, add more tests --- crates/uv-resolver/src/resolution.rs | 20 +++++----- crates/uv/src/commands/pip_compile.rs | 4 +- crates/uv/src/main.rs | 15 ++++---- crates/uv/tests/pip_compile.rs | 53 +++++++++++++++++++++++---- 4 files changed, 66 insertions(+), 26 deletions(-) diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index 9fda0609e14c..ce8bedf8ca24 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -507,7 +507,7 @@ pub struct DisplayResolutionGraph<'a> { /// requested each package. include_annotations: bool, /// Whether to include indexes in the output, to indicate which index was used for each package. - include_indexes: bool, + include_index_annotation: bool, /// The style of annotation comments, used to indicate the dependencies that requested each /// package. annotation_style: AnnotationStyle, @@ -536,7 +536,7 @@ impl<'a> DisplayResolutionGraph<'a> { show_hashes: bool, include_extras: bool, include_annotations: bool, - include_indexees: bool, + include_index_annotation: bool, annotation_style: AnnotationStyle, ) -> DisplayResolutionGraph<'a> { Self { @@ -545,7 +545,7 @@ impl<'a> DisplayResolutionGraph<'a> { show_hashes, include_extras, include_annotations, - include_indexes: include_indexees, + include_index_annotation, annotation_style, } } @@ -675,6 +675,8 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { // Determine the annotation comment and separator (between comment and requirement). let mut annotation = None; + // If enabled, include annotations to indicate the dependencies that requested each + // package (e.g., `# via mypy`). if self.include_annotations { // Display all dependencies. let mut edges = self @@ -730,12 +732,12 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { writeln!(f, "{line}")?; } - if self.include_indexes && node.index().is_some() { - writeln!( - f, - "{}", - format!(" # from {}", node.index().unwrap()).green() - )?; + // If enabled, include indexes to indicate which index was used for each package (e.g., + // `# from https://pypi.org/simple`). + if self.include_index_annotation { + if let Some(index) = node.index() { + writeln!(f, "{}", format!(" # from {}", index).green())?; + } } } diff --git a/crates/uv/src/commands/pip_compile.rs b/crates/uv/src/commands/pip_compile.rs index 0f1af134d345..b48d33e60e18 100644 --- a/crates/uv/src/commands/pip_compile.rs +++ b/crates/uv/src/commands/pip_compile.rs @@ -63,11 +63,11 @@ pub(crate) async fn pip_compile( include_extras: bool, include_annotations: bool, include_header: bool, - include_indexes: bool, custom_compile_command: Option, include_index_url: bool, include_find_links: bool, include_marker_expression: bool, + include_index_annotation: bool, index_locations: IndexLocations, index_strategy: IndexStrategy, keyring_provider: KeyringProvider, @@ -502,7 +502,7 @@ pub(crate) async fn pip_compile( generate_hashes, include_extras, include_annotations, - include_indexes, + include_index_annotation, annotation_style, ) )?; diff --git a/crates/uv/src/main.rs b/crates/uv/src/main.rs index 5c3654f7951c..8f30598ca54c 100644 --- a/crates/uv/src/main.rs +++ b/crates/uv/src/main.rs @@ -335,9 +335,9 @@ struct PipCompileArgs { #[clap(long)] no_header: bool, - /// Include comment annotations indicating the index of each package. - #[clap(long)] - include_indexes: bool, + /// Choose the style of the annotation comments, which indicate the source of each package. + #[clap(long, default_value_t=AnnotationStyle::Split, value_enum)] + annotation_style: AnnotationStyle, /// Change header comment to reflect custom command wrapping `uv pip compile`. #[clap(long, env = "UV_CUSTOM_COMPILE_COMMAND")] @@ -499,9 +499,10 @@ struct PipCompileArgs { #[clap(long, hide = true)] emit_marker_expression: bool, - /// Choose the style of the annotation comments, which indicate the source of each package. - #[clap(long, default_value_t=AnnotationStyle::Split, value_enum)] - annotation_style: AnnotationStyle, + /// Include comment annotations indicating the index used to resolve each package (e.g., + /// `# from https://pypi.org/simple`). + #[clap(long)] + emit_index_annotation: bool, #[command(flatten)] compat_args: compat::PipCompileCompatArgs, @@ -1587,11 +1588,11 @@ async fn run() -> Result { args.no_strip_extras, !args.no_annotate, !args.no_header, - args.include_indexes, args.custom_compile_command, args.emit_index_url, args.emit_find_links, args.emit_marker_expression, + args.emit_index_annotation, index_urls, args.index_strategy, args.keyring_provider, diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 3ff7e0fc950d..e31bf94b846a 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -7335,9 +7335,9 @@ fn compile_index_url_fallback_prefer_primary() -> Result<()> { Ok(()) } -/// Ensure that `--include-indexes` prints the index URL for each package. +/// Ensure that `--emit-index-annotation` prints the index URL for each package. #[test] -fn include_indexes_pypi_org_simple() -> Result<()> { +fn emit_index_annotation_pypi_org_simple() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); @@ -7345,12 +7345,12 @@ fn include_indexes_pypi_org_simple() -> Result<()> { uv_snapshot!(context.compile() .arg("requirements.in") - .arg("--include-indexes"), @r###" + .arg("--emit-index-annotation"), @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 --include-indexes + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --emit-index-annotation certifi==2024.2.2 # via requests # from https://pypi.org/simple @@ -7374,9 +7374,46 @@ fn include_indexes_pypi_org_simple() -> Result<()> { Ok(()) } -/// `--include-indexes` where packages are pulled from two distinct indexes. +/// Ensure that `--emit-index-annotation` plays nicely with `--annotation-style=line`. #[test] -fn include_indexes_multiple_indexes() -> Result<()> { +fn emit_index_annotation_pypi_org_line() -> Result<()> { + let context = TestContext::new("3.12"); + + let requirements_in = context.temp_dir.child("requirements.in"); + requirements_in.write_str("requests")?; + + uv_snapshot!(context.compile() + .arg("requirements.in") + .arg("--emit-index-annotation") + .arg("--annotation-style") + .arg("line"), @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-index-annotation --annotation-style line + certifi==2024.2.2 # via requests + # from https://pypi.org/simple + charset-normalizer==3.3.2 # via requests + # from https://pypi.org/simple + idna==3.6 # via requests + # from https://pypi.org/simple + requests==2.31.0 + # from https://pypi.org/simple + urllib3==2.2.1 # via requests + # from https://pypi.org/simple + + ----- stderr ----- + Resolved 5 packages in [TIME] + "### + ); + + Ok(()) +} + +/// `--emit-index-annotation` where packages are pulled from two distinct indexes. +#[test] +fn emit_index_annotation_multiple_indexes() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); @@ -7386,12 +7423,12 @@ fn include_indexes_multiple_indexes() -> Result<()> { .arg("requirements.in") .arg("--extra-index-url") .arg("https://test.pypi.org/simple") - .arg("--include-indexes"), @r###" + .arg("--emit-index-annotation"), @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 --include-indexes + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --emit-index-annotation requests==2.5.4.1 # from https://test.pypi.org/simple uv==0.1.24 From aa1c8417efdfb00546057266a5ad91e42600b442 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 10 Apr 2024 11:56:13 -0400 Subject: [PATCH 12/12] Add test --- crates/uv-resolver/src/resolution.rs | 2 +- crates/uv/tests/pip_compile.rs | 41 +++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index ce8bedf8ca24..533fcd0dad7f 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -736,7 +736,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { // `# from https://pypi.org/simple`). if self.include_index_annotation { if let Some(index) = node.index() { - writeln!(f, "{}", format!(" # from {}", index).green())?; + writeln!(f, "{}", format!(" # from {index}").green())?; } } } diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index e31bf94b846a..1f82bc188738 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -7374,9 +7374,48 @@ fn emit_index_annotation_pypi_org_simple() -> Result<()> { Ok(()) } +/// Ensure that `--emit-index-annotation` plays nicely with `--no-annotate`. +/// +/// For now, `--no-annotate` doesn't affect `--emit-index-annotation`, in that we still emit the +/// index annotation, and leave `--no-annotate` to only affect the package _source_ annotations. +#[test] +fn emit_index_annotation_no_annotate() -> Result<()> { + let context = TestContext::new("3.12"); + + let requirements_in = context.temp_dir.child("requirements.in"); + requirements_in.write_str("requests")?; + + uv_snapshot!(context.compile() + .arg("requirements.in") + .arg("--emit-index-annotation") + .arg("--no-annotate"), @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-index-annotation --no-annotate + certifi==2024.2.2 + # from https://pypi.org/simple + charset-normalizer==3.3.2 + # from https://pypi.org/simple + idna==3.6 + # from https://pypi.org/simple + requests==2.31.0 + # from https://pypi.org/simple + urllib3==2.2.1 + # from https://pypi.org/simple + + ----- stderr ----- + Resolved 5 packages in [TIME] + "### + ); + + Ok(()) +} + /// Ensure that `--emit-index-annotation` plays nicely with `--annotation-style=line`. #[test] -fn emit_index_annotation_pypi_org_line() -> Result<()> { +fn emit_index_annotation_line() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in");