From bc963d13cb5b1e0ca0783f62848d3ff5d93f3dda Mon Sep 17 00:00:00 2001 From: Tom Parker-Shemilt Date: Thu, 9 May 2024 04:19:22 +0100 Subject: [PATCH] Annotate sources of requirements (#3269) ## Summary Fixes https://github.com/astral-sh/uv/issues/1343. This is kinda a first draft at the moment, but does at least mostly work locally (barring some bits of the test suite that seem to not work for me in general). ## Test Plan Mostly running the existing tests and checking the revised output is sane ## Outstanding issues Most of these come down to "AFAIK, the existing tools don't support these patterns, but `uv` does" and so I'm not sure there's an existing good answer here! Most of the answers so far are "whatever was easiest to build" - [x] ~~Is "-r pyproject.toml" correct? Should it show something else or get skipped entirely~~ No it wasn't. Fixed in 3044fa8b86791369a3c468ced585753428e70b1b - [ ] If the requirements file is stdin, that just gets skipped. Should it be recorded? - [ ] Overrides get shown as "--override". Correct? - [x] ~~Some of the tests (e.g. `dependency_excludes_non_contiguous_range_of_compatible_versions`) make assumptions about the order of package versions being outputted, which this PR breaks. I'm not sure if the text is fairly arbitrary and can be replaced or whether the behaviour needs fixing?~~ - fixed by removing the custom pubgrub PartialEq/Hash - [ ] Are all the `TrackedFromStr` et al changes needed, or is there an easier way? I don't think so, I think it's necessary to track these sort of things fairly comprehensively to make this feature work, and this sort of invasive change feels necessary, but happy to be proved wrong there :) - [x] ~~If you have a requirement coming in from two or more different requirements files only one turns up. I've got a closed-source example for this (can go into more detail if needed), mostly consisting of a complicated set of common deps creating a larger set. It's a rarer case, but worth considering.~~ 042432b200395d498b4517121a9fb25f1bbda8ca - [ ] Doesn't add annotations for `setup.py` yet - This is pretty hard, as the correct location to insert the path is `crates/pypi-types/src/metadata.rs`'s `parse_pkg_info`, which as it's based off a source distribution has entirely thrown away such matters as "where did this package requirement get built from". Could add "`built package name`" as a dep, but that's a little odd. --- crates/distribution-types/src/annotation.rs | 52 ++ crates/distribution-types/src/lib.rs | 2 + crates/distribution-types/src/requirement.rs | 2 + crates/distribution-types/src/resolution.rs | 1 + .../src/specified_requirement.rs | 2 + crates/pep508-rs/src/lib.rs | 17 +- crates/pep508-rs/src/unnamed.rs | 11 +- crates/requirements-txt/src/lib.rs | 643 +++++++++++------- crates/requirements-txt/src/requirement.rs | 13 +- ...nts_txt__test__line-endings-basic.txt.snap | 36 + ..._test__line-endings-constraints-a.txt.snap | 12 + ..._test__line-endings-constraints-b.txt.snap | 12 + ..._txt__test__line-endings-editable.txt.snap | 12 + ...xt__test__line-endings-for-poetry.txt.snap | 24 + ...txt__test__line-endings-include-a.txt.snap | 12 + ...txt__test__line-endings-include-b.txt.snap | 6 + ...__line-endings-poetry-with-hashes.txt.snap | 30 + ...nts_txt__test__line-endings-small.txt.snap | 12 + ...xt__test__line-endings-whitespace.txt.snap | 12 + ...quirements_txt__test__parse-basic.txt.snap | 36 + ...ts_txt__test__parse-constraints-a.txt.snap | 12 + ...ts_txt__test__parse-constraints-b.txt.snap | 12 + ...ments_txt__test__parse-for-poetry.txt.snap | 24 + ...ements_txt__test__parse-include-a.txt.snap | 12 + ...ements_txt__test__parse-include-b.txt.snap | 6 + ...t__test__parse-poetry-with-hashes.txt.snap | 30 + ...quirements_txt__test__parse-small.txt.snap | 12 + ...ts_txt__test__parse-unix-bare-url.txt.snap | 18 + ...ments_txt__test__parse-whitespace.txt.snap | 12 + ...txt__test__parse-windows-bare-url.txt.snap | 18 + crates/uv-dev/src/resolve_many.rs | 1 + crates/uv-fs/src/path.rs | 28 +- crates/uv-installer/src/site_packages.rs | 2 + crates/uv-requirements/src/pyproject.rs | 10 +- crates/uv-requirements/src/specification.rs | 30 +- crates/uv-requirements/src/unnamed.rs | 10 +- crates/uv-resolver/src/resolution.rs | 46 +- crates/uv/src/commands/pip_compile.rs | 75 +- crates/uv/src/commands/pip_install.rs | 8 +- crates/uv/src/commands/pip_sync.rs | 7 +- crates/uv/tests/pip_compile.rs | 303 ++++++++- crates/uv/tests/pip_compile_scenarios.rs | 3 + 42 files changed, 1295 insertions(+), 331 deletions(-) create mode 100644 crates/distribution-types/src/annotation.rs diff --git a/crates/distribution-types/src/annotation.rs b/crates/distribution-types/src/annotation.rs new file mode 100644 index 000000000..54b107979 --- /dev/null +++ b/crates/distribution-types/src/annotation.rs @@ -0,0 +1,52 @@ +use serde::{Deserialize, Deserializer, Serialize}; +use std::path::PathBuf; +use uv_fs::Simplified; + +/// Source of a dependency, e.g., a `-r requirements.txt` file. +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)] +pub enum SourceAnnotation { + /// A `pyproject.toml` file. + PyProject { + path: PathBuf, + project_name: Option, + }, + /// A `-c constraints.txt` file. + Constraint(PathBuf), + /// An `--override overrides.txt` file. + Override(PathBuf), + /// A `-r requirements.txt` file. + Requirement(PathBuf), +} + +impl<'de> Deserialize<'de> for SourceAnnotation { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(SourceAnnotation::Requirement(PathBuf::from(s))) + } +} + +impl std::fmt::Display for SourceAnnotation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Requirement(path) => { + write!(f, "-r {}", path.user_display()) + } + Self::Constraint(path) => { + write!(f, "-c {}", path.user_display()) + } + Self::Override(path) => { + write!(f, "--override {}", path.user_display()) + } + Self::PyProject { path, project_name } => { + if let Some(project_name) = project_name { + write!(f, "{} ({})", project_name, path.user_display()) + } else { + write!(f, "{}", path.user_display()) + } + } + } + } +} diff --git a/crates/distribution-types/src/lib.rs b/crates/distribution-types/src/lib.rs index b59d07268..ad6d75a5d 100644 --- a/crates/distribution-types/src/lib.rs +++ b/crates/distribution-types/src/lib.rs @@ -44,6 +44,7 @@ use pep440_rs::Version; use pep508_rs::{Pep508Url, Scheme, VerbatimUrl}; use uv_normalize::PackageName; +pub use crate::annotation::*; pub use crate::any::*; pub use crate::buildable::*; pub use crate::cached::*; @@ -62,6 +63,7 @@ pub use crate::resolved::*; pub use crate::specified_requirement::*; pub use crate::traits::*; +mod annotation; mod any; mod buildable; mod cached; diff --git a/crates/distribution-types/src/requirement.rs b/crates/distribution-types/src/requirement.rs index efbb94618..95f78d665 100644 --- a/crates/distribution-types/src/requirement.rs +++ b/crates/distribution-types/src/requirement.rs @@ -28,6 +28,7 @@ pub struct Requirement { pub extras: Vec, pub marker: Option, pub source: RequirementSource, + pub path: Option, } impl Requirement { @@ -62,6 +63,7 @@ impl Requirement { extras: requirement.extras, marker: requirement.marker, source, + path: requirement.path, }) } } diff --git a/crates/distribution-types/src/resolution.rs b/crates/distribution-types/src/resolution.rs index 8b5290155..38391c4f7 100644 --- a/crates/distribution-types/src/resolution.rs +++ b/crates/distribution-types/src/resolution.rs @@ -139,6 +139,7 @@ impl From<&ResolvedDist> for Requirement { extras: vec![], marker: None, source, + path: None, } } } diff --git a/crates/distribution-types/src/specified_requirement.rs b/crates/distribution-types/src/specified_requirement.rs index 6d0ea8b27..d750f4381 100644 --- a/crates/distribution-types/src/specified_requirement.rs +++ b/crates/distribution-types/src/specified_requirement.rs @@ -14,6 +14,8 @@ pub struct UnresolvedRequirementSpecification { pub requirement: UnresolvedRequirement, /// Hashes of the downloadable packages. pub hashes: Vec, + /// Path of the source of the requirement + pub path: Option, } /// A requirement read from a `requirements.txt` or `pyproject.toml` file. diff --git a/crates/pep508-rs/src/lib.rs b/crates/pep508-rs/src/lib.rs index 335e81737..b181baad2 100644 --- a/crates/pep508-rs/src/lib.rs +++ b/crates/pep508-rs/src/lib.rs @@ -26,7 +26,7 @@ use std::fmt::{Debug, Display, Formatter}; use std::hash::{Hash, Hasher}; #[cfg(feature = "pyo3")] use std::ops::Deref; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str::FromStr; #[cfg(feature = "pyo3")] @@ -148,6 +148,16 @@ pub struct Requirement { /// `requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8"`. /// Those are a nested and/or tree. pub marker: Option, + /// The source file containing the requirement. + pub path: Option, +} + +impl Requirement { + /// Set the source file containing the requirement. + #[must_use] + pub fn with_source(self, path: Option) -> Self { + Self { path, ..self } + } } impl Display for Requirement { @@ -482,6 +492,7 @@ impl Requirement { extras, version_or_url, marker, + path, } = self; Requirement { name, @@ -494,6 +505,7 @@ impl Requirement { Some(VersionOrUrl::Url(url)) => Some(VersionOrUrl::Url(U::from(url))), }, marker, + path, } } } @@ -1017,6 +1029,7 @@ fn parse_pep508_requirement( extras, version_or_url: requirement_kind, marker, + path: None, }) } @@ -1158,6 +1171,7 @@ mod tests { operator: MarkerOperator::LessThan, r_value: MarkerValue::QuotedString("2.7".to_string()), })), + path: None, }; assert_eq!(requests, expected); } @@ -1383,6 +1397,7 @@ mod tests { extras: vec![], marker: None, version_or_url: Some(VersionOrUrl::Url(Url::parse(url).unwrap())), + path: None, }; assert_eq!(pip_url, expected); } diff --git a/crates/pep508-rs/src/unnamed.rs b/crates/pep508-rs/src/unnamed.rs index 9b9f101f2..aa7d9c5fe 100644 --- a/crates/pep508-rs/src/unnamed.rs +++ b/crates/pep508-rs/src/unnamed.rs @@ -1,5 +1,5 @@ use std::fmt::{Display, Formatter}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str::FromStr; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -30,6 +30,8 @@ pub struct UnnamedRequirement { /// `requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8"`. /// Those are a nested and/or tree. pub marker: Option, + /// The source file containing the requirement. + pub path: Option, } impl UnnamedRequirement { @@ -41,6 +43,12 @@ impl UnnamedRequirement { true } } + + /// Set the source file containing the requirement. + #[must_use] + pub fn with_source(self, path: Option) -> Self { + Self { path, ..self } + } } impl Display for UnnamedRequirement { @@ -159,6 +167,7 @@ fn parse_unnamed_requirement( url, extras, marker, + path: None, }) } diff --git a/crates/requirements-txt/src/lib.rs b/crates/requirements-txt/src/lib.rs index da68cd5fb..4d71ed961 100644 --- a/crates/requirements-txt/src/lib.rs +++ b/crates/requirements-txt/src/lib.rs @@ -167,6 +167,9 @@ pub struct EditableRequirement { pub url: VerbatimUrl, pub extras: Vec, pub path: PathBuf, + + /// Path of the original file (where existing) + pub source: Option, } impl EditableRequirement { @@ -191,6 +194,7 @@ impl EditableRequirement { /// We disallow URLs with schemes other than `file://` (e.g., `https://...`). pub fn parse( given: &str, + source: Option<&Path>, working_dir: impl AsRef, ) -> Result { // Identify the extras. @@ -265,7 +269,12 @@ impl EditableRequirement { // Add the verbatim representation of the URL to the `VerbatimUrl`. let url = url.with_given(requirement.to_string()); - Ok(Self { url, extras, path }) + Ok(Self { + url, + extras, + path, + source: source.map(Path::to_path_buf), + }) } /// Identify the extras in an editable URL (e.g., `../editable[dev]`). @@ -305,6 +314,8 @@ pub struct RequirementEntry { pub requirement: RequirementsTxtRequirement, /// Hashes of the downloadable packages. pub hashes: Vec, + /// Path of the original file (where existing) + pub path: Option, } // We place the impl here instead of next to `UnresolvedRequirementSpecification` because @@ -324,6 +335,7 @@ impl TryFrom for UnresolvedRequirementSpecification { } }, hashes: value.hashes, + path: value.path, }) } } @@ -402,12 +414,18 @@ impl RequirementsTxt { })?; let requirements_dir = requirements_txt.parent().unwrap_or(working_dir); - let data = Self::parse_inner(&content, working_dir, requirements_dir, client_builder) - .await - .map_err(|err| RequirementsTxtFileError { - file: requirements_txt.to_path_buf(), - error: err, - })?; + let data = Self::parse_inner( + &content, + working_dir, + requirements_dir, + client_builder, + requirements_txt, + ) + .await + .map_err(|err| RequirementsTxtFileError { + file: requirements_txt.to_path_buf(), + error: err, + })?; if data == Self::default() { warn_user!( "Requirements file {} does not contain any dependencies", @@ -429,11 +447,12 @@ impl RequirementsTxt { working_dir: &Path, requirements_dir: &Path, client_builder: &BaseClientBuilder<'_>, + requirements_txt: &Path, ) -> Result { let mut s = Scanner::new(content); let mut data = Self::default(); - while let Some(statement) = parse_entry(&mut s, content, working_dir)? { + while let Some(statement) = parse_entry(&mut s, content, working_dir, requirements_txt)? { match statement { RequirementsTxtStatement::Requirements { filename, @@ -511,7 +530,9 @@ impl RequirementsTxt { } } } - data.constraints.extend(sub_constraints.constraints); + for constraint in sub_constraints.constraints { + data.constraints.push(constraint); + } } RequirementsTxtStatement::RequirementEntry(requirement_entry) => { data.requirements.push(requirement_entry); @@ -585,6 +606,7 @@ fn parse_entry( s: &mut Scanner, content: &str, working_dir: &Path, + requirements_txt: &Path, ) -> Result, RequirementsTxtParserError> { // Eat all preceding whitespace, this may run us to the end of file eat_wrappable_whitespace(s); @@ -613,8 +635,9 @@ fn parse_entry( } } else if s.eat_if("-e") || s.eat_if("--editable") { let path_or_url = parse_value(content, s, |c: char| !['\n', '\r', '#'].contains(&c))?; - let editable_requirement = EditableRequirement::parse(path_or_url, working_dir) - .map_err(|err| err.with_offset(start))?; + let editable_requirement = + EditableRequirement::parse(path_or_url, Some(requirements_txt), working_dir) + .map_err(|err| err.with_offset(start))?; RequirementsTxtStatement::EditableRequirement(editable_requirement) } else if s.eat_if("-i") || s.eat_if("--index-url") { let given = parse_value(content, s, |c: char| !['\n', '\r', '#'].contains(&c))?; @@ -676,10 +699,17 @@ fn parse_entry( })?; RequirementsTxtStatement::OnlyBinary(NoBuild::from_arg(specifier)) } else if s.at(char::is_ascii_alphanumeric) || s.at(|char| matches!(char, '.' | '/' | '$')) { - let (requirement, hashes) = parse_requirement_and_hashes(s, content, working_dir)?; + let source = if requirements_txt == Path::new("-") { + None + } else { + Some(requirements_txt) + }; + + let (requirement, hashes) = parse_requirement_and_hashes(s, content, source, working_dir)?; RequirementsTxtStatement::RequirementEntry(RequirementEntry { requirement, hashes, + path: requirements_txt.to_str().map(ToString::to_string), }) } else if let Some(char) = s.peek() { let (line, column) = calculate_row_column(content, s.cursor()); @@ -738,6 +768,7 @@ fn eat_trailing_line(content: &str, s: &mut Scanner) -> Result<(), RequirementsT fn parse_requirement_and_hashes( s: &mut Scanner, content: &str, + source: Option<&Path>, working_dir: &Path, ) -> Result<(RequirementsTxtRequirement, Vec), RequirementsTxtParserError> { // PEP 508 requirement @@ -795,8 +826,9 @@ fn parse_requirement_and_hashes( } } - let requirement = - RequirementsTxtRequirement::parse(requirement, working_dir).map_err(|err| match err { + let requirement = RequirementsTxtRequirement::parse(requirement, working_dir) + .map(|requirement| requirement.with_source(source.map(Path::to_path_buf))) + .map_err(|err| match err { RequirementsTxtRequirementError::ParsedUrl(err) => { RequirementsTxtParserError::ParsedUrl { source: err, @@ -1332,7 +1364,11 @@ mod test { use crate::{calculate_row_column, EditableRequirement, RequirementsTxt}; fn workspace_test_data_dir() -> PathBuf { - PathBuf::from("./test-data").canonicalize().unwrap() + Path::new("./test-data").simple_canonicalize().unwrap() + } + + fn safe_filter_path(path: &Path) -> String { + regex::escape(&path.simplified_display().to_string()).replace(r"\\", r"(\\\\|/)") } #[test_case(Path::new("basic.txt"))] @@ -1350,13 +1386,23 @@ mod test { let working_dir = workspace_test_data_dir().join("requirements-txt"); let requirements_txt = working_dir.join(path); - let actual = - RequirementsTxt::parse(requirements_txt, &working_dir, &BaseClientBuilder::new()) - .await - .unwrap(); + let actual = RequirementsTxt::parse( + requirements_txt.clone(), + &working_dir, + &BaseClientBuilder::new(), + ) + .await + .unwrap(); let snapshot = format!("parse-{}", path.to_string_lossy()); - insta::assert_debug_snapshot!(snapshot, actual); + let filter_path = safe_filter_path(&working_dir); + let filters = vec![(filter_path.as_str(), ""), (r"\\\\", "/")]; + + insta::with_settings!({ + filters => filters, + }, { + insta::assert_debug_snapshot!(snapshot, actual); + }); } #[test_case(Path::new("basic.txt"))] @@ -1401,7 +1447,14 @@ mod test { .unwrap(); let snapshot = format!("line-endings-{}", path.to_string_lossy()); - insta::assert_debug_snapshot!(snapshot, actual); + let filter_path = safe_filter_path(temp_dir.path()); + let filters = vec![(filter_path.as_str(), ""), (r"\\\\", "/")]; + + insta::with_settings!({ + filters => filters, + }, { + insta::assert_debug_snapshot!(snapshot, actual); + }); } #[cfg(unix)] @@ -1439,13 +1492,8 @@ mod test { .unwrap(); let snapshot = format!("parse-windows-{}", path.to_string_lossy()); - let pattern = regex::escape( - &working_dir - .simplified_display() - .to_string() - .replace('\\', "/"), - ); - let filters = vec![(pattern.as_str(), "[WORKSPACE_DIR]")]; + let filter_path = safe_filter_path(&working_dir); + let filters = vec![(filter_path.as_str(), "[WORKSPACE_DIR]"), (r"\\\\", "/")]; insta::with_settings!({ filters => filters }, { @@ -1764,33 +1812,46 @@ mod test { ) .await .unwrap(); - insta::assert_debug_snapshot!(requirements, @r###" - RequirementsTxt { - requirements: [ - RequirementEntry { - requirement: Named( - Requirement { - name: PackageName( - "flask", - ), - extras: [], - version_or_url: None, - marker: None, - }, - ), - hashes: [], - }, - ], - constraints: [], - editables: [], - index_url: None, - extra_index_urls: [], - find_links: [], - no_index: false, - no_binary: None, - only_binary: None, - } - "###); + let filter_path = safe_filter_path(temp_dir.path()); + let filters = vec![(filter_path.as_str(), ""), (r"\\\\", "/")]; + + insta::with_settings!({ + filters => filters, + }, { + insta::assert_debug_snapshot!(requirements, @r###" + RequirementsTxt { + requirements: [ + RequirementEntry { + requirement: Named( + Requirement { + name: PackageName( + "flask", + ), + extras: [], + version_or_url: None, + marker: None, + path: Some( + "/subdir/sibling.txt", + ), + }, + ), + hashes: [], + path: Some( + "/subdir/sibling.txt", + ), + }, + ], + constraints: [], + editables: [], + index_url: None, + extra_index_urls: [], + find_links: [], + no_index: false, + no_binary: None, + only_binary: None, + } + "###); + }); Ok(()) } @@ -1818,39 +1879,52 @@ mod test { ) .await .unwrap(); - insta::assert_debug_snapshot!(requirements, @r###" - RequirementsTxt { - requirements: [ - RequirementEntry { - requirement: Named( - Requirement { - name: PackageName( - "flask", - ), - extras: [], - version_or_url: None, - marker: None, - }, - ), - hashes: [], - }, - ], - constraints: [], - editables: [], - index_url: None, - extra_index_urls: [], - find_links: [], - no_index: false, - no_binary: Packages( - [ - PackageName( - "flask", - ), + let filter_path = safe_filter_path(temp_dir.path()); + let filters = vec![(filter_path.as_str(), ""), (r"\\\\", "/")]; + + insta::with_settings!({ + filters => filters, + }, { + insta::assert_debug_snapshot!(requirements, @r###" + RequirementsTxt { + requirements: [ + RequirementEntry { + requirement: Named( + Requirement { + name: PackageName( + "flask", + ), + extras: [], + version_or_url: None, + marker: None, + path: Some( + "/requirements.txt", + ), + }, + ), + hashes: [], + path: Some( + "/requirements.txt", + ), + }, ], - ), - only_binary: None, - } - "###); + constraints: [], + editables: [], + index_url: None, + extra_index_urls: [], + find_links: [], + no_index: false, + no_binary: Packages( + [ + PackageName( + "flask", + ), + ], + ), + only_binary: None, + } + "###); + }); Ok(()) } @@ -1884,40 +1958,49 @@ mod test { .await .unwrap(); - insta::assert_debug_snapshot!(requirements, @r###" - RequirementsTxt { - requirements: [], - constraints: [], - editables: [ - EditableRequirement { - url: VerbatimUrl { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/foo/bar", - query: None, - fragment: None, + let filter_path = safe_filter_path(temp_dir.path()); + let filters = vec![(filter_path.as_str(), ""), (r"\\\\", "/")]; + insta::with_settings!({ + filters => filters, + }, { + insta::assert_debug_snapshot!(requirements, @r###" + RequirementsTxt { + requirements: [], + constraints: [], + editables: [ + EditableRequirement { + url: VerbatimUrl { + url: Url { + scheme: "file", + cannot_be_a_base: false, + username: "", + password: None, + host: None, + port: None, + path: "/foo/bar", + query: None, + fragment: None, + }, + given: Some( + "/foo/bar", + ), }, - given: Some( - "/foo/bar", + extras: [], + path: "/foo/bar", + source: Some( + "/grandchild.txt", ), }, - extras: [], - path: "/foo/bar", - }, - ], - index_url: None, - extra_index_urls: [], - find_links: [], - no_index: true, - no_binary: None, - only_binary: None, - } - "###); + ], + index_url: None, + extra_index_urls: [], + find_links: [], + no_index: true, + no_binary: None, + only_binary: None, + } + "###); + }); Ok(()) } @@ -2000,154 +2083,190 @@ mod test { ) .await .unwrap(); - insta::assert_debug_snapshot!(requirements, @r###" - RequirementsTxt { - requirements: [ - RequirementEntry { - requirement: Named( - Requirement { - name: PackageName( - "httpx", - ), - extras: [], - version_or_url: None, - marker: None, - }, - ), - hashes: [], - }, - RequirementEntry { - requirement: Named( - Requirement { - name: PackageName( - "flask", - ), - extras: [], - version_or_url: Some( - VersionSpecifier( - VersionSpecifiers( - [ - VersionSpecifier { - operator: Equal, - version: "3.0.0", - }, - ], - ), + let filter_path = safe_filter_path(temp_dir.path()); + let filters = vec![(filter_path.as_str(), ""), (r"\\\\", "/")]; + insta::with_settings!({ + filters => filters, + }, { + insta::assert_debug_snapshot!(requirements, @r###" + RequirementsTxt { + requirements: [ + RequirementEntry { + requirement: Named( + Requirement { + name: PackageName( + "httpx", ), - ), - marker: None, - }, - ), - hashes: [ - "sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - ], - }, - RequirementEntry { - requirement: Named( - Requirement { - name: PackageName( - "requests", - ), - extras: [], - version_or_url: Some( - VersionSpecifier( - VersionSpecifiers( - [ - VersionSpecifier { - operator: Equal, - version: "2.26.0", - }, - ], - ), + extras: [], + version_or_url: None, + marker: None, + path: Some( + "/./sibling.txt", ), - ), - marker: None, - }, - ), - hashes: [ - "sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321", - ], - }, - RequirementEntry { - requirement: Named( - Requirement { - name: PackageName( - "black", - ), - extras: [], - version_or_url: Some( - VersionSpecifier( - VersionSpecifiers( - [ - VersionSpecifier { - operator: Equal, - version: "21.12b0", - }, - ], - ), - ), - ), - marker: None, - }, - ), - hashes: [], - }, - RequirementEntry { - requirement: Named( - Requirement { - name: PackageName( - "mypy", - ), - extras: [], - version_or_url: Some( - VersionSpecifier( - VersionSpecifiers( - [ - VersionSpecifier { - operator: Equal, - version: "0.910", - }, - ], - ), - ), - ), - marker: None, - }, - ), - hashes: [], - }, - ], - constraints: [], - editables: [], - index_url: Some( - VerbatimUrl { - url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "test.pypi.org", - ), + }, + ), + hashes: [], + path: Some( + "/./sibling.txt", ), - port: None, - path: "/simple/", - query: None, - fragment: None, }, - given: Some( - "https://test.pypi.org/simple/", - ), - }, - ), - extra_index_urls: [], - find_links: [], - no_index: false, - no_binary: All, - only_binary: None, - } - "###); + RequirementEntry { + requirement: Named( + Requirement { + name: PackageName( + "flask", + ), + extras: [], + version_or_url: Some( + VersionSpecifier( + VersionSpecifiers( + [ + VersionSpecifier { + operator: Equal, + version: "3.0.0", + }, + ], + ), + ), + ), + marker: None, + path: Some( + "/requirements.txt", + ), + }, + ), + hashes: [ + "sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + ], + path: Some( + "/requirements.txt", + ), + }, + RequirementEntry { + requirement: Named( + Requirement { + name: PackageName( + "requests", + ), + extras: [], + version_or_url: Some( + VersionSpecifier( + VersionSpecifiers( + [ + VersionSpecifier { + operator: Equal, + version: "2.26.0", + }, + ], + ), + ), + ), + marker: None, + path: Some( + "/requirements.txt", + ), + }, + ), + hashes: [ + "sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321", + ], + path: Some( + "/requirements.txt", + ), + }, + RequirementEntry { + requirement: Named( + Requirement { + name: PackageName( + "black", + ), + extras: [], + version_or_url: Some( + VersionSpecifier( + VersionSpecifiers( + [ + VersionSpecifier { + operator: Equal, + version: "21.12b0", + }, + ], + ), + ), + ), + marker: None, + path: Some( + "/requirements.txt", + ), + }, + ), + hashes: [], + path: Some( + "/requirements.txt", + ), + }, + RequirementEntry { + requirement: Named( + Requirement { + name: PackageName( + "mypy", + ), + extras: [], + version_or_url: Some( + VersionSpecifier( + VersionSpecifiers( + [ + VersionSpecifier { + operator: Equal, + version: "0.910", + }, + ], + ), + ), + ), + marker: None, + path: Some( + "/requirements.txt", + ), + }, + ), + hashes: [], + path: Some( + "/requirements.txt", + ), + }, + ], + constraints: [], + editables: [], + index_url: Some( + VerbatimUrl { + url: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "test.pypi.org", + ), + ), + port: None, + path: "/simple/", + query: None, + fragment: None, + }, + given: Some( + "https://test.pypi.org/simple/", + ), + }, + ), + extra_index_urls: [], + find_links: [], + no_index: false, + no_binary: All, + only_binary: None, + } + "###); + }); Ok(()) } diff --git a/crates/requirements-txt/src/requirement.rs b/crates/requirements-txt/src/requirement.rs index 18dc777ab..aacd26884 100644 --- a/crates/requirements-txt/src/requirement.rs +++ b/crates/requirements-txt/src/requirement.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::path::{Path, PathBuf}; use thiserror::Error; @@ -18,6 +18,17 @@ pub enum RequirementsTxtRequirement { Unnamed(UnnamedRequirement), } +impl RequirementsTxtRequirement { + /// Set the source file containing the requirement. + #[must_use] + pub fn with_source(self, path: Option) -> Self { + match self { + Self::Named(requirement) => Self::Named(requirement.with_source(path)), + Self::Unnamed(requirement) => Self::Unnamed(requirement.with_source(path)), + } + } +} + #[derive(Debug, Error)] pub enum RequirementsTxtRequirementError { #[error(transparent)] diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-basic.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-basic.txt.snap index 8aad25caa..eabfd6187 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-basic.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-basic.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -48,9 +54,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -72,9 +84,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -96,9 +114,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -120,9 +144,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -144,9 +174,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-constraints-a.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-constraints-a.txt.snap index ff4c07535..f01b19f11 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-constraints-a.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-constraints-a.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-a.txt", + ), }, ), hashes: [], + path: Some( + "/constraints-a.txt", + ), }, ], constraints: [ @@ -48,6 +54,9 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-b.txt", + ), }, Requirement { name: PackageName( @@ -67,6 +76,9 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-b.txt", + ), }, ], editables: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-constraints-b.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-constraints-b.txt.snap index 8141b2c1d..a30f9f50a 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-constraints-b.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-constraints-b.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-b.txt", + ), }, ), hashes: [], + path: Some( + "/constraints-b.txt", + ), }, RequirementEntry { requirement: Named( @@ -48,9 +54,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-b.txt", + ), }, ), hashes: [], + path: Some( + "/constraints-b.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-editable.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-editable.txt.snap index 0b18a38c4..46fca22fb 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-editable.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-editable.txt.snap @@ -13,9 +13,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/editable.txt", + ), }, ), hashes: [], + path: Some( + "/editable.txt", + ), }, RequirementEntry { requirement: Named( @@ -53,9 +59,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/editable.txt", + ), }, ), hashes: [], + path: Some( + "/editable.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-for-poetry.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-for-poetry.txt.snap index 5c2d30ea7..26bad24f6 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-for-poetry.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-for-poetry.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/for-poetry.txt", + ), }, ), hashes: [], + path: Some( + "/for-poetry.txt", + ), }, RequirementEntry { requirement: Named( @@ -48,9 +54,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/for-poetry.txt", + ), }, ), hashes: [], + path: Some( + "/for-poetry.txt", + ), }, RequirementEntry { requirement: Named( @@ -61,9 +73,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/for-poetry.txt", + ), }, ), hashes: [], + path: Some( + "/for-poetry.txt", + ), }, RequirementEntry { requirement: Named( @@ -93,9 +111,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/for-poetry.txt", + ), }, ), hashes: [], + path: Some( + "/for-poetry.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-include-a.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-include-a.txt.snap index e02e864a4..0d6f8c146 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-include-a.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-include-a.txt.snap @@ -13,9 +13,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/include-b.txt", + ), }, ), hashes: [], + path: Some( + "/include-b.txt", + ), }, RequirementEntry { requirement: Named( @@ -37,9 +43,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/include-a.txt", + ), }, ), hashes: [], + path: Some( + "/include-a.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-include-b.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-include-b.txt.snap index ee9c0987f..f60a2d6fb 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-include-b.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-include-b.txt.snap @@ -13,9 +13,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/include-b.txt", + ), }, ), hashes: [], + path: Some( + "/include-b.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-poetry-with-hashes.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-poetry-with-hashes.txt.snap index 1466557e5..096758411 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-poetry-with-hashes.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-poetry-with-hashes.txt.snap @@ -51,11 +51,17 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ "sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, RequirementEntry { requirement: Named( @@ -104,11 +110,17 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, RequirementEntry { requirement: Named( @@ -168,11 +180,17 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, RequirementEntry { requirement: Named( @@ -221,12 +239,18 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, RequirementEntry { requirement: Named( @@ -275,6 +299,9 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ @@ -283,6 +310,9 @@ RequirementsTxt { "sha256:1a5c7d7d577e0eabfcf15eb87d1e19314c8c4f0e722a301f98e0e3a65e238b4e", "sha256:1e5a38aa85bd660c53947bd28aeaafb6a97d70423606f1ccb044a03a1203fe4a", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-small.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-small.txt.snap index 370397552..089ccb3de 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-small.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-small.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/small.txt", + ), }, ), hashes: [], + path: Some( + "/small.txt", + ), }, RequirementEntry { requirement: Named( @@ -48,9 +54,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/small.txt", + ), }, ), hashes: [], + path: Some( + "/small.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-whitespace.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-whitespace.txt.snap index 0b18a38c4..0ba8a9c41 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-whitespace.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__line-endings-whitespace.txt.snap @@ -13,9 +13,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/whitespace.txt", + ), }, ), hashes: [], + path: Some( + "/whitespace.txt", + ), }, RequirementEntry { requirement: Named( @@ -53,9 +59,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/whitespace.txt", + ), }, ), hashes: [], + path: Some( + "/whitespace.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-basic.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-basic.txt.snap index 8aad25caa..eabfd6187 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-basic.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-basic.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -48,9 +54,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -72,9 +84,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -96,9 +114,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -120,9 +144,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, RequirementEntry { requirement: Named( @@ -144,9 +174,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/basic.txt", + ), }, ), hashes: [], + path: Some( + "/basic.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-constraints-a.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-constraints-a.txt.snap index ff4c07535..f01b19f11 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-constraints-a.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-constraints-a.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-a.txt", + ), }, ), hashes: [], + path: Some( + "/constraints-a.txt", + ), }, ], constraints: [ @@ -48,6 +54,9 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-b.txt", + ), }, Requirement { name: PackageName( @@ -67,6 +76,9 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-b.txt", + ), }, ], editables: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-constraints-b.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-constraints-b.txt.snap index 8141b2c1d..a30f9f50a 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-constraints-b.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-constraints-b.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-b.txt", + ), }, ), hashes: [], + path: Some( + "/constraints-b.txt", + ), }, RequirementEntry { requirement: Named( @@ -48,9 +54,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/constraints-b.txt", + ), }, ), hashes: [], + path: Some( + "/constraints-b.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-for-poetry.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-for-poetry.txt.snap index 5c2d30ea7..26bad24f6 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-for-poetry.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-for-poetry.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/for-poetry.txt", + ), }, ), hashes: [], + path: Some( + "/for-poetry.txt", + ), }, RequirementEntry { requirement: Named( @@ -48,9 +54,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/for-poetry.txt", + ), }, ), hashes: [], + path: Some( + "/for-poetry.txt", + ), }, RequirementEntry { requirement: Named( @@ -61,9 +73,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/for-poetry.txt", + ), }, ), hashes: [], + path: Some( + "/for-poetry.txt", + ), }, RequirementEntry { requirement: Named( @@ -93,9 +111,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/for-poetry.txt", + ), }, ), hashes: [], + path: Some( + "/for-poetry.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-include-a.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-include-a.txt.snap index e02e864a4..0d6f8c146 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-include-a.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-include-a.txt.snap @@ -13,9 +13,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/include-b.txt", + ), }, ), hashes: [], + path: Some( + "/include-b.txt", + ), }, RequirementEntry { requirement: Named( @@ -37,9 +43,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/include-a.txt", + ), }, ), hashes: [], + path: Some( + "/include-a.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-include-b.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-include-b.txt.snap index ee9c0987f..f60a2d6fb 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-include-b.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-include-b.txt.snap @@ -13,9 +13,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/include-b.txt", + ), }, ), hashes: [], + path: Some( + "/include-b.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-poetry-with-hashes.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-poetry-with-hashes.txt.snap index 1466557e5..096758411 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-poetry-with-hashes.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-poetry-with-hashes.txt.snap @@ -51,11 +51,17 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ "sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, RequirementEntry { requirement: Named( @@ -104,11 +110,17 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, RequirementEntry { requirement: Named( @@ -168,11 +180,17 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, RequirementEntry { requirement: Named( @@ -221,12 +239,18 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, RequirementEntry { requirement: Named( @@ -275,6 +299,9 @@ RequirementsTxt { ], ), ), + path: Some( + "/poetry-with-hashes.txt", + ), }, ), hashes: [ @@ -283,6 +310,9 @@ RequirementsTxt { "sha256:1a5c7d7d577e0eabfcf15eb87d1e19314c8c4f0e722a301f98e0e3a65e238b4e", "sha256:1e5a38aa85bd660c53947bd28aeaafb6a97d70423606f1ccb044a03a1203fe4a", ], + path: Some( + "/poetry-with-hashes.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-small.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-small.txt.snap index 370397552..089ccb3de 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-small.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-small.txt.snap @@ -24,9 +24,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/small.txt", + ), }, ), hashes: [], + path: Some( + "/small.txt", + ), }, RequirementEntry { requirement: Named( @@ -48,9 +54,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/small.txt", + ), }, ), hashes: [], + path: Some( + "/small.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-unix-bare-url.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-unix-bare-url.txt.snap index 6ebf240d1..92a67545e 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-unix-bare-url.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-unix-bare-url.txt.snap @@ -25,9 +25,15 @@ RequirementsTxt { }, extras: [], marker: None, + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, ), hashes: [], + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, RequirementEntry { requirement: Unnamed( @@ -54,9 +60,15 @@ RequirementsTxt { ), ], marker: None, + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, ), hashes: [], + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, RequirementEntry { requirement: Unnamed( @@ -79,9 +91,15 @@ RequirementsTxt { }, extras: [], marker: None, + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, ), hashes: [], + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-whitespace.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-whitespace.txt.snap index 0b18a38c4..0ba8a9c41 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-whitespace.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-whitespace.txt.snap @@ -13,9 +13,15 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, + path: Some( + "/whitespace.txt", + ), }, ), hashes: [], + path: Some( + "/whitespace.txt", + ), }, RequirementEntry { requirement: Named( @@ -53,9 +59,15 @@ RequirementsTxt { ), ), marker: None, + path: Some( + "/whitespace.txt", + ), }, ), hashes: [], + path: Some( + "/whitespace.txt", + ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-windows-bare-url.txt.snap b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-windows-bare-url.txt.snap index 0f05ef8ea..10d05e232 100644 --- a/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-windows-bare-url.txt.snap +++ b/crates/requirements-txt/src/snapshots/requirements_txt__test__parse-windows-bare-url.txt.snap @@ -25,9 +25,15 @@ RequirementsTxt { }, extras: [], marker: None, + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, ), hashes: [], + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, RequirementEntry { requirement: Unnamed( @@ -54,9 +60,15 @@ RequirementsTxt { ), ], marker: None, + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, ), hashes: [], + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, RequirementEntry { requirement: Unnamed( @@ -79,9 +91,15 @@ RequirementsTxt { }, extras: [], marker: None, + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, ), hashes: [], + path: Some( + "[WORKSPACE_DIR]/bare-url.txt", + ), }, ], constraints: [], diff --git a/crates/uv-dev/src/resolve_many.rs b/crates/uv-dev/src/resolve_many.rs index d80c971af..95228cc43 100644 --- a/crates/uv-dev/src/resolve_many.rs +++ b/crates/uv-dev/src/resolve_many.rs @@ -132,6 +132,7 @@ pub(crate) async fn resolve_many(args: ResolveManyArgs) -> Result<()> { extras: requirement.extras, version_or_url: Some(equals_version), marker: None, + path: requirement.path, } } else { requirement diff --git a/crates/uv-fs/src/path.rs b/crates/uv-fs/src/path.rs index 3ae7102ae..b790549cd 100644 --- a/crates/uv-fs/src/path.rs +++ b/crates/uv-fs/src/path.rs @@ -3,11 +3,16 @@ use std::path::{Component, Path, PathBuf}; use once_cell::sync::Lazy; -pub static CWD: Lazy = Lazy::new(|| { +/// The current working directory. +pub static CWD: Lazy = + Lazy::new(|| std::env::current_dir().expect("The current directory must exist")); + +/// The current working directory, canonicalized. +pub static CANONICAL_CWD: Lazy = Lazy::new(|| { std::env::current_dir() - .unwrap() - .canonicalize() .expect("The current directory must exist") + .canonicalize() + .expect("The current directory must be canonicalized") }); pub trait Simplified { @@ -22,6 +27,9 @@ pub trait Simplified { /// equivalent to [`std::path::Display`]. fn simplified_display(&self) -> std::path::Display; + /// Canonicalize a path without a `\\?\` prefix on Windows. + fn simple_canonicalize(&self) -> std::io::Result; + /// Render a [`Path`] for user-facing display. /// /// Like [`simplified_display`], but relativizes the path against the current working directory. @@ -37,10 +45,20 @@ impl> Simplified for T { dunce::simplified(self.as_ref()).display() } + fn simple_canonicalize(&self) -> std::io::Result { + dunce::canonicalize(self.as_ref()) + } + fn user_display(&self) -> std::path::Display { let path = dunce::simplified(self.as_ref()); + + // Attempt to strip the current working directory, then the canonicalized current working + // directory, in case they differ. path.strip_prefix(CWD.simplified()) - .unwrap_or(path) + .unwrap_or_else(|_| { + path.strip_prefix(CANONICAL_CWD.simplified()) + .unwrap_or(path) + }) .display() } } @@ -136,7 +154,7 @@ pub fn normalize_path(path: &Path) -> Result { pub fn absolutize_path(path: &Path) -> Result, std::io::Error> { use path_absolutize::Absolutize; - path.absolutize_from(&*CWD) + path.absolutize_from(CWD.simplified()) } /// Like `fs_err::canonicalize`, but with permissive failures on Windows. diff --git a/crates/uv-installer/src/site_packages.rs b/crates/uv-installer/src/site_packages.rs index 77bb7ca40..63643acee 100644 --- a/crates/uv-installer/src/site_packages.rs +++ b/crates/uv-installer/src/site_packages.rs @@ -342,6 +342,7 @@ impl<'a> SitePackages<'a> { Requirement::from_pep508(dependency)?, ), hashes: vec![], + path: None, }; if seen.insert(dependency.clone()) { stack.push(dependency); @@ -406,6 +407,7 @@ impl<'a> SitePackages<'a> { Requirement::from_pep508(dependency)?, ), hashes: vec![], + path: None, }; if seen.insert(dependency.clone()) { stack.push(dependency); diff --git a/crates/uv-requirements/src/pyproject.rs b/crates/uv-requirements/src/pyproject.rs index 5904f486c..c578cc586 100644 --- a/crates/uv-requirements/src/pyproject.rs +++ b/crates/uv-requirements/src/pyproject.rs @@ -238,6 +238,7 @@ impl Pep621Metadata { pub(crate) fn try_from( pyproject: PyProjectToml, extras: &ExtrasSpecification, + pyproject_path: &Path, project_dir: &Path, workspace_sources: &HashMap, workspace_packages: &HashMap, @@ -281,6 +282,7 @@ impl Pep621Metadata { let requirements = lower_requirements( &project.dependencies.unwrap_or_default(), &project.optional_dependencies.unwrap_or_default(), + pyproject_path, &project.name, project_dir, &project_sources.unwrap_or_default(), @@ -320,6 +322,7 @@ impl Pep621Metadata { pub(crate) fn lower_requirements( dependencies: &[String], optional_dependencies: &IndexMap>, + pyproject_path: &Path, project_name: &PackageName, project_dir: &Path, project_sources: &HashMap, @@ -330,7 +333,8 @@ pub(crate) fn lower_requirements( let dependencies = dependencies .iter() .map(|dependency| { - let requirement = pep508_rs::Requirement::from_str(dependency)?; + let requirement = pep508_rs::Requirement::from_str(dependency)? + .with_source(Some(pyproject_path.to_path_buf())); let name = requirement.name.clone(); lower_requirement( requirement, @@ -350,7 +354,8 @@ pub(crate) fn lower_requirements( let dependencies: Vec<_> = dependencies .iter() .map(|dependency| { - let requirement = pep508_rs::Requirement::from_str(dependency)?; + let requirement = pep508_rs::Requirement::from_str(dependency)? + .with_source(Some(pyproject_path.to_path_buf())); let name = requirement.name.clone(); lower_requirement( requirement, @@ -532,6 +537,7 @@ pub(crate) fn lower_requirement( extras: requirement.extras, marker: requirement.marker, source, + path: Some(project_dir.join("pyproject.toml")), }) } diff --git a/crates/uv-requirements/src/specification.rs b/crates/uv-requirements/src/specification.rs index 7e07a5517..9ac0d5415 100644 --- a/crates/uv-requirements/src/specification.rs +++ b/crates/uv-requirements/src/specification.rs @@ -71,6 +71,7 @@ impl RequirementsSpecification { RequirementEntry { requirement, hashes: vec![], + path: None, }, )?], constraints: vec![], @@ -87,7 +88,7 @@ impl RequirementsSpecification { } } RequirementsSource::Editable(name) => { - let requirement = EditableRequirement::parse(name, std::env::current_dir()?) + let requirement = EditableRequirement::parse(name, None, std::env::current_dir()?) .with_context(|| format!("Failed to parse `{name}`"))?; Self { project: None, @@ -145,10 +146,6 @@ impl RequirementsSpecification { } RequirementsSource::PyprojectToml(path) => { let contents = uv_fs::read_to_string(&path).await?; - // We need use this path as base for the relative paths inside pyproject.toml, so - // we need the absolute path instead of a potentially relative path. E.g. with - // `foo = { path = "../foo" }`, we will join `../foo` onto this path. - let path = uv_fs::absolutize_path(path)?; Self::parse_direct_pyproject_toml(&contents, extras, path.as_ref(), preview) .with_context(|| format!("Failed to parse `{}`", path.user_display()))? } @@ -187,19 +184,25 @@ impl RequirementsSpecification { pub(crate) fn parse_direct_pyproject_toml( contents: &str, extras: &ExtrasSpecification, - path: &Path, + pyproject_path: &Path, preview: PreviewMode, ) -> Result { let pyproject = toml::from_str::(contents)?; + // We need use this path as base for the relative paths inside pyproject.toml, so + // we need the absolute path instead of a potentially relative path. E.g. with + // `foo = { path = "../foo" }`, we will join `../foo` onto this path. + let absolute_path = uv_fs::absolutize_path(pyproject_path)?; + let project_dir = absolute_path + .parent() + .context("`pyproject.toml` has no parent directory")?; + let workspace_sources = HashMap::default(); let workspace_packages = HashMap::default(); - let project_dir = path - .parent() - .context("pyproject.toml has no parent directory")?; match Pep621Metadata::try_from( pyproject, extras, + pyproject_path, project_dir, &workspace_sources, &workspace_packages, @@ -221,11 +224,13 @@ impl RequirementsSpecification { url, path, extras: requirement.extras, + source: Some(pyproject_path.to_path_buf()), }) } else { Either::Right(UnresolvedRequirementSpecification { requirement: UnresolvedRequirement::Named(requirement), hashes: vec![], + path: Some(pyproject_path.to_string_lossy().to_string()), }) } }); @@ -239,8 +244,11 @@ impl RequirementsSpecification { }) } Ok(None) => { - debug!("Dynamic pyproject.toml at: `{}`", path.user_display()); - let path = fs_err::canonicalize(path)?; + debug!( + "Dynamic pyproject.toml at: `{}`", + pyproject_path.user_display() + ); + let path = fs_err::canonicalize(pyproject_path)?; let source_tree = path.parent().ok_or_else(|| { anyhow::anyhow!( "The file `{}` appears to be a `pyproject.toml` file, which must be in a directory", diff --git a/crates/uv-requirements/src/unnamed.rs b/crates/uv-requirements/src/unnamed.rs index 4ef0f5aff..b00cbe729 100644 --- a/crates/uv-requirements/src/unnamed.rs +++ b/crates/uv-requirements/src/unnamed.rs @@ -101,6 +101,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, + path: requirement.path, }); } @@ -119,6 +120,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, + path: requirement.path, }); } @@ -146,11 +148,13 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, + path: requirement.path, }); } // Attempt to read a `pyproject.toml` file. - if let Some(pyproject) = fs_err::read_to_string(path.join("pyproject.toml")) + let project_path = path.join("pyproject.toml"); + if let Some(pyproject) = fs_err::read_to_string(&project_path) .ok() .and_then(|contents| toml::from_str::(&contents).ok()) { @@ -166,6 +170,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, + path: Some(project_path.clone()), }); } @@ -183,6 +188,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, + path: Some(project_path.clone()), }); } } @@ -211,6 +217,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, + path: requirement.path, }); } } @@ -269,6 +276,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, + path: requirement.path, }) } } diff --git a/crates/uv-resolver/src/resolution.rs b/crates/uv-resolver/src/resolution.rs index 3407cd483..b40de6190 100644 --- a/crates/uv-resolver/src/resolution.rs +++ b/crates/uv-resolver/src/resolution.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::collections::{BTreeMap, BTreeSet}; use std::hash::BuildHasherDefault; use std::rc::Rc; @@ -14,7 +15,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use distribution_types::{ Dist, DistributionMetadata, IndexUrl, LocalEditable, Name, ParsedUrlError, Requirement, - ResolvedDist, Verbatim, VersionId, VersionOrUrlRef, + ResolvedDist, SourceAnnotation, Verbatim, VersionId, VersionOrUrlRef, }; use once_map::OnceMap; use pep440_rs::Version; @@ -543,12 +544,15 @@ pub struct DisplayResolutionGraph<'a> { /// The style of annotation comments, used to indicate the dependencies that requested each /// package. annotation_style: AnnotationStyle, + /// External sources for each package: requirements, constraints, and overrides. + sources: BTreeMap>, } impl<'a> From<&'a ResolutionGraph> for DisplayResolutionGraph<'a> { fn from(resolution: &'a ResolutionGraph) -> Self { Self::new( resolution, + BTreeMap::default(), &[], false, false, @@ -561,9 +565,10 @@ 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)] + #[allow(clippy::fn_params_excessive_bools, clippy::too_many_arguments)] pub fn new( underlying: &'a ResolutionGraph, + sources: BTreeMap>, no_emit_packages: &'a [PackageName], show_hashes: bool, include_extras: bool, @@ -579,6 +584,7 @@ impl<'a> DisplayResolutionGraph<'a> { include_annotations, include_index_annotation, annotation_style, + sources, } } } @@ -719,13 +725,24 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { .collect::>(); edges.sort_unstable_by_key(|package| package.name()); + // Include all external sources (e.g., requirements files). + let source_name: String = match node { + Node::Editable(_package_name, local_editable) => { + local_editable.url.given().unwrap_or_default().to_string() + } + Node::Distribution(name, _, _) => name.to_string(), + }; + + let source = self.sources.get(&source_name).cloned().unwrap_or_default(); + match self.annotation_style { AnnotationStyle::Line => { if !edges.is_empty() { let separator = if has_hashes { "\n " } else { " " }; let deps = edges .into_iter() - .map(|dependency| dependency.name().to_string()) + .map(|dependency| format!("{}", dependency.name())) + .chain(source.into_iter().map(|source| source.to_string())) .collect::>() .join(", "); let comment = format!("# via {deps}").green().to_string(); @@ -733,17 +750,30 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> { } } AnnotationStyle::Split => match edges.as_slice() { - [] => {} - [edge] => { + [] if source.is_empty() => {} + [] if source.len() == 1 => { + let separator = "\n"; + let comment = format!(" # via {}", source.iter().next().unwrap()) + .green() + .to_string(); + annotation = Some((separator, comment)); + } + [edge] if source.is_empty() => { let separator = "\n"; let comment = format!(" # via {}", edge.name()).green().to_string(); annotation = Some((separator, comment)); } edges => { let separator = "\n"; - let deps = edges - .iter() - .map(|dependency| format!(" # {}", dependency.name())) + let deps = source + .into_iter() + .map(|source| source.to_string()) + .chain( + edges + .iter() + .map(|dependency| format!("{}", dependency.name())), + ) + .map(|name| format!(" # {name}")) .collect::>() .join("\n"); let comment = format!(" # via\n{deps}").green().to_string(); diff --git a/crates/uv/src/commands/pip_compile.rs b/crates/uv/src/commands/pip_compile.rs index b2043a885..a29a89318 100644 --- a/crates/uv/src/commands/pip_compile.rs +++ b/crates/uv/src/commands/pip_compile.rs @@ -1,5 +1,5 @@ -use indexmap::IndexMap; use std::borrow::Cow; +use std::collections::{BTreeMap, BTreeSet}; use std::env; use std::fmt::Write; use std::io::stdout; @@ -10,15 +10,17 @@ use std::str::FromStr; use anstream::{eprint, AutoStream, StripStream}; use anyhow::{anyhow, Context, Result}; use fs_err as fs; +use indexmap::IndexMap; use itertools::Itertools; use owo_colors::OwoColorize; use tempfile::tempdir_in; use tracing::debug; -use distribution_types::{IndexLocations, LocalEditable, LocalEditables, ParsedUrlError, Verbatim}; +use distribution_types::{ + IndexLocations, LocalEditable, LocalEditables, ParsedUrlError, SourceAnnotation, Verbatim, +}; use distribution_types::{Requirement, Requirements}; use install_wheel_rs::linker::LinkMode; - use platform_tags::Tags; use pypi_types::Metadata23; use requirements_txt::EditableRequirement; @@ -352,6 +354,65 @@ pub(crate) async fn pip_compile( .resolve() .await?; + let mut sources: BTreeMap> = BTreeMap::new(); + + for requirement in &requirements { + if let Some(path) = &requirement.path { + if path.ends_with("pyproject.toml") { + sources + .entry(requirement.name.to_string()) + .or_default() + .insert(SourceAnnotation::PyProject { + path: path.clone(), + project_name: project.as_ref().map(ToString::to_string), + }); + } else { + sources + .entry(requirement.name.to_string()) + .or_default() + .insert(SourceAnnotation::Requirement(path.clone())); + } + } + } + + for requirement in &constraints { + if let Some(path) = &requirement.path { + sources + .entry(requirement.name.to_string()) + .or_default() + .insert(SourceAnnotation::Constraint(path.clone())); + } + } + + for requirement in &overrides { + if let Some(path) = &requirement.path { + sources + .entry(requirement.name.to_string()) + .or_default() + .insert(SourceAnnotation::Override(path.clone())); + } + } + + for editable in &editables { + let package_name = editable.url.given().unwrap_or_default().to_string(); + if let Some(source) = &editable.source { + if source.ends_with("pyproject.toml") { + sources + .entry(package_name) + .or_default() + .insert(SourceAnnotation::PyProject { + path: source.clone(), + project_name: project.as_ref().map(ToString::to_string), + }); + } else { + sources + .entry(package_name) + .or_default() + .insert(SourceAnnotation::Requirement(source.clone())); + } + } + } + // Collect constraints and overrides. let constraints = Constraints::from_requirements(constraints); let overrides = Overrides::from_requirements(overrides); @@ -363,7 +424,12 @@ pub(crate) async fn pip_compile( let start = std::time::Instant::now(); let editables = LocalEditables::from_editables(editables.into_iter().map(|editable| { - let EditableRequirement { url, extras, path } = editable; + let EditableRequirement { + url, + extras, + path, + source: _, + } = editable; LocalEditable { url, path, extras } })); @@ -588,6 +654,7 @@ pub(crate) async fn pip_compile( "{}", DisplayResolutionGraph::new( &resolution, + sources, &no_emit_packages, generate_hashes, include_extras, diff --git a/crates/uv/src/commands/pip_install.rs b/crates/uv/src/commands/pip_install.rs index 612dfa86a..34fc7bf56 100644 --- a/crates/uv/src/commands/pip_install.rs +++ b/crates/uv/src/commands/pip_install.rs @@ -575,7 +575,12 @@ async fn build_editables( .with_reporter(DownloadReporter::from(printer).with_length(editables.len() as u64)); let editables = LocalEditables::from_editables(editables.iter().map(|editable| { - let EditableRequirement { url, extras, path } = editable; + let EditableRequirement { + url, + extras, + path, + source: _, + } = editable; LocalEditable { url: url.clone(), extras: extras.clone(), @@ -673,6 +678,7 @@ async fn resolve( extras: vec![], marker: None, source, + path: None, }; Ok(Preference::from_requirement(requirement)) }) diff --git a/crates/uv/src/commands/pip_sync.rs b/crates/uv/src/commands/pip_sync.rs index 4d7e6c283..017573f39 100644 --- a/crates/uv/src/commands/pip_sync.rs +++ b/crates/uv/src/commands/pip_sync.rs @@ -684,7 +684,12 @@ async fn resolve_editables( .with_reporter(DownloadReporter::from(printer).with_length(uninstalled.len() as u64)); let editables = LocalEditables::from_editables(uninstalled.iter().map(|editable| { - let EditableRequirement { url, path, extras } = editable; + let EditableRequirement { + url, + path, + extras, + source: _, + } = editable; LocalEditable { url: url.clone(), path: path.clone(), diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index caf4db042..94067fd70 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -35,6 +35,7 @@ fn compile_requirements_in() -> Result<()> { # 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 anyio==3.7.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -178,6 +179,7 @@ dependencies = [ # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z pyproject.toml anyio==3.7.0 + # via project (pyproject.toml) idna==3.6 # via anyio sniffio==1.3.1 @@ -211,8 +213,11 @@ fn compile_constraints_txt() -> Result<()> { # 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 --constraint constraints.txt anyio==3.7.0 + # via -r requirements.in idna==3.3 - # via anyio + # via + # -c constraints.txt + # anyio sniffio==1.3.1 # via anyio @@ -275,10 +280,13 @@ fn compile_constraints_markers() -> Result<()> { # 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 --constraint constraints.txt anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.0 - # via anyio + # via + # -c constraints.txt + # anyio ----- stderr ----- Resolved 3 packages in [TIME] @@ -315,6 +323,9 @@ fn compile_constraint_extra() -> Result<()> { click==8.1.7 # via flask flask==3.0.2 + # via + # -c constraints.txt + # -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -362,6 +373,7 @@ optional-dependencies.foo = [ # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z pyproject.toml --extra foo anyio==3.7.0 + # via project (pyproject.toml) idna==3.6 # via anyio sniffio==1.3.1 @@ -403,6 +415,7 @@ optional-dependencies."FrIeNdLy-._.-bArD" = [ # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z pyproject.toml --extra FRiENDlY-...-_-BARd anyio==3.7.0 + # via project (pyproject.toml) idna==3.6 # via anyio sniffio==1.3.1 @@ -822,6 +835,7 @@ fn compile_python_312() -> Result<()> { # 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 --python-version 3.12 black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -891,6 +905,7 @@ fn compile_python_312_no_deps() -> Result<()> { # 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 --no-deps --python-version 3.12 black==23.10.1 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -955,6 +970,7 @@ fn compile_sdist_resolution_lowest() -> Result<()> { # 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 --resolution=lowest-direct --python-version 3.12 anyio @ https://files.pythonhosted.org/packages/2d/b8/7333d87d5f03247215d86a86362fd3e324111788c6cdd8d2e6196a6ba833/anyio-4.2.0.tar.gz + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -1036,6 +1052,7 @@ fn compile_numpy_py38() -> Result<()> { # 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 --no-build numpy==1.24.4 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1064,6 +1081,7 @@ fn compile_wheel_url_dependency() -> Result<()> { click==8.1.7 # via flask flask @ https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -1104,6 +1122,7 @@ fn compile_sdist_url_dependency() -> Result<()> { click==8.1.7 # via flask flask @ https://files.pythonhosted.org/packages/d8/09/c1a7354d3925a3c6c8cfdebf4245bae67d633ffda1ba415add06ffc839c5/flask-3.0.0.tar.gz + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -1147,6 +1166,7 @@ fn compile_git_https_dependency() -> Result<()> { # 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 uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@[COMMIT] + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1173,6 +1193,7 @@ fn compile_git_branch_https_dependency() -> Result<()> { # 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 uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1200,6 +1221,7 @@ fn compile_git_tag_https_dependency() -> Result<()> { # 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 uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1229,6 +1251,7 @@ fn compile_git_date_tag_https_dependency() -> Result<()> { # 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 uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1256,6 +1279,7 @@ fn compile_git_long_commit_https_dependency() -> Result<()> { # 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 uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1283,6 +1307,7 @@ fn compile_git_short_commit_https_dependency() -> Result<()> { # 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 uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1309,6 +1334,7 @@ fn compile_git_refs_https_dependency() -> Result<()> { # 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 uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@9d01a806f17ddacb9c7b66b1b68574adf790b63f + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1334,6 +1360,7 @@ fn compile_git_subdirectory_dependency() -> Result<()> { # 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 example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1360,7 +1387,9 @@ fn compile_git_concurrent_access() -> Result<()> { # 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 example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a + # via -r requirements.in example-pkg-b @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_b + # via -r requirements.in ----- stderr ----- Resolved 2 packages in [TIME] @@ -1387,7 +1416,9 @@ fn compile_git_unnamed_concurrent_access() -> Result<()> { # 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 example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a + # via -r requirements.in example-pkg-b @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_b + # via -r requirements.in ----- stderr ----- Resolved 2 packages in [TIME] @@ -1438,6 +1469,7 @@ fn compile_git_subdirectory_static_metadata() -> Result<()> { # 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 uv-public-pypackage @ git+https://github.com/astral-test/uv-workspace-pypackage#subdirectory=uv-public-pypackage@b8c4e192456d736c27f2c84c61175c896dba8373 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1467,6 +1499,7 @@ fn mixed_url_dependency() -> Result<()> { click==8.1.7 # via flask flask==3.0.0 + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -1476,7 +1509,9 @@ fn mixed_url_dependency() -> Result<()> { # jinja2 # werkzeug werkzeug @ https://files.pythonhosted.org/packages/c3/fc/254c3e9b5feb89ff5b9076a23218dafbc99c96ac5941e900b71206e6313b/werkzeug-3.0.1-py3-none-any.whl - # via flask + # via + # -r requirements.in + # flask ----- stderr ----- Resolved 7 packages in [TIME] @@ -1525,6 +1560,7 @@ fn compatible_direct_url_dependency() -> Result<()> { # 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 werkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1576,6 +1612,7 @@ fn conflicting_repeated_url_dependency_markers() -> Result<()> { # 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 werkzeug @ https://files.pythonhosted.org/packages/bd/24/11c3ea5a7e866bf2d97f0501d0b4b1c9bbeade102bb4b588f0d2919a5212/Werkzeug-2.0.1-py3-none-any.whl + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -1652,6 +1689,7 @@ fn compatible_repeated_url_dependency() -> Result<()> { # 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 anyio @ git+https://github.com/agronholm/anyio@437a7e310925a962cab4a58fcd2455fbcd578d51 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -1712,6 +1750,7 @@ fn compatible_narrowed_url_dependency() -> Result<()> { # 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 anyio @ git+https://github.com/agronholm/anyio@437a7e310925a962cab4a58fcd2455fbcd578d51 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -1745,6 +1784,7 @@ fn compatible_broader_url_dependency() -> Result<()> { # 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 anyio @ git+https://github.com/agronholm/anyio.git@437a7e310925a962cab4a58fcd2455fbcd578d51 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -1778,6 +1818,7 @@ fn compatible_repeated_narrowed_url_dependency() -> Result<()> { # 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 anyio @ git+https://github.com/agronholm/anyio.git@437a7e310925a962cab4a58fcd2455fbcd578d51 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -1838,6 +1879,7 @@ fn allowed_transitive_git_dependency() -> Result<()> { # 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 hatchling-editable @ https://github.com/astral-sh/uv/files/14762645/hatchling_editable.zip + # via -r requirements.in iniconfig @ git+https://github.com/pytest-dev/iniconfig@9cae43103df70bac6fde7b9f35ad11a9f1be0cb4 # via hatchling-editable @@ -1872,8 +1914,11 @@ fn allowed_transitive_url_dependency() -> Result<()> { # 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 --constraint constraints.txt hatchling-editable @ https://github.com/astral-sh/uv/files/14762645/hatchling_editable.zip + # via -r requirements.in iniconfig @ git+https://github.com/pytest-dev/iniconfig@9cae43103df70bac6fde7b9f35ad11a9f1be0cb4 - # via hatchling-editable + # via + # -c constraints.txt + # hatchling-editable ----- stderr ----- Resolved 2 packages in [TIME] @@ -1907,8 +1952,11 @@ fn allowed_transitive_canonical_url_dependency() -> Result<()> { # 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 --constraint constraints.txt hatchling-editable @ https://github.com/astral-sh/uv/files/14762645/hatchling_editable.zip + # via -r requirements.in iniconfig @ git+https://github.com/pytest-dev/iniconfig.git@9cae43103df70bac6fde7b9f35ad11a9f1be0cb4 - # via hatchling-editable + # via + # -c constraints.txt + # hatchling-editable ----- stderr ----- Resolved 2 packages in [TIME] @@ -1938,6 +1986,7 @@ fn allowed_transitive_url_path_dependency() -> Result<()> { # 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 hatchling-editable @ ${HATCH_PATH} + # via -r requirements.in iniconfig @ git+https://github.com/pytest-dev/iniconfig@9cae43103df70bac6fde7b9f35ad11a9f1be0cb4 # via hatchling-editable @@ -2008,6 +2057,9 @@ fn requirement_override_prerelease() -> Result<()> { click==7.1.2 # via flask flask==1.1.4 + # via + # --override overrides.txt + # -r requirements.in itsdangerous==1.1.0 # via flask jinja2==2.11.3 @@ -2055,15 +2107,19 @@ optional-dependencies.bar = [ # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z pyproject.toml --all-extras anyio==3.7.0 - # via httpcore + # via + # project (pyproject.toml) + # httpcore certifi==2024.2.2 # via httpcore h11==0.14.0 # via httpcore httpcore==0.18.0 + # via project (pyproject.toml) idna==3.6 # via anyio iniconfig==1.1.1 + # via project (pyproject.toml) sniffio==1.3.1 # via # anyio @@ -2106,7 +2162,7 @@ optional-dependencies.bar = [ ----- 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 --annotation-style=line pyproject.toml --all-extras - anyio==3.7.0 # via httpcore + anyio==3.7.0 # via httpcore, project (pyproject.toml) certifi==2024.2.2 # via httpcore h11==0.14.0 # via httpcore httpcore==0.18.0 @@ -2245,6 +2301,7 @@ fn compile_exclude_newer() -> Result<()> { .arg(context.cache_dir.path()) .env("VIRTUAL_ENV", context.venv.as_os_str()) .env("UV_NO_WRAP", "1") + .env("UV_STACK_SIZE", (2 * 1024 * 1024).to_string()) .current_dir(context.temp_dir.path()), @r###" success: true exit_code: 0 @@ -2252,6 +2309,7 @@ fn compile_exclude_newer() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile requirements.in --exclude-newer 2022-04-04T12:00:00Z --cache-dir [CACHE_DIR] tqdm==4.64.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -2270,6 +2328,7 @@ fn compile_exclude_newer() -> Result<()> { .arg(context.cache_dir.path()) .env("VIRTUAL_ENV", context.venv.as_os_str()) .env("UV_NO_WRAP", "1") + .env("UV_STACK_SIZE", (2 * 1024 * 1024).to_string()) .current_dir(context.temp_dir.path()), @r###" success: true exit_code: 0 @@ -2277,6 +2336,7 @@ fn compile_exclude_newer() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile requirements.in --exclude-newer 2022-04-04 --cache-dir [CACHE_DIR] tqdm==4.64.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -2294,6 +2354,7 @@ fn compile_exclude_newer() -> Result<()> { .arg(context.cache_dir.path()) .env("VIRTUAL_ENV", context.venv.as_os_str()) .env("UV_NO_WRAP", "1") + .env("UV_STACK_SIZE", (2 * 1024 * 1024).to_string()) .current_dir(context.temp_dir.path()), @r###" success: false exit_code: 2 @@ -2338,6 +2399,7 @@ fn compile_wheel_path_dependency() -> Result<()> { click==8.1.7 # via flask flask @ file://[TEMP_DIR]/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2369,6 +2431,7 @@ fn compile_wheel_path_dependency() -> Result<()> { click==8.1.7 # via flask flask @ file:flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2401,6 +2464,7 @@ fn compile_wheel_path_dependency() -> Result<()> { click==8.1.7 # via flask flask @ file://flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2433,6 +2497,7 @@ fn compile_wheel_path_dependency() -> Result<()> { click==8.1.7 # via flask flask @ ./flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2465,6 +2530,7 @@ fn compile_wheel_path_dependency() -> Result<()> { click==8.1.7 # via flask flask @ [TEMP_DIR]/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2498,6 +2564,7 @@ fn compile_wheel_path_dependency() -> Result<()> { click==8.1.7 # via flask flask @ file://[TEMP_DIR]/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2534,6 +2601,7 @@ fn compile_wheel_path_dependency() -> Result<()> { click==8.1.7 # via flask flask @ file://localhost/[TEMP_DIR]/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2581,6 +2649,7 @@ fn compile_source_distribution_path_dependency() -> Result<()> { click==8.1.7 # via flask flask @ file://[TEMP_DIR]/flask-3.0.0.tar.gz + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2640,6 +2709,7 @@ fn compile_yanked_version_direct() -> Result<()> { # 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 attrs==21.1.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -2701,6 +2771,7 @@ fn override_dependency() -> Result<()> { click==8.1.7 # via flask flask==3.0.0 + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2710,7 +2781,9 @@ fn override_dependency() -> Result<()> { # jinja2 # werkzeug werkzeug==2.3.0 - # via flask + # via + # --override overrides.txt + # flask ----- stderr ----- Resolved 7 packages in [TIME] @@ -2743,6 +2816,7 @@ fn override_multi_dependency() -> Result<()> { # 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 --override overrides.txt black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -2754,7 +2828,9 @@ fn override_multi_dependency() -> Result<()> { platformdirs==4.2.0 # via black tomli==2.0.1 - # via black + # via + # --override overrides.txt + # black ----- stderr ----- Resolved 7 packages in [TIME] @@ -2789,6 +2865,7 @@ fn override_dependency_url() -> Result<()> { click==8.1.7 # via flask flask==3.0.0 + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2796,7 +2873,9 @@ fn override_dependency_url() -> Result<()> { markupsafe==2.1.5 # via jinja2 werkzeug @ https://files.pythonhosted.org/packages/cc/94/5f7079a0e00bd6863ef8f1da638721e9da21e5bacee597595b318f71d62e/Werkzeug-1.0.1-py2.py3-none-any.whl - # via flask + # via + # --override overrides.txt + # flask ----- stderr ----- Resolved 7 packages in [TIME] @@ -2831,6 +2910,7 @@ fn override_dependency_unnamed_url() -> Result<()> { click==8.1.7 # via flask flask==3.0.0 + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2838,7 +2918,9 @@ fn override_dependency_unnamed_url() -> Result<()> { markupsafe==2.1.5 # via jinja2 werkzeug @ https://files.pythonhosted.org/packages/cc/94/5f7079a0e00bd6863ef8f1da638721e9da21e5bacee597595b318f71d62e/Werkzeug-1.0.1-py2.py3-none-any.whl - # via flask + # via + # --override overrides.txt + # flask ----- stderr ----- Resolved 7 packages in [TIME] @@ -2863,6 +2945,7 @@ fn missing_registry_extra() -> Result<()> { # 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 black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -2902,6 +2985,7 @@ fn missing_url_extra() -> Result<()> { click==8.1.7 # via flask flask @ https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2942,6 +3026,7 @@ fn preserve_url() -> Result<()> { click==8.1.7 # via flask flask @ https://files.PYTHONHOSTED.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -2987,6 +3072,7 @@ fn preserve_project_root() -> Result<()> { click==8.1.7 # via flask flask @ file://${PROJECT_ROOT}/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -3027,6 +3113,7 @@ fn respect_http_env_var() -> Result<()> { click==8.1.7 # via flask flask @ ${URL} + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -3067,6 +3154,7 @@ fn respect_unnamed_env_var() -> Result<()> { click==8.1.7 # via flask flask @ ${URL} + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -3138,6 +3226,7 @@ fn respect_file_env_var() -> Result<()> { click==8.1.7 # via flask flask @ ${FILE_PATH} + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -3179,8 +3268,11 @@ fn compile_editable() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in -e ${PROJECT_ROOT}/../../scripts/packages/maturin_editable + # via -r [TEMP_DIR]/requirements.in -e ../../scripts/packages/poetry_editable + # via -r [TEMP_DIR]/requirements.in -e file://../../scripts/packages/black_editable + # via -r [TEMP_DIR]/requirements.in aiohttp==3.9.3 # via black aiosignal==1.3.1 @@ -3190,6 +3282,7 @@ fn compile_editable() -> Result<()> { attrs==23.2.0 # via aiohttp boltons==23.1.1 + # via -r [TEMP_DIR]/requirements.in frozenlist==1.4.1 # via # aiohttp @@ -3238,6 +3331,7 @@ fn deduplicate_editable() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in -e file://../../scripts/packages/black_editable + # via -r [TEMP_DIR]/requirements.in aiohttp==3.9.3 # via black aiosignal==1.3.1 @@ -3295,6 +3389,7 @@ fn recursive_extras_direct_url() -> Result<()> { attrs==23.2.0 # via aiohttp black @ ../../scripts/packages/black_editable + # via -r [TEMP_DIR]/requirements.in frozenlist==1.4.1 # via # aiohttp @@ -3333,6 +3428,7 @@ fn compile_editable_url_requirement() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in -e ../../scripts/packages/hatchling_editable + # via -r [TEMP_DIR]/requirements.in iniconfig @ git+https://github.com/pytest-dev/iniconfig@9cae43103df70bac6fde7b9f35ad11a9f1be0cb4 # via hatchling-editable @@ -3460,6 +3556,7 @@ fn compile_html() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile requirements.in --cache-dir [CACHE_DIR] jinja2==3.1.2 + # via -r requirements.in markupsafe==2.1.5 # via jinja2 @@ -3488,6 +3585,7 @@ fn trailing_slash() -> Result<()> { # 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 jinja2==3.1.3 + # via -r requirements.in markupsafe==2.1.5 # via jinja2 @@ -3506,6 +3604,7 @@ fn trailing_slash() -> Result<()> { # 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 jinja2==3.1.3 + # via -r requirements.in markupsafe==2.1.5 # via jinja2 @@ -3532,6 +3631,7 @@ fn compile_legacy_sdist_pep_517() -> Result<()> { # 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 flake8 @ https://files.pythonhosted.org/packages/66/53/3ad4a3b74d609b3b9008a10075c40e7c8909eae60af53623c3888f7a529a/flake8-6.0.0.tar.gz + # via -r requirements.in mccabe==0.7.0 # via flake8 pycodestyle==2.10.0 @@ -3563,6 +3663,7 @@ fn compile_legacy_sdist_setuptools() -> Result<()> { # 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 --legacy-setup-py flake8 @ https://files.pythonhosted.org/packages/66/53/3ad4a3b74d609b3b9008a10075c40e7c8909eae60af53623c3888f7a529a/flake8-6.0.0.tar.gz + # via -r requirements.in mccabe==0.7.0 # via flake8 pycodestyle==2.10.0 @@ -3596,6 +3697,7 @@ fn generate_hashes_registry() -> Result<()> { anyio==4.0.0 \ --hash=sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f \ --hash=sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -3630,6 +3732,7 @@ fn generate_hashes_source_distribution_url() -> Result<()> { # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --generate-hashes anyio @ https://files.pythonhosted.org/packages/2d/b8/7333d87d5f03247215d86a86362fd3e324111788c6cdd8d2e6196a6ba833/anyio-4.2.0.tar.gz \ --hash=sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -3664,6 +3767,7 @@ fn generate_hashes_built_distribution_url() -> Result<()> { # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --generate-hashes anyio @ https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl \ --hash=sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8 + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -3697,6 +3801,7 @@ fn generate_hashes_git() -> Result<()> { # 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 --generate-hashes anyio @ git+https://github.com/agronholm/anyio@437a7e310925a962cab4a58fcd2455fbcd578d51 + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -3731,6 +3836,7 @@ fn generate_hashes_unnamed_url() -> Result<()> { # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --generate-hashes anyio @ https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl \ --hash=sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8 + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -3778,6 +3884,7 @@ fn generate_hashes_local_directory() -> Result<()> { --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f # via anyio poetry-editable @ ../../scripts/packages/poetry_editable + # via [WORKSPACE]/scripts/packages/poetry_editable/pyproject.toml sniffio==1.3.1 \ --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc @@ -3812,6 +3919,7 @@ fn generate_hashes_editable() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in --generate-hashes -e ../../scripts/packages/poetry_editable + # via -r [TEMP_DIR]/requirements.in anyio==4.3.0 \ --hash=sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8 \ --hash=sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6 @@ -3856,8 +3964,11 @@ fn find_links_directory() -> Result<()> { markupsafe==2.1.5 # via werkzeug numpy==1.26.4 + # via -r requirements.in tqdm==1000.0.0 + # via -r requirements.in werkzeug @ https://files.pythonhosted.org/packages/c3/fc/254c3e9b5feb89ff5b9076a23218dafbc99c96ac5941e900b71206e6313b/werkzeug-3.0.1-py3-none-any.whl + # via -r requirements.in ----- stderr ----- Resolved 4 packages in [TIME] @@ -3884,6 +3995,7 @@ fn find_links_url() -> Result<()> { # 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 --no-index tqdm==4.64.1 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -3910,6 +4022,7 @@ fn find_links_env_var() -> Result<()> { # 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 --no-index tqdm==4.64.1 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -3939,6 +4052,7 @@ fn find_links_requirements_txt() -> Result<()> { --find-links https://download.pytorch.org/whl/torch_stable.html tqdm==4.64.1 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -3972,6 +4086,7 @@ fn avoid_irrelevant_extras() -> Result<()> { anyio==4.3.0 # via extras extras==0.0.1 + # via -r requirements.in idna==3.6 # via anyio iniconfig==2.0.0 @@ -4022,6 +4137,7 @@ coverage = ["example[test]", "extras>=0.0.1,<=0.0.2"] # 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 -e . + # via -r requirements.in extras==0.0.1 # via example iniconfig==2.0.0 @@ -4069,6 +4185,7 @@ fn upgrade_none() -> Result<()> { # 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 --output-file requirements.txt black==23.10.1 + # via -r requirements.in click==8.1.2 # via black mypy-extensions==1.0.0 @@ -4124,6 +4241,7 @@ fn upgrade_all() -> Result<()> { # 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 --output-file requirements.txt black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4180,6 +4298,7 @@ fn upgrade_package() -> Result<()> { # 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 --output-file requirements.txt --upgrade-package click black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4269,6 +4388,7 @@ fn unnamed_requirement_with_package_name() -> Result<()> { click==8.1.7 # via flask flask @ https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -4332,6 +4452,7 @@ fn no_header() -> Result<()> { exit_code: 0 ----- stdout ----- black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4368,6 +4489,7 @@ fn custom_compile_command() -> Result<()> { # This file was autogenerated by uv via the following command: # ./custom-uv-compile.sh black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4394,6 +4516,7 @@ fn custom_compile_command() -> Result<()> { # This file was autogenerated by uv via the following command: # ./custom-uv-compile.sh black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4431,6 +4554,7 @@ fn allow_unsafe() -> Result<()> { markupsafe==2.1.5 # via werkzeug werkzeug==3.0.1 + # via -r requirements.in ----- stderr ----- warning: pip-compile's `--allow-unsafe` has no effect (uv can safely pin `pip` and other packages). @@ -4487,6 +4611,7 @@ fn emit_index_urls() -> Result<()> { --extra-index-url https://pypi.org/simple black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4526,6 +4651,7 @@ fn emit_find_links() -> Result<()> { --find-links ./ black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4588,6 +4714,7 @@ fn index_url_requirements_txt() -> Result<()> { # 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 tqdm==4.66.2 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -4683,6 +4810,7 @@ fn offline_registry() -> Result<()> { # 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 black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4709,6 +4837,7 @@ fn offline_registry() -> Result<()> { # 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 --offline black==23.10.1 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -4745,6 +4874,7 @@ fn offline_registry_backtrack() -> Result<()> { # 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 iniconfig==1.1.1 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -4764,6 +4894,7 @@ fn offline_registry_backtrack() -> Result<()> { # 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 --offline iniconfig==1.1.1 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -4853,6 +4984,7 @@ fn offline_direct_url() -> Result<()> { # 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 iniconfig @ https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -4869,6 +5001,7 @@ fn offline_direct_url() -> Result<()> { # 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 --offline iniconfig @ https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -4960,6 +5093,7 @@ fn invalid_metadata_backtrack() -> Result<()> { # 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 --no-index validation==1.0.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -4992,6 +5126,7 @@ fn compile_relative_subfile() -> Result<()> { # 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 anyio==4.3.0 + # via -r subdir/requirements-dev.in idna==3.6 # via anyio sniffio==1.3.1 @@ -5020,6 +5155,7 @@ fn compile_none_extra() -> Result<()> { # 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 entrypoints==0.3 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -5051,6 +5187,7 @@ fn compile_types_pytz() -> Result<()> { # 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 -o requirements.txt types-pytz==2021.1.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -5080,6 +5217,9 @@ fn compile_constraints_compatible_url() -> Result<()> { # 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 --constraint constraints.txt anyio @ https://files.pythonhosted.org/packages/bf/cd/d6d9bb1dadf73e7af02d18225cbd2c93f8552e13130484f1c8dcfece292b/anyio-4.2.0-py3-none-any.whl + # via + # -c constraints.txt + # -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -5114,6 +5254,9 @@ fn compile_constraints_compatible_url_version() -> Result<()> { # 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 --constraint constraints.txt anyio @ https://files.pythonhosted.org/packages/bf/cd/d6d9bb1dadf73e7af02d18225cbd2c93f8552e13130484f1c8dcfece292b/anyio-4.2.0-py3-none-any.whl + # via + # -c constraints.txt + # -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -5196,6 +5339,7 @@ fn index_url_from_command_line() -> Result<()> { # 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 anyio==3.7.1 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -5247,6 +5391,7 @@ fn no_deps_valid_extra() -> Result<()> { # 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 --no-deps flask==3.0.2 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -5272,6 +5417,7 @@ fn no_deps_invalid_extra() -> Result<()> { # 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 --no-deps flask==3.0.2 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -5340,7 +5486,9 @@ dependencies = [ # 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 --no-deps -e [TEMP_DIR]/editable1 + # via -r requirements.in -e [TEMP_DIR]/editable2 + # via -r requirements.in ----- stderr ----- Built 2 editables in [TIME] @@ -5367,6 +5515,7 @@ fn editable_invalid_extra() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in -e ../../scripts/packages/black_editable + # via -r [TEMP_DIR]/requirements.in ----- stderr ----- Built 1 editable in [TIME] @@ -5397,6 +5546,7 @@ fn no_strip_extra() -> Result<()> { click==8.1.7 # via flask flask[dotenv]==3.0.2 + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -5437,6 +5587,7 @@ fn no_strip_extras() -> Result<()> { alabaster==0.7.16 # via sphinx anyio[doc, trio]==4.3.0 + # via -r requirements.in attrs==23.2.0 # via # outcome @@ -5540,10 +5691,13 @@ fn compile_constraints_compatible_version() -> Result<()> { distlib==0.3.8 # via virtualenv filelock==3.8.0 - # via virtualenv + # via + # -c constraints.txt + # virtualenv platformdirs==3.11.0 # via virtualenv virtualenv==20.21.1 + # via -r requirements.in ----- stderr ----- Resolved 4 packages in [TIME] @@ -5634,6 +5788,7 @@ fn editable_override() -> Result<()> { # 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 --override overrides.txt black==24.3.0 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -5676,6 +5831,7 @@ fn override_editable() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in --override [TEMP_DIR]/overrides.txt -e ../../scripts/packages/black_editable + # via -r [TEMP_DIR]/requirements.in ----- stderr ----- Built 1 editable in [TIME] @@ -5711,6 +5867,10 @@ fn override_with_compatible_constraint() -> Result<()> { # 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 --constraint constraints.txt --override overrides.txt anyio==3.0.0 + # via + # -c constraints.txt + # --override overrides.txt + # -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -5780,6 +5940,7 @@ fn unsafe_package() -> Result<()> { click==8.1.7 # via flask flask==3.0.2 + # via -r requirements.in itsdangerous==2.1.2 # via flask markupsafe==2.1.5 @@ -5819,6 +5980,7 @@ fn pre_release_upper_bound_exclude() -> Result<()> { click==7.1.2 # via flask flask==1.1.4 + # via -r requirements.in itsdangerous==1.1.0 # via flask jinja2==2.11.3 @@ -5855,6 +6017,7 @@ fn pre_release_upper_bound_include() -> Result<()> { click==8.1.7 # via flask flask==2.0.0rc2 + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -5892,6 +6055,7 @@ fn pre_alias() -> Result<()> { click==7.1.2 # via flask flask==1.1.4 + # via -r requirements.in itsdangerous==1.1.0 # via flask jinja2==2.11.3 @@ -5931,6 +6095,9 @@ fn pre_release_constraint() -> Result<()> { click==8.1.7 # via flask flask==2.0.0rc2 + # via + # -c constraints.txt + # -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -5985,7 +6152,9 @@ dev = [ # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z pyproject.toml --extra dev pep517==0.13.1 + # via my-project (pyproject.toml) tomli==2.0.1 + # via my-project (pyproject.toml) ----- stderr ----- Resolved 2 packages in [TIME] @@ -6013,6 +6182,7 @@ fn editable_direct_dependency() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z [TEMP_DIR]/requirements.in --resolution lowest-direct -e ../../scripts/packages/setuptools_editable + # via -r [TEMP_DIR]/requirements.in iniconfig==0.1 # via setuptools-editable @@ -6043,6 +6213,7 @@ fn empty_index_url_env_var() -> Result<()> { --index-url https://pypi.org/simple anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -6075,6 +6246,7 @@ fn empty_extra_index_url_env_var() -> Result<()> { --index-url https://pypi.org/simple anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -6108,6 +6280,7 @@ fn empty_index_url_env_var_override() -> Result<()> { --index-url https://test.pypi.org/simple idna==2.7 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -6136,6 +6309,7 @@ fn index_url_env_var_override() -> Result<()> { --index-url https://test.pypi.org/simple idna==2.7 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -6156,7 +6330,7 @@ fn expand_env_var_requirements_txt() -> Result<()> { let requirements_dev_in = context.temp_dir.child("requirements-dev.in"); requirements_dev_in.write_str("anyio")?; - uv_snapshot!(context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -6164,6 +6338,7 @@ fn expand_env_var_requirements_txt() -> Result<()> { # 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 anyio==4.3.0 + # via -r requirements-dev.in idna==3.6 # via anyio sniffio==1.3.1 @@ -6297,6 +6472,7 @@ dev = [ # 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 -e . + # via -r requirements.in anyio @ https://files.pythonhosted.org/packages/bf/cd/d6d9bb1dadf73e7af02d18225cbd2c93f8552e13130484f1c8dcfece292b/anyio-4.2.0-py3-none-any.whl # via example idna==3.6 @@ -6347,6 +6523,7 @@ dev = ["setuptools"] # 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 --resolution=lowest-direct -e . + # via -r requirements.in packaging==24.0 # via setuptools-scm setuptools==69.2.0 @@ -6380,6 +6557,7 @@ fn metadata_2_2() -> Result<()> { boltons==23.1.1 # via pyo3-mixed pyo3-mixed @ https://files.pythonhosted.org/packages/2b/b8/e04b783d3569d5b61b1dcdfda683ac2e3617340539aecd0f099fbade0b4a/pyo3_mixed-2.1.5.tar.gz + # via -r requirements.in ----- stderr ----- Resolved 2 packages in [TIME] @@ -6414,8 +6592,11 @@ fn no_stream() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] requirements.in -c constraints.in hashb-foxglove-protocolbuffers-python==25.3.0.1.20240226043130+465630478360 + # via -r requirements.in protobuf==5.26.0 - # via hashb-foxglove-protocolbuffers-python + # via + # -c constraints.in + # hashb-foxglove-protocolbuffers-python ----- stderr ----- Resolved 2 packages in [TIME] @@ -6505,6 +6686,7 @@ fn compile_root_uri_editable() -> Result<()> { # 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 -e ${ROOT_PATH} + # via -r requirements.in black @ file://[WORKSPACE]/scripts/packages/root_editable/../black_editable # via root-editable @@ -6537,8 +6719,11 @@ fn compile_root_uri_non_editable() -> Result<()> { # 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 black @ ${BLACK_PATH} - # via root-editable + # via + # [WORKSPACE]/scripts/packages/black_editable/pyproject.toml + # root-editable root-editable @ ${ROOT_PATH} + # via [WORKSPACE]/scripts/packages/root_editable/pyproject.toml ----- stderr ----- Resolved 2 packages in [TIME] @@ -6604,6 +6789,7 @@ fn preserve_hashes_no_upgrade() -> Result<()> { --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -6695,6 +6881,7 @@ fn preserve_hashes_upgrade() -> Result<()> { --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -6782,6 +6969,7 @@ fn preserve_hashes_no_existing_hashes() -> Result<()> { --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -6882,6 +7070,7 @@ fn preserve_hashes_newer_version() -> Result<()> { --hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \ --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \ --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -6917,6 +7106,7 @@ fn unnamed_path_requirement() -> Result<()> { # httpx # poetry-editable black @ ../../scripts/packages/black_editable + # via [WORKSPACE]/scripts/packages/black_editable/pyproject.toml certifi==2024.2.2 # via # httpcore @@ -6936,10 +7126,13 @@ fn unnamed_path_requirement() -> Result<()> { # httpx # requests poetry-editable @ ../../scripts/packages/poetry_editable + # via [WORKSPACE]/scripts/packages/poetry_editable/pyproject.toml requests==2.31.0 # via setup-cfg-editable setup-cfg-editable @ ../../scripts/packages/setup_cfg_editable + # via -r [TEMP_DIR]/requirements.in setup-py-editable @ ../../scripts/packages/setup_py_editable + # via -r [TEMP_DIR]/requirements.in sniffio==1.3.1 # via # anyio @@ -6973,6 +7166,7 @@ fn unnamed_git_requirement() -> Result<()> { click==8.1.7 # via flask flask @ git+https://github.com/pallets/flask.git@735a4701d6d5e848241e7d7535db898efb62d400 + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -7011,6 +7205,7 @@ fn unnamed_https_requirement() -> Result<()> { click==8.1.7 # via flask flask @ https://github.com/pallets/flask/archive/refs/tags/3.0.2.tar.gz + # via -r requirements.in itsdangerous==2.1.2 # via flask jinja2==3.1.3 @@ -7047,6 +7242,7 @@ fn dynamic_dependencies() -> Result<()> { anyio==4.3.0 # via hatchling-dynamic hatchling-dynamic @ ../../scripts/packages/hatchling_dynamic + # via -r [TEMP_DIR]/requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -7086,6 +7282,7 @@ fn emit_marker_expression_exciting_linux() -> Result<()> { # Pinned dependencies known to be valid for: # platform_system == 'Linux' and python_version == '3.12' and platform_python_implementation == 'CPython' anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -7122,6 +7319,7 @@ fn emit_marker_expression_direct() -> Result<()> { # Pinned dependencies known to be valid for: # python_version == '3.12' and platform_python_implementation == 'CPython' and sys_platform == 'linux' and platform_system == 'Linux' anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -7201,6 +7399,7 @@ fn emit_marker_expression_pypy() -> Result<()> { # Pinned dependencies known to be valid for: # python_version == '3.12' and implementation_name == 'cpython' pendulum==3.0.0 + # via -r requirements.in python-dateutil==2.9.0.post0 # via # pendulum @@ -7236,6 +7435,7 @@ fn local_version_of_remote_package() -> Result<()> { # 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 anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -7272,6 +7472,7 @@ fn local_version_of_remote_package() -> Result<()> { # 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 anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -7303,6 +7504,7 @@ fn local_version_of_remote_package() -> Result<()> { # 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 --output-file requirements.txt anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -7331,6 +7533,7 @@ fn pendulum_no_tzdata_on_windows() -> Result<()> { # 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 pendulum==3.0.0 + # via -r requirements.in python-dateutil==2.9.0.post0 # via # pendulum @@ -7415,6 +7618,7 @@ requires-python = ">3.8" anyio @ file://[TEMP_DIR]/anyio/ # via lib example @ ./app + # via app/pyproject.toml idna==3.6 # via anyio lib @ file://[TEMP_DIR]/lib/ @@ -7498,8 +7702,11 @@ requires-python = ">3.8" # 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 --override overrides.txt anyio==3.7.0 - # via lib + # via + # --override overrides.txt + # lib example @ ./app + # via app/pyproject.toml idna==3.6 # via anyio lib @ file://[TEMP_DIR]/lib/ @@ -7609,8 +7816,12 @@ requires-python = ">3.8" # 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 --override overrides.txt --constraint constraints.txt anyio @ ./anyio - # via lib + # via + # -c constraints.txt + # --override overrides.txt + # lib example @ ./app + # via app/pyproject.toml idna==3.6 # via anyio lib @ file://[TEMP_DIR]/lib @@ -7646,7 +7857,7 @@ requires-python = ">3.8" let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str(".")?; - uv_snapshot!(context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -7656,6 +7867,7 @@ requires-python = ">3.8" click==8.1.7 # via flask example @ . + # via pyproject.toml flask==2.0.0rc1 # via example itsdangerous==2.1.2 @@ -7707,6 +7919,7 @@ requires-python = ">3.8" # 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 -e . + # via -r requirements.in click==8.1.7 # via flask flask==2.0.0rc1 @@ -7790,6 +8003,7 @@ fn compile_index_url_fallback() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --index-strategy unsafe-any-match requirements.in --no-deps jinja2==3.1.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -7829,6 +8043,7 @@ fn compile_index_url_fallback_prefer_primary() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --index-strategy unsafe-any-match requirements.in --no-deps anyio==3.5.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -7868,6 +8083,7 @@ fn compile_index_url_unsafe_highest() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --index-strategy unsafe-best-match requirements.in --no-deps anyio==4.3.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -7909,6 +8125,7 @@ fn compile_index_url_unsafe_lowest() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --resolution lowest --index-strategy unsafe-best-match requirements.in --no-deps anyio==1.0.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -7946,6 +8163,7 @@ fn emit_index_annotation_hide_password() -> Result<()> { # via requests # from https://pypi.org/simple requests==2.31.0 + # via -r requirements.in # from https://pypi.org/simple urllib3==2.2.1 # via requests @@ -7985,6 +8203,7 @@ fn emit_index_annotation_pypi_org_simple() -> Result<()> { # via requests # from https://pypi.org/simple requests==2.31.0 + # via -r requirements.in # from https://pypi.org/simple urllib3==2.2.1 # via requests @@ -8093,8 +8312,10 @@ fn emit_index_annotation_multiple_indexes() -> Result<()> { # 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 requests==2.5.4.1 + # via -r requirements.in # from https://test.pypi.org/simple uv==0.1.24 + # via -r requirements.in # from https://pypi.org/simple ----- stderr ----- @@ -8150,6 +8371,7 @@ fn python_platform() -> Result<()> { # 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 --python-platform aarch64-unknown-linux-gnu black==24.3.0 + # via -r requirements.in click==8.1.7 # via black mypy-extensions==1.0.0 @@ -8178,6 +8400,7 @@ fn python_platform() -> Result<()> { # 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 --python-platform x86_64-pc-windows-msvc black==24.3.0 + # via -r requirements.in click==8.1.7 # via black colorama==0.4.6 @@ -8227,6 +8450,7 @@ fn resolve_configuration() -> Result<()> { anyio==3.0.1 \ --hash=sha256:1ef7622396ab55829d4236a6f75e2199df6d26a4ba79bea0cb942a5fd2f79a23 \ --hash=sha256:ed71f7542ef39875b65def219794d9dcb0a48c571317b13612c12b1f292701b5 + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -8253,6 +8477,7 @@ fn resolve_configuration() -> Result<()> { anyio==4.3.0 \ --hash=sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8 \ --hash=sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6 + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -8278,6 +8503,7 @@ fn resolve_configuration() -> Result<()> { # 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 --resolution=highest --no-generate-hashes anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -8307,6 +8533,7 @@ fn resolve_configuration() -> Result<()> { anyio==3.0.1 \ --hash=sha256:1ef7622396ab55829d4236a6f75e2199df6d26a4ba79bea0cb942a5fd2f79a23 \ --hash=sha256:ed71f7542ef39875b65def219794d9dcb0a48c571317b13612c12b1f292701b5 + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -8333,6 +8560,7 @@ fn resolve_configuration() -> Result<()> { # 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 anyio==4.3.0 + # via -r requirements.in idna==3.6 # via anyio sniffio==1.3.1 @@ -8366,6 +8594,7 @@ fn resolve_configuration() -> Result<()> { anyio==3.0.1 \ --hash=sha256:1ef7622396ab55829d4236a6f75e2199df6d26a4ba79bea0cb942a5fd2f79a23 \ --hash=sha256:ed71f7542ef39875b65def219794d9dcb0a48c571317b13612c12b1f292701b5 + # via -r requirements.in idna==3.6 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f @@ -8417,6 +8646,7 @@ fn git_source_default_branch() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview pyproject.toml uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@[COMMIT] + # via project (pyproject.toml) ----- stderr ----- Resolved 1 package in [TIME] @@ -8444,7 +8674,7 @@ fn git_source_branch() -> Result<()> { uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", branch = "test-branch" } "#})?; - uv_snapshot!(context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("--preview") .arg("pyproject.toml"), @r###" success: true @@ -8453,6 +8683,7 @@ fn git_source_branch() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview pyproject.toml uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via project (pyproject.toml) ----- stderr ----- Resolved 1 package in [TIME] @@ -8480,7 +8711,7 @@ fn git_source_tag() -> Result<()> { uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", tag = "test-tag" } "#})?; - uv_snapshot!(context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("--preview") .arg("pyproject.toml"), @r###" success: true @@ -8489,6 +8720,7 @@ fn git_source_tag() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview pyproject.toml uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via project (pyproject.toml) ----- stderr ----- Resolved 1 package in [TIME] @@ -8516,7 +8748,7 @@ fn git_source_long_commit() -> Result<()> { uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", rev = "0dacfd662c64cb4ceb16e6cf65a157a8b715b979" } "#})?; - uv_snapshot!(context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("--preview") .arg("pyproject.toml"), @r###" success: true @@ -8525,6 +8757,7 @@ fn git_source_long_commit() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview pyproject.toml uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via project (pyproject.toml) ----- stderr ----- Resolved 1 package in [TIME] @@ -8552,7 +8785,7 @@ fn git_source_short_commit() -> Result<()> { uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", rev = "0dacfd6" } "#})?; - uv_snapshot!(context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("--preview") .arg("pyproject.toml"), @r###" success: true @@ -8561,6 +8794,7 @@ fn git_source_short_commit() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview pyproject.toml uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0dacfd662c64cb4ceb16e6cf65a157a8b715b979 + # via project (pyproject.toml) ----- stderr ----- Resolved 1 package in [TIME] @@ -8588,7 +8822,7 @@ fn git_source_refs() -> Result<()> { uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", rev = "refs/pull/4/head" } "#})?; - uv_snapshot!(context.compile() + uv_snapshot!(context.filters(), context.compile() .arg("--preview") .arg("pyproject.toml"), @r###" success: true @@ -8597,6 +8831,7 @@ fn git_source_refs() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview pyproject.toml uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@9d01a806f17ddacb9c7b66b1b68574adf790b63f + # via project (pyproject.toml) ----- stderr ----- Resolved 1 package in [TIME] @@ -8673,11 +8908,13 @@ fn warn_missing_constraint() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview pyproject.toml anyio @ https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl + # via foo (pyproject.toml) idna==3.6 # via anyio sniffio==1.3.1 # via anyio tqdm==4.66.2 + # via foo (pyproject.toml) ----- stderr ----- warning: Missing version constraint (e.g., a lower bound) for `tqdm` @@ -8712,11 +8949,13 @@ fn dont_warn_missing_constraint_without_sources() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview pyproject.toml anyio==4.3.0 + # via foo (pyproject.toml) idna==3.6 # via anyio sniffio==1.3.1 # via anyio tqdm==4.66.2 + # via foo (pyproject.toml) ----- stderr ----- Resolved 4 packages in [TIME] @@ -8733,15 +8972,13 @@ fn tool_uv_sources() -> Result<()> { let pyproject_toml = context.temp_dir.child(require_path); pyproject_toml.write_str(indoc! {r#" [project] - name = "foo" + name = "project" version = "0.0.0" dependencies = [ "tqdm>4,<=5", "packaging @ git+https://github.com/pypa/packaging@32deafe8668a2130a3366b98154914d188f3718e", "poetry_editable", "urllib3 @ https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl", - # Windows consistency - "colorama>0.4,<5", ] [project.optional-dependencies] @@ -8771,12 +9008,8 @@ fn tool_uv_sources() -> Result<()> { .join("poetry_editable/poetry_editable/__init__.py"), )?; - let mut filters = context.filters(); - // Remove windows-only tqdm -> colorama dependency - filters.push((" # via tqdm\n", "")); - // Install the editable packages. - uv_snapshot!(filters, windows_filters=false, context.compile() + uv_snapshot!(context.compile() .arg("--preview") .arg(require_path) .arg("--extra") @@ -8787,21 +9020,25 @@ fn tool_uv_sources() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z --preview some_dir/pyproject.toml --extra utils -e ../poetry_editable + # via project (some_dir/pyproject.toml) anyio==4.3.0 # via poetry-editable boltons @ git+https://github.com/mahmoud/boltons@57fbaa9b673ed85b32458b31baeeae230520e4a0 - colorama==0.4.6 + # via project (some_dir/pyproject.toml) idna==3.6 # via anyio packaging @ git+https://github.com/pypa/packaging@32deafe8668a2130a3366b98154914d188f3718e + # via project (some_dir/pyproject.toml) sniffio==1.3.1 # via anyio tqdm @ https://files.pythonhosted.org/packages/a5/d6/502a859bac4ad5e274255576cd3e15ca273cdb91731bc39fb840dd422ee9/tqdm-4.66.0-py3-none-any.whl + # via project (some_dir/pyproject.toml) urllib3 @ https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + # via project (some_dir/pyproject.toml) ----- stderr ----- Built 1 editable in [TIME] - Resolved 9 packages in [TIME] + Resolved 8 packages in [TIME] "### ); diff --git a/crates/uv/tests/pip_compile_scenarios.rs b/crates/uv/tests/pip_compile_scenarios.rs index 815def6d3..5a9012467 100644 --- a/crates/uv/tests/pip_compile_scenarios.rs +++ b/crates/uv/tests/pip_compile_scenarios.rs @@ -82,6 +82,7 @@ fn incompatible_python_compatible_override() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile requirements.in --cache-dir [CACHE_DIR] --python-version=3.11 package-a==1.0.0 + # via -r requirements.in ----- stderr ----- warning: The requested Python version 3.11 is not available; 3.9.[X] will be used to build dependencies instead. @@ -240,6 +241,7 @@ fn incompatible_python_compatible_override_available_no_wheels() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile requirements.in --cache-dir [CACHE_DIR] --python-version=3.11 package-a==1.0.0 + # via -r requirements.in ----- stderr ----- Resolved 1 package in [TIME] @@ -456,6 +458,7 @@ fn python_patch_override_patch_compatible() -> Result<()> { # This file was autogenerated by uv via the following command: # uv pip compile requirements.in --cache-dir [CACHE_DIR] --python-version=3.8.0 package-a==1.0.0 + # via -r requirements.in ----- stderr ----- warning: The requested Python version 3.8.0 is not available; 3.8.18 will be used to build dependencies instead.