diff --git a/crates/distribution-types/src/annotation.rs b/crates/distribution-types/src/annotation.rs index 026135af4c19..2080cc97ed03 100644 --- a/crates/distribution-types/src/annotation.rs +++ b/crates/distribution-types/src/annotation.rs @@ -1,46 +1,38 @@ use std::collections::{BTreeMap, BTreeSet}; -use std::path::PathBuf; use url::Url; -use pep508_rs::VerbatimUrl; +use pep508_rs::{RequirementOrigin, VerbatimUrl}; use uv_fs::Simplified; use uv_normalize::PackageName; /// Source of a dependency, e.g., a `-r requirements.txt` file. #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum SourceAnnotation { - /// A `pyproject.toml` file. - PyProject { - path: PathBuf, - project_name: Option, - }, /// A `-c constraints.txt` file. - Constraint(PathBuf), + Constraint(RequirementOrigin), /// An `--override overrides.txt` file. - Override(PathBuf), + Override(RequirementOrigin), /// A `-r requirements.txt` file. - Requirement(PathBuf), + Requirement(RequirementOrigin), } 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()) + Self::Requirement(origin) => match origin { + RequirementOrigin::File(path) => { + write!(f, "-r {}", path.user_display()) } + RequirementOrigin::Project(path, project_name) => { + write!(f, "{project_name} ({})", path.user_display()) + } + }, + Self::Constraint(origin) => { + write!(f, "-c {}", origin.path().user_display()) + } + Self::Override(origin) => { + write!(f, "--override {}", origin.path().user_display()) } } } diff --git a/crates/distribution-types/src/requirement.rs b/crates/distribution-types/src/requirement.rs index 47d3b6ac6df6..7b8367f98be5 100644 --- a/crates/distribution-types/src/requirement.rs +++ b/crates/distribution-types/src/requirement.rs @@ -5,7 +5,7 @@ use indexmap::IndexMap; use url::Url; use pep440_rs::VersionSpecifiers; -use pep508_rs::{MarkerEnvironment, MarkerTree, VerbatimUrl, VersionOrUrl}; +use pep508_rs::{MarkerEnvironment, MarkerTree, RequirementOrigin, VerbatimUrl, VersionOrUrl}; use uv_git::GitReference; use uv_normalize::{ExtraName, PackageName}; @@ -28,7 +28,7 @@ pub struct Requirement { pub extras: Vec, pub marker: Option, pub source: RequirementSource, - pub path: Option, + pub origin: Option, } impl Requirement { @@ -63,7 +63,7 @@ impl Requirement { extras: requirement.extras, marker: requirement.marker, source, - path: requirement.source, + origin: requirement.origin, }) } } diff --git a/crates/distribution-types/src/resolution.rs b/crates/distribution-types/src/resolution.rs index 38391c4f7e87..b8b9ba770670 100644 --- a/crates/distribution-types/src/resolution.rs +++ b/crates/distribution-types/src/resolution.rs @@ -139,7 +139,7 @@ impl From<&ResolvedDist> for Requirement { extras: vec![], marker: None, source, - path: None, + origin: None, } } } diff --git a/crates/distribution-types/src/specified_requirement.rs b/crates/distribution-types/src/specified_requirement.rs index d750f43819f0..6d0ea8b278bc 100644 --- a/crates/distribution-types/src/specified_requirement.rs +++ b/crates/distribution-types/src/specified_requirement.rs @@ -14,8 +14,6 @@ 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 d4b2e367da4d..09bdbf9618bf 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, PathBuf}; +use std::path::Path; use std::str::FromStr; #[cfg(feature = "pyo3")] @@ -49,6 +49,7 @@ use pep440_rs::{Version, VersionSpecifier, VersionSpecifiers}; #[cfg(feature = "non-pep508-extensions")] pub use unnamed::UnnamedRequirement; // Parity with the crates.io version of pep508_rs +pub use origin::RequirementOrigin; pub use uv_normalize::{ExtraName, InvalidNameError, PackageName}; pub use verbatim_url::{ expand_env_vars, split_scheme, strip_host, Scheme, VerbatimUrl, VerbatimUrlError, @@ -56,6 +57,7 @@ pub use verbatim_url::{ mod cursor; mod marker; +mod origin; #[cfg(feature = "non-pep508-extensions")] mod unnamed; mod verbatim_url; @@ -149,14 +151,14 @@ pub struct Requirement { /// Those are a nested and/or tree. pub marker: Option, /// The source file containing the requirement. - pub source: Option, + pub origin: Option, } impl Requirement { /// Set the source file containing the requirement. #[must_use] - pub fn with_source(self, source: Option) -> Self { - Self { source, ..self } + pub fn with_origin(self, origin: Option) -> Self { + Self { origin, ..self } } } @@ -492,7 +494,7 @@ impl Requirement { extras, version_or_url, marker, - source, + origin, } = self; Requirement { name, @@ -505,7 +507,7 @@ impl Requirement { Some(VersionOrUrl::Url(url)) => Some(VersionOrUrl::Url(U::from(url))), }, marker, - source, + origin, } } } @@ -1029,7 +1031,7 @@ fn parse_pep508_requirement( extras, version_or_url: requirement_kind, marker, - source: None, + origin: None, }) } @@ -1171,7 +1173,7 @@ mod tests { operator: MarkerOperator::LessThan, r_value: MarkerValue::QuotedString("2.7".to_string()), })), - source: None, + origin: None, }; assert_eq!(requests, expected); } @@ -1397,7 +1399,7 @@ mod tests { extras: vec![], marker: None, version_or_url: Some(VersionOrUrl::Url(Url::parse(url).unwrap())), - source: None, + origin: None, }; assert_eq!(pip_url, expected); } diff --git a/crates/pep508-rs/src/origin.rs b/crates/pep508-rs/src/origin.rs new file mode 100644 index 000000000000..e8dd7d11070a --- /dev/null +++ b/crates/pep508-rs/src/origin.rs @@ -0,0 +1,22 @@ +use std::path::{Path, PathBuf}; + +use uv_normalize::PackageName; + +/// The origin of a dependency, e.g., a `-r requirements.txt` file. +#[derive(Hash, Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub enum RequirementOrigin { + /// The requirement was provided via a standalone file (e.g., a `requirements.txt` file). + File(PathBuf), + /// The requirement was provided via a local project (e.g., a `pyproject.toml` file). + Project(PathBuf, PackageName), +} + +impl RequirementOrigin { + /// Returns the path of the requirement origin. + pub fn path(&self) -> &Path { + match self { + RequirementOrigin::File(path) => path.as_path(), + RequirementOrigin::Project(path, _) => path.as_path(), + } + } +} diff --git a/crates/pep508-rs/src/unnamed.rs b/crates/pep508-rs/src/unnamed.rs index 36dcd26c5ab3..dbda9f7395ec 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, PathBuf}; +use std::path::Path; use std::str::FromStr; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -10,8 +10,8 @@ use uv_normalize::ExtraName; use crate::marker::parse_markers_cursor; use crate::{ expand_env_vars, parse_extras_cursor, split_extras, split_scheme, strip_host, Cursor, - MarkerEnvironment, MarkerTree, Pep508Error, Pep508ErrorSource, Scheme, VerbatimUrl, - VerbatimUrlError, + MarkerEnvironment, MarkerTree, Pep508Error, Pep508ErrorSource, RequirementOrigin, Scheme, + VerbatimUrl, VerbatimUrlError, }; /// A PEP 508-like, direct URL dependency specifier without a package name. @@ -31,7 +31,7 @@ pub struct UnnamedRequirement { /// Those are a nested and/or tree. pub marker: Option, /// The source file containing the requirement. - pub source: Option, + pub origin: Option, } impl UnnamedRequirement { @@ -46,8 +46,8 @@ impl UnnamedRequirement { /// Set the source file containing the requirement. #[must_use] - pub fn with_source(self, source: Option) -> Self { - Self { source, ..self } + pub fn with_origin(self, origin: Option) -> Self { + Self { origin, ..self } } } @@ -167,7 +167,7 @@ fn parse_unnamed_requirement( url, extras, marker, - source: None, + origin: None, }) } diff --git a/crates/requirements-txt/src/lib.rs b/crates/requirements-txt/src/lib.rs index b44ad2e26657..c28b2a189707 100644 --- a/crates/requirements-txt/src/lib.rs +++ b/crates/requirements-txt/src/lib.rs @@ -48,8 +48,8 @@ use distribution_types::{ ParsedUrlError, Requirement, UnresolvedRequirement, UnresolvedRequirementSpecification, }; use pep508_rs::{ - expand_env_vars, split_scheme, strip_host, Extras, Pep508Error, Pep508ErrorSource, Scheme, - VerbatimUrl, + expand_env_vars, split_scheme, strip_host, Extras, Pep508Error, Pep508ErrorSource, + RequirementOrigin, Scheme, VerbatimUrl, }; #[cfg(feature = "http")] use uv_client::BaseClient; @@ -171,7 +171,7 @@ pub struct EditableRequirement { /// The local path to the editable. pub path: PathBuf, /// The source file containing the requirement. - pub source: Option, + pub origin: Option, } impl EditableRequirement { @@ -196,7 +196,7 @@ impl EditableRequirement { /// We disallow URLs with schemes other than `file://` (e.g., `https://...`). pub fn parse( given: &str, - source: Option<&Path>, + origin: Option<&Path>, working_dir: impl AsRef, ) -> Result { // Identify the extras. @@ -275,7 +275,7 @@ impl EditableRequirement { url, extras, path, - source: source.map(Path::to_path_buf), + origin: origin.map(Path::to_path_buf).map(RequirementOrigin::File), }) } @@ -316,8 +316,6 @@ 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 @@ -337,7 +335,6 @@ impl TryFrom for UnresolvedRequirementSpecification { } }, hashes: value.hashes, - path: value.path, }) } } @@ -711,7 +708,6 @@ fn parse_entry( 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()); @@ -829,7 +825,9 @@ fn parse_requirement_and_hashes( } let requirement = RequirementsTxtRequirement::parse(requirement, working_dir) - .map(|requirement| requirement.with_source(source.map(Path::to_path_buf))) + .map(|requirement| { + requirement.with_origin(source.map(Path::to_path_buf).map(RequirementOrigin::File)) + }) .map_err(|err| match err { RequirementsTxtRequirementError::ParsedUrl(err) => { RequirementsTxtParserError::ParsedUrl { @@ -1815,15 +1813,14 @@ mod test { extras: [], version_or_url: None, marker: None, - source: Some( - "/subdir/sibling.txt", + origin: Some( + File( + "/subdir/sibling.txt", + ), ), }, ), hashes: [], - path: Some( - "/subdir/sibling.txt", - ), }, ], constraints: [], @@ -1880,15 +1877,14 @@ mod test { extras: [], version_or_url: None, marker: None, - source: Some( - "/requirements.txt", + origin: Some( + File( + "/requirements.txt", + ), ), }, ), hashes: [], - path: Some( - "/requirements.txt", - ), }, ], constraints: [], @@ -1968,8 +1964,10 @@ mod test { }, extras: [], path: "/foo/bar", - source: Some( - "/grandchild.txt", + origin: Some( + File( + "/grandchild.txt", + ), ), }, ], @@ -2077,15 +2075,14 @@ mod test { extras: [], version_or_url: None, marker: None, - source: Some( - "/./sibling.txt", + origin: Some( + File( + "/./sibling.txt", + ), ), }, ), hashes: [], - path: Some( - "/./sibling.txt", - ), }, RequirementEntry { requirement: Named( @@ -2107,17 +2104,16 @@ mod test { ), ), marker: None, - source: Some( - "/requirements.txt", + origin: Some( + File( + "/requirements.txt", + ), ), }, ), hashes: [ "sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", ], - path: Some( - "/requirements.txt", - ), }, RequirementEntry { requirement: Named( @@ -2139,17 +2135,16 @@ mod test { ), ), marker: None, - source: Some( - "/requirements.txt", + origin: Some( + File( + "/requirements.txt", + ), ), }, ), hashes: [ "sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321", ], - path: Some( - "/requirements.txt", - ), }, RequirementEntry { requirement: Named( @@ -2171,15 +2166,14 @@ mod test { ), ), marker: None, - source: Some( - "/requirements.txt", + origin: Some( + File( + "/requirements.txt", + ), ), }, ), hashes: [], - path: Some( - "/requirements.txt", - ), }, RequirementEntry { requirement: Named( @@ -2201,15 +2195,14 @@ mod test { ), ), marker: None, - source: Some( - "/requirements.txt", + origin: Some( + File( + "/requirements.txt", + ), ), }, ), hashes: [], - path: Some( - "/requirements.txt", - ), }, ], constraints: [], diff --git a/crates/requirements-txt/src/requirement.rs b/crates/requirements-txt/src/requirement.rs index aacd26884693..9b8420b20da6 100644 --- a/crates/requirements-txt/src/requirement.rs +++ b/crates/requirements-txt/src/requirement.rs @@ -1,9 +1,9 @@ -use std::path::{Path, PathBuf}; +use std::path::Path; use thiserror::Error; use distribution_types::ParsedUrlError; -use pep508_rs::{Pep508Error, Pep508ErrorSource, UnnamedRequirement}; +use pep508_rs::{Pep508Error, Pep508ErrorSource, RequirementOrigin, UnnamedRequirement}; /// A requirement specifier in a `requirements.txt` file. /// @@ -21,10 +21,10 @@ pub enum RequirementsTxtRequirement { impl RequirementsTxtRequirement { /// Set the source file containing the requirement. #[must_use] - pub fn with_source(self, path: Option) -> Self { + pub fn with_origin(self, origin: Option) -> Self { match self { - Self::Named(requirement) => Self::Named(requirement.with_source(path)), - Self::Unnamed(requirement) => Self::Unnamed(requirement.with_source(path)), + Self::Named(requirement) => Self::Named(requirement.with_origin(origin)), + Self::Unnamed(requirement) => Self::Unnamed(requirement.with_origin(origin)), } } } 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 aa9549525dba..60d86edb04b7 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -54,15 +53,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -84,15 +82,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -114,15 +111,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -144,15 +140,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -174,15 +169,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/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 bef1a11b8f27..5fa0a3a74002 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-a.txt", + origin: Some( + File( + "/constraints-a.txt", + ), ), }, ), hashes: [], - path: Some( - "/constraints-a.txt", - ), }, ], constraints: [ @@ -54,8 +53,10 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-b.txt", + origin: Some( + File( + "/constraints-b.txt", + ), ), }, Requirement { @@ -76,8 +77,10 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-b.txt", + origin: Some( + File( + "/constraints-b.txt", + ), ), }, ], 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 8cb30a4bf81c..5068a0870d42 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-b.txt", + origin: Some( + File( + "/constraints-b.txt", + ), ), }, ), hashes: [], - path: Some( - "/constraints-b.txt", - ), }, RequirementEntry { requirement: Named( @@ -54,15 +53,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-b.txt", + origin: Some( + File( + "/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 d19aafc7e7b7..63c3db751b30 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,15 +13,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/editable.txt", + origin: Some( + File( + "/editable.txt", + ), ), }, ), hashes: [], - path: Some( - "/editable.txt", - ), }, RequirementEntry { requirement: Named( @@ -59,15 +58,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/editable.txt", + origin: Some( + File( + "/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 eba1e0a78087..6073a0df0330 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/for-poetry.txt", + origin: Some( + File( + "/for-poetry.txt", + ), ), }, ), hashes: [], - path: Some( - "/for-poetry.txt", - ), }, RequirementEntry { requirement: Named( @@ -54,15 +53,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/for-poetry.txt", + origin: Some( + File( + "/for-poetry.txt", + ), ), }, ), hashes: [], - path: Some( - "/for-poetry.txt", - ), }, RequirementEntry { requirement: Named( @@ -73,15 +71,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/for-poetry.txt", + origin: Some( + File( + "/for-poetry.txt", + ), ), }, ), hashes: [], - path: Some( - "/for-poetry.txt", - ), }, RequirementEntry { requirement: Named( @@ -111,15 +108,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/for-poetry.txt", + origin: Some( + File( + "/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 5b1e68b12e3a..431b25b2cd85 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,15 +13,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/include-b.txt", + origin: Some( + File( + "/include-b.txt", + ), ), }, ), hashes: [], - path: Some( - "/include-b.txt", - ), }, RequirementEntry { requirement: Named( @@ -43,15 +42,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/include-a.txt", + origin: Some( + File( + "/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 8e8e003e61e4..9cbe6c861ad6 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,15 +13,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/include-b.txt", + origin: Some( + File( + "/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 4a684c8b7c84..e6c891fb3181 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,17 +51,16 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), hashes: [ "sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe", ], - path: Some( - "/poetry-with-hashes.txt", - ), }, RequirementEntry { requirement: Named( @@ -110,17 +109,16 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), hashes: [ "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305", ], - path: Some( - "/poetry-with-hashes.txt", - ), }, RequirementEntry { requirement: Named( @@ -180,17 +178,16 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), hashes: [ "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1", ], - path: Some( - "/poetry-with-hashes.txt", - ), }, RequirementEntry { requirement: Named( @@ -239,8 +236,10 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), @@ -248,9 +247,6 @@ RequirementsTxt { "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a", ], - path: Some( - "/poetry-with-hashes.txt", - ), }, RequirementEntry { requirement: Named( @@ -299,8 +295,10 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), @@ -310,9 +308,6 @@ 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 eadd880b8a3b..c57791d2d596 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/small.txt", + origin: Some( + File( + "/small.txt", + ), ), }, ), hashes: [], - path: Some( - "/small.txt", - ), }, RequirementEntry { requirement: Named( @@ -54,15 +53,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/small.txt", + origin: Some( + File( + "/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 8d5fce0286bd..3b03dc8eddb5 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,15 +13,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/whitespace.txt", + origin: Some( + File( + "/whitespace.txt", + ), ), }, ), hashes: [], - path: Some( - "/whitespace.txt", - ), }, RequirementEntry { requirement: Named( @@ -59,15 +58,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/whitespace.txt", + origin: Some( + File( + "/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 aa9549525dba..60d86edb04b7 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -54,15 +53,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -84,15 +82,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -114,15 +111,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -144,15 +140,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/basic.txt", + ), ), }, ), hashes: [], - path: Some( - "/basic.txt", - ), }, RequirementEntry { requirement: Named( @@ -174,15 +169,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/basic.txt", + origin: Some( + File( + "/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 bef1a11b8f27..5fa0a3a74002 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-a.txt", + origin: Some( + File( + "/constraints-a.txt", + ), ), }, ), hashes: [], - path: Some( - "/constraints-a.txt", - ), }, ], constraints: [ @@ -54,8 +53,10 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-b.txt", + origin: Some( + File( + "/constraints-b.txt", + ), ), }, Requirement { @@ -76,8 +77,10 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-b.txt", + origin: Some( + File( + "/constraints-b.txt", + ), ), }, ], 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 8cb30a4bf81c..5068a0870d42 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-b.txt", + origin: Some( + File( + "/constraints-b.txt", + ), ), }, ), hashes: [], - path: Some( - "/constraints-b.txt", - ), }, RequirementEntry { requirement: Named( @@ -54,15 +53,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/constraints-b.txt", + origin: Some( + File( + "/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 eba1e0a78087..6073a0df0330 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/for-poetry.txt", + origin: Some( + File( + "/for-poetry.txt", + ), ), }, ), hashes: [], - path: Some( - "/for-poetry.txt", - ), }, RequirementEntry { requirement: Named( @@ -54,15 +53,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/for-poetry.txt", + origin: Some( + File( + "/for-poetry.txt", + ), ), }, ), hashes: [], - path: Some( - "/for-poetry.txt", - ), }, RequirementEntry { requirement: Named( @@ -73,15 +71,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/for-poetry.txt", + origin: Some( + File( + "/for-poetry.txt", + ), ), }, ), hashes: [], - path: Some( - "/for-poetry.txt", - ), }, RequirementEntry { requirement: Named( @@ -111,15 +108,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/for-poetry.txt", + origin: Some( + File( + "/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 5b1e68b12e3a..431b25b2cd85 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,15 +13,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/include-b.txt", + origin: Some( + File( + "/include-b.txt", + ), ), }, ), hashes: [], - path: Some( - "/include-b.txt", - ), }, RequirementEntry { requirement: Named( @@ -43,15 +42,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/include-a.txt", + origin: Some( + File( + "/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 8e8e003e61e4..9cbe6c861ad6 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,15 +13,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/include-b.txt", + origin: Some( + File( + "/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 4a684c8b7c84..e6c891fb3181 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,17 +51,16 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), hashes: [ "sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe", ], - path: Some( - "/poetry-with-hashes.txt", - ), }, RequirementEntry { requirement: Named( @@ -110,17 +109,16 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), hashes: [ "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305", ], - path: Some( - "/poetry-with-hashes.txt", - ), }, RequirementEntry { requirement: Named( @@ -180,17 +178,16 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), hashes: [ "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1", ], - path: Some( - "/poetry-with-hashes.txt", - ), }, RequirementEntry { requirement: Named( @@ -239,8 +236,10 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), @@ -248,9 +247,6 @@ RequirementsTxt { "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a", ], - path: Some( - "/poetry-with-hashes.txt", - ), }, RequirementEntry { requirement: Named( @@ -299,8 +295,10 @@ RequirementsTxt { ], ), ), - source: Some( - "/poetry-with-hashes.txt", + origin: Some( + File( + "/poetry-with-hashes.txt", + ), ), }, ), @@ -310,9 +308,6 @@ 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 eadd880b8a3b..c57791d2d596 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,15 +24,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/small.txt", + origin: Some( + File( + "/small.txt", + ), ), }, ), hashes: [], - path: Some( - "/small.txt", - ), }, RequirementEntry { requirement: Named( @@ -54,15 +53,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/small.txt", + origin: Some( + File( + "/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 ef554ceefd73..f935f7e457ec 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,15 +25,14 @@ RequirementsTxt { }, extras: [], marker: None, - source: Some( - "/bare-url.txt", + origin: Some( + File( + "/bare-url.txt", + ), ), }, ), hashes: [], - path: Some( - "/bare-url.txt", - ), }, RequirementEntry { requirement: Unnamed( @@ -60,15 +59,14 @@ RequirementsTxt { ), ], marker: None, - source: Some( - "/bare-url.txt", + origin: Some( + File( + "/bare-url.txt", + ), ), }, ), hashes: [], - path: Some( - "/bare-url.txt", - ), }, RequirementEntry { requirement: Unnamed( @@ -91,15 +89,14 @@ RequirementsTxt { }, extras: [], marker: None, - source: Some( - "/bare-url.txt", + origin: Some( + File( + "/bare-url.txt", + ), ), }, ), hashes: [], - path: Some( - "/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 8d5fce0286bd..3b03dc8eddb5 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,15 +13,14 @@ RequirementsTxt { extras: [], version_or_url: None, marker: None, - source: Some( - "/whitespace.txt", + origin: Some( + File( + "/whitespace.txt", + ), ), }, ), hashes: [], - path: Some( - "/whitespace.txt", - ), }, RequirementEntry { requirement: Named( @@ -59,15 +58,14 @@ RequirementsTxt { ), ), marker: None, - source: Some( - "/whitespace.txt", + origin: Some( + File( + "/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 cfbd36cce379..2611057d7828 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,15 +25,14 @@ RequirementsTxt { }, extras: [], marker: None, - source: Some( - "/bare-url.txt", + origin: Some( + File( + "/bare-url.txt", + ), ), }, ), hashes: [], - path: Some( - "/bare-url.txt", - ), }, RequirementEntry { requirement: Unnamed( @@ -60,15 +59,14 @@ RequirementsTxt { ), ], marker: None, - source: Some( - "/bare-url.txt", + origin: Some( + File( + "/bare-url.txt", + ), ), }, ), hashes: [], - path: Some( - "/bare-url.txt", - ), }, RequirementEntry { requirement: Unnamed( @@ -91,15 +89,14 @@ RequirementsTxt { }, extras: [], marker: None, - source: Some( - "/bare-url.txt", + origin: Some( + File( + "/bare-url.txt", + ), ), }, ), hashes: [], - path: Some( - "/bare-url.txt", - ), }, ], constraints: [], diff --git a/crates/uv-dev/src/resolve_many.rs b/crates/uv-dev/src/resolve_many.rs index 3e10fd886423..81a85b895738 100644 --- a/crates/uv-dev/src/resolve_many.rs +++ b/crates/uv-dev/src/resolve_many.rs @@ -132,7 +132,7 @@ pub(crate) async fn resolve_many(args: ResolveManyArgs) -> Result<()> { extras: requirement.extras, version_or_url: Some(equals_version), marker: None, - source: requirement.source, + origin: requirement.origin, } } else { requirement diff --git a/crates/uv-installer/src/site_packages.rs b/crates/uv-installer/src/site_packages.rs index 63643aceead2..77bb7ca4031b 100644 --- a/crates/uv-installer/src/site_packages.rs +++ b/crates/uv-installer/src/site_packages.rs @@ -342,7 +342,6 @@ impl<'a> SitePackages<'a> { Requirement::from_pep508(dependency)?, ), hashes: vec![], - path: None, }; if seen.insert(dependency.clone()) { stack.push(dependency); @@ -407,7 +406,6 @@ 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 c578cc586c41..2691aacfffa2 100644 --- a/crates/uv-requirements/src/pyproject.rs +++ b/crates/uv-requirements/src/pyproject.rs @@ -22,7 +22,7 @@ use url::Url; use distribution_types::{ParsedUrlError, Requirement, RequirementSource, Requirements}; use pep440_rs::VersionSpecifiers; -use pep508_rs::{VerbatimUrl, VersionOrUrl}; +use pep508_rs::{RequirementOrigin, VerbatimUrl, VersionOrUrl}; use uv_configuration::PreviewMode; use uv_fs::Simplified; use uv_git::GitReference; @@ -333,8 +333,9 @@ pub(crate) fn lower_requirements( let dependencies = dependencies .iter() .map(|dependency| { - let requirement = pep508_rs::Requirement::from_str(dependency)? - .with_source(Some(pyproject_path.to_path_buf())); + let requirement = pep508_rs::Requirement::from_str(dependency)?.with_origin(Some( + RequirementOrigin::Project(pyproject_path.to_path_buf(), project_name.clone()), + )); let name = requirement.name.clone(); lower_requirement( requirement, @@ -354,8 +355,12 @@ pub(crate) fn lower_requirements( let dependencies: Vec<_> = dependencies .iter() .map(|dependency| { - let requirement = pep508_rs::Requirement::from_str(dependency)? - .with_source(Some(pyproject_path.to_path_buf())); + let requirement = pep508_rs::Requirement::from_str(dependency)?.with_origin( + Some(RequirementOrigin::Project( + pyproject_path.to_path_buf(), + project_name.clone(), + )), + ); let name = requirement.name.clone(); lower_requirement( requirement, @@ -537,7 +542,7 @@ pub(crate) fn lower_requirement( extras: requirement.extras, marker: requirement.marker, source, - path: Some(project_dir.join("pyproject.toml")), + origin: requirement.origin, }) } diff --git a/crates/uv-requirements/src/source_tree.rs b/crates/uv-requirements/src/source_tree.rs index 6da664f820ee..38a353b30cc3 100644 --- a/crates/uv-requirements/src/source_tree.rs +++ b/crates/uv-requirements/src/source_tree.rs @@ -8,6 +8,7 @@ use url::Url; use distribution_types::{ BuildableSource, HashPolicy, PathSourceUrl, Requirement, SourceUrl, VersionId, }; +use pep508_rs::RequirementOrigin; use uv_client::RegistryClient; use uv_distribution::{DistributionDatabase, Reporter}; @@ -77,20 +78,27 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> { } /// Infer the package name for a given "unnamed" requirement. - async fn resolve_source_tree(&self, source_tree: &Path) -> Result> { + async fn resolve_source_tree(&self, path: &Path) -> Result> { // Convert to a buildable source. - let path = fs_err::canonicalize(source_tree).with_context(|| { + let source_tree = fs_err::canonicalize(path).with_context(|| { format!( "Failed to canonicalize path to source tree: {}", - source_tree.user_display() + path.user_display() ) })?; - let Ok(url) = Url::from_directory_path(&path) else { + let source_tree = source_tree.parent().ok_or_else(|| { + anyhow::anyhow!( + "The file `{}` appears to be a `setup.py` or `setup.cfg` file, which must be in a directory", + path.user_display() + ) + })?; + + let Ok(url) = Url::from_directory_path(source_tree) else { return Err(anyhow::anyhow!("Failed to convert path to URL")); }; let source = SourceUrl::Path(PathSourceUrl { url: &url, - path: Cow::Owned(path), + path: Cow::Borrowed(source_tree), }); // Determine the hash policy. Since we don't have a package name, we perform a @@ -101,7 +109,7 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> { HashStrategy::Validate { .. } => { return Err(anyhow::anyhow!( "Hash-checking is not supported for local directories: {}", - source_tree.user_display() + path.user_display() )); } }; @@ -136,15 +144,23 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> { } }; + // Extract the origin. + let origin = RequirementOrigin::Project(path.to_path_buf(), metadata.name.clone()); + // Determine the appropriate requirements to return based on the extras. This involves // evaluating the `extras` expression in any markers, but preserving the remaining marker // conditions. match self.extras { - ExtrasSpecification::None => Ok(metadata.requires_dist), + ExtrasSpecification::None => Ok(metadata + .requires_dist + .into_iter() + .map(|requirement| requirement.with_origin(Some(origin.clone()))) + .collect()), ExtrasSpecification::All => Ok(metadata .requires_dist .into_iter() .map(|requirement| pep508_rs::Requirement { + origin: Some(origin.clone()), marker: requirement .marker .and_then(|marker| marker.simplify_extras(&metadata.provides_extras)), @@ -155,6 +171,7 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> { .requires_dist .into_iter() .map(|requirement| pep508_rs::Requirement { + origin: Some(origin.clone()), marker: requirement .marker .and_then(|marker| marker.simplify_extras(extras)), diff --git a/crates/uv-requirements/src/specification.rs b/crates/uv-requirements/src/specification.rs index 9ac0d5415b34..712fcf968e5f 100644 --- a/crates/uv-requirements/src/specification.rs +++ b/crates/uv-requirements/src/specification.rs @@ -71,7 +71,6 @@ impl RequirementsSpecification { RequirementEntry { requirement, hashes: vec![], - path: None, }, )?], constraints: vec![], @@ -149,30 +148,21 @@ impl RequirementsSpecification { Self::parse_direct_pyproject_toml(&contents, extras, path.as_ref(), preview) .with_context(|| format!("Failed to parse `{}`", path.user_display()))? } - RequirementsSource::SetupPy(path) | RequirementsSource::SetupCfg(path) => { - let path = fs_err::canonicalize(path)?; - let source_tree = path.parent().ok_or_else(|| { - anyhow::anyhow!( - "The file `{}` appears to be a `setup.py` or `setup.cfg` file, which must be in a directory", - path.user_display() - ) - })?; - Self { - project: None, - requirements: vec![], - constraints: vec![], - overrides: vec![], - editables: vec![], - source_trees: vec![source_tree.to_path_buf()], - extras: FxHashSet::default(), - index_url: None, - extra_index_urls: vec![], - no_index: false, - find_links: vec![], - no_binary: NoBinary::default(), - no_build: NoBuild::default(), - } - } + RequirementsSource::SetupPy(path) | RequirementsSource::SetupCfg(path) => Self { + project: None, + requirements: vec![], + constraints: vec![], + overrides: vec![], + editables: vec![], + source_trees: vec![path.clone()], + extras: FxHashSet::default(), + index_url: None, + extra_index_urls: vec![], + no_index: false, + find_links: vec![], + no_binary: NoBinary::default(), + no_build: NoBuild::default(), + }, }) } @@ -224,13 +214,12 @@ impl RequirementsSpecification { url, path, extras: requirement.extras, - source: Some(pyproject_path.to_path_buf()), + origin: requirement.origin, }) } else { Either::Right(UnresolvedRequirementSpecification { requirement: UnresolvedRequirement::Named(requirement), hashes: vec![], - path: Some(pyproject_path.to_string_lossy().to_string()), }) } }); @@ -248,17 +237,10 @@ impl RequirementsSpecification { "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", - path.user_display() - ) - })?; Ok(Self { project: None, requirements: vec![], - source_trees: vec![source_tree.to_path_buf()], + source_trees: vec![pyproject_path.to_path_buf()], ..Self::default() }) } diff --git a/crates/uv-requirements/src/unnamed.rs b/crates/uv-requirements/src/unnamed.rs index ff6bd9e00378..727fd83c7de4 100644 --- a/crates/uv-requirements/src/unnamed.rs +++ b/crates/uv-requirements/src/unnamed.rs @@ -101,7 +101,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, - source: requirement.source, + origin: requirement.origin, }); } @@ -120,7 +120,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, - source: requirement.source, + origin: requirement.origin, }); } @@ -148,13 +148,13 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, - source: requirement.source, + origin: requirement.origin, }); } // Attempt to read a `pyproject.toml` file. let project_path = path.join("pyproject.toml"); - if let Some(pyproject) = fs_err::read_to_string(&project_path) + if let Some(pyproject) = fs_err::read_to_string(project_path) .ok() .and_then(|contents| toml::from_str::(&contents).ok()) { @@ -170,7 +170,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, - source: Some(project_path.clone()), + origin: requirement.origin, }); } @@ -188,7 +188,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, - source: Some(project_path.clone()), + origin: requirement.origin, }); } } @@ -217,7 +217,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, - source: requirement.source, + origin: requirement.origin, }); } } @@ -276,7 +276,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { extras: requirement.extras, version_or_url: Some(VersionOrUrl::Url(requirement.url)), marker: requirement.marker, - source: requirement.source, + origin: requirement.origin, }) } } diff --git a/crates/uv/src/commands/pip_compile.rs b/crates/uv/src/commands/pip_compile.rs index 00bc2a49fca7..8d9ae3cbf722 100644 --- a/crates/uv/src/commands/pip_compile.rs +++ b/crates/uv/src/commands/pip_compile.rs @@ -361,21 +361,11 @@ pub(crate) async fn pip_compile( .iter() .filter(|requirement| requirement.evaluate_markers(&markers, &[])) { - if let Some(path) = &requirement.path { - if path.ends_with("pyproject.toml") { - sources.add( - &requirement.name, - SourceAnnotation::PyProject { - path: path.clone(), - project_name: project.as_ref().map(ToString::to_string), - }, - ); - } else { - sources.add( - &requirement.name, - SourceAnnotation::Requirement(path.clone()), - ); - } + if let Some(origin) = &requirement.origin { + sources.add( + &requirement.name, + SourceAnnotation::Requirement(origin.clone()), + ); } } @@ -383,10 +373,10 @@ pub(crate) async fn pip_compile( .iter() .filter(|requirement| requirement.evaluate_markers(&markers, &[])) { - if let Some(path) = &requirement.path { + if let Some(origin) = &requirement.origin { sources.add( &requirement.name, - SourceAnnotation::Constraint(path.clone()), + SourceAnnotation::Constraint(origin.clone()), ); } } @@ -395,27 +385,20 @@ pub(crate) async fn pip_compile( .iter() .filter(|requirement| requirement.evaluate_markers(&markers, &[])) { - if let Some(path) = &requirement.path { - sources.add(&requirement.name, SourceAnnotation::Override(path.clone())); + if let Some(origin) = &requirement.origin { + sources.add( + &requirement.name, + SourceAnnotation::Override(origin.clone()), + ); } } for editable in &editables { - if let Some(source) = &editable.source { - if source.ends_with("pyproject.toml") { - sources.add_editable( - editable.url(), - SourceAnnotation::PyProject { - path: source.clone(), - project_name: project.as_ref().map(ToString::to_string), - }, - ); - } else { - sources.add_editable( - editable.url(), - SourceAnnotation::Requirement(source.clone()), - ); - } + if let Some(origin) = &editable.origin { + sources.add_editable( + editable.url(), + SourceAnnotation::Requirement(origin.clone()), + ); } } @@ -434,7 +417,7 @@ pub(crate) async fn pip_compile( url, extras, path, - source: _, + origin: _, } = editable; LocalEditable { url, path, extras } })); diff --git a/crates/uv/src/commands/pip_install.rs b/crates/uv/src/commands/pip_install.rs index 34fc7bf568ce..60cef4413849 100644 --- a/crates/uv/src/commands/pip_install.rs +++ b/crates/uv/src/commands/pip_install.rs @@ -579,7 +579,7 @@ async fn build_editables( url, extras, path, - source: _, + origin: _, } = editable; LocalEditable { url: url.clone(), @@ -678,7 +678,7 @@ async fn resolve( extras: vec![], marker: None, source, - path: None, + origin: 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 017573f3987e..09f14253fd41 100644 --- a/crates/uv/src/commands/pip_sync.rs +++ b/crates/uv/src/commands/pip_sync.rs @@ -688,7 +688,7 @@ async fn resolve_editables( url, path, extras, - source: _, + origin: _, } = editable; LocalEditable { url: url.clone(), diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index bf1b3f129d7a..8c19723fad1b 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -499,6 +499,7 @@ build-backend = "poetry.core.masonry.api" # 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 test anyio==3.7.1 + # via poetry-editable (pyproject.toml) idna==3.6 # via anyio iniconfig==2.0.0 @@ -508,6 +509,7 @@ build-backend = "poetry.core.masonry.api" pluggy==1.4.0 # via pytest pytest==8.1.1 + # via poetry-editable (pyproject.toml) sniffio==1.3.1 # via anyio @@ -568,9 +570,11 @@ setup( # 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 anyio==4.3.0 + # via dummypkg (pyproject.toml) idna==3.6 # via anyio iniconfig==2.0.0 + # via dummypkg (pyproject.toml) sniffio==1.3.1 # via anyio @@ -624,9 +628,11 @@ setup( # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z setup.cfg --extra dev anyio==4.3.0 + # via dummypkg (setup.cfg) idna==3.6 # via anyio iniconfig==2.0.0 + # via dummypkg (setup.cfg) sniffio==1.3.1 # via anyio @@ -670,9 +676,11 @@ setup( # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z setup.py --extra dev anyio==4.3.0 + # via dummypkg (setup.py) idna==3.6 # via anyio iniconfig==2.0.0 + # via dummypkg (setup.py) sniffio==1.3.1 # via anyio @@ -3919,7 +3927,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 + # via -r [TEMP_DIR]/requirements.in sniffio==1.3.1 \ --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc @@ -6755,10 +6763,10 @@ fn compile_root_uri_non_editable() -> Result<()> { # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in black @ ${BLACK_PATH} # via - # [WORKSPACE]/scripts/packages/black_editable/pyproject.toml + # -r requirements.in # root-editable root-editable @ ${ROOT_PATH} - # via [WORKSPACE]/scripts/packages/root_editable/pyproject.toml + # via -r requirements.in ----- stderr ----- Resolved 2 packages in [TIME] @@ -7141,7 +7149,7 @@ fn unnamed_path_requirement() -> Result<()> { # httpx # poetry-editable black @ ../../scripts/packages/black_editable - # via [WORKSPACE]/scripts/packages/black_editable/pyproject.toml + # via -r [TEMP_DIR]/requirements.in certifi==2024.2.2 # via # httpcore @@ -7161,7 +7169,7 @@ fn unnamed_path_requirement() -> Result<()> { # httpx # requests poetry-editable @ ../../scripts/packages/poetry_editable - # via [WORKSPACE]/scripts/packages/poetry_editable/pyproject.toml + # via -r [TEMP_DIR]/requirements.in requests==2.31.0 # via setup-cfg-editable setup-cfg-editable @ ../../scripts/packages/setup_cfg_editable @@ -7653,7 +7661,7 @@ requires-python = ">3.8" anyio @ file://[TEMP_DIR]/anyio/ # via lib example @ ./app - # via app/pyproject.toml + # via -r requirements.in idna==3.6 # via anyio lib @ file://[TEMP_DIR]/lib/ @@ -7741,7 +7749,7 @@ requires-python = ">3.8" # --override overrides.txt # lib example @ ./app - # via app/pyproject.toml + # via -r requirements.in idna==3.6 # via anyio lib @ file://[TEMP_DIR]/lib/ @@ -7856,7 +7864,7 @@ requires-python = ">3.8" # --override overrides.txt # lib example @ ./app - # via app/pyproject.toml + # via -r requirements.in idna==3.6 # via anyio lib @ file://[TEMP_DIR]/lib @@ -7902,7 +7910,7 @@ requires-python = ">3.8" click==8.1.7 # via flask example @ . - # via pyproject.toml + # via -r requirements.in flask==2.0.0rc1 # via example itsdangerous==2.1.2