Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/uv-distribution-types/src/dependency_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub struct StaticMetadata {
pub version: Option<Version>,
// Optional fields
#[serde(default)]
pub requires_dist: Vec<Requirement<VerbatimParsedUrl>>,
pub requires_dist: Box<[Requirement<VerbatimParsedUrl>]>,
#[cfg_attr(
feature = "schemars",
schemars(
Expand All @@ -110,5 +110,5 @@ pub struct StaticMetadata {
)]
pub requires_python: Option<VersionSpecifiers>,
#[serde(default)]
pub provides_extras: Vec<ExtraName>,
pub provides_extras: Box<[ExtraName]>,
}
10 changes: 4 additions & 6 deletions crates/uv-distribution/src/metadata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ pub struct Metadata {
pub name: PackageName,
pub version: Version,
// Optional fields
pub requires_dist: Vec<Requirement>,
pub requires_dist: Box<[Requirement]>,
pub requires_python: Option<VersionSpecifiers>,
pub provides_extras: Vec<ExtraName>,
pub dependency_groups: BTreeMap<GroupName, Vec<Requirement>>,
pub provides_extras: Box<[ExtraName]>,
pub dependency_groups: BTreeMap<GroupName, Box<[Requirement]>>,
pub dynamic: bool,
}

Expand All @@ -60,9 +60,7 @@ impl Metadata {
Self {
name: metadata.name,
version: metadata.version,
requires_dist: metadata
.requires_dist
.into_iter()
requires_dist: Box::into_iter(metadata.requires_dist)
.map(Requirement::from)
.collect(),
requires_python: metadata.requires_python,
Expand Down
146 changes: 78 additions & 68 deletions crates/uv-distribution/src/metadata/requires_dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use crate::Metadata;
#[derive(Debug, Clone)]
pub struct RequiresDist {
pub name: PackageName,
pub requires_dist: Vec<Requirement>,
pub provides_extras: Vec<ExtraName>,
pub dependency_groups: BTreeMap<GroupName, Vec<Requirement>>,
pub requires_dist: Box<[Requirement]>,
pub provides_extras: Box<[ExtraName]>,
pub dependency_groups: BTreeMap<GroupName, Box<[Requirement]>>,
pub dynamic: bool,
}

Expand All @@ -30,9 +30,7 @@ impl RequiresDist {
pub fn from_metadata23(metadata: uv_pypi_types::RequiresDist) -> Self {
Self {
name: metadata.name,
requires_dist: metadata
.requires_dist
.into_iter()
requires_dist: Box::into_iter(metadata.requires_dist)
.map(Requirement::from)
.collect(),
provides_extras: metadata.provides_extras,
Expand Down Expand Up @@ -185,17 +183,17 @@ impl RequiresDist {
},
)
})
.collect::<Result<Vec<_>, _>>(),
.collect::<Result<Box<_>, _>>(),
SourceStrategy::Disabled => {
Ok(requirements.into_iter().map(Requirement::from).collect())
}
}?;
Ok::<(GroupName, Vec<Requirement>), MetadataError>((name, requirements))
Ok::<(GroupName, Box<_>), MetadataError>((name, requirements))
})
.collect::<Result<BTreeMap<_, _>, _>>()?;

// Lower the requirements.
let requires_dist = metadata.requires_dist.into_iter();
let requires_dist = Box::into_iter(metadata.requires_dist);
let requires_dist = match source_strategy {
SourceStrategy::Enabled => requires_dist
.flat_map(|requirement| {
Expand All @@ -222,7 +220,7 @@ impl RequiresDist {
)),
})
})
.collect::<Result<Vec<_>, _>>()?,
.collect::<Result<Box<_>, _>>()?,
SourceStrategy::Disabled => requires_dist.into_iter().map(Requirement::from).collect(),
};

Expand Down Expand Up @@ -353,11 +351,11 @@ impl From<Metadata> for RequiresDist {
/// The [`FlatRequiresDist`] struct is used to flatten out the recursive dependencies, i.e., convert
/// from the former to the latter.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FlatRequiresDist(Vec<Requirement>);
pub struct FlatRequiresDist(Box<[Requirement]>);

impl FlatRequiresDist {
/// Flatten a set of requirements, resolving any self-references.
pub fn from_requirements(requirements: Vec<Requirement>, name: &PackageName) -> Self {
pub fn from_requirements(requirements: Box<[Requirement]>, name: &PackageName) -> Self {
// If there are no self-references, we can return early.
if requirements.iter().all(|req| req.name != *name) {
return Self(requirements);
Expand All @@ -370,7 +368,7 @@ impl FlatRequiresDist {
.collect();

// Transitively process all extras that are recursively included.
let mut flattened = requirements.clone();
let mut flattened = requirements.to_vec();
let mut seen = FxHashSet::<(ExtraName, MarkerTree)>::default();
let mut queue: VecDeque<_> = flattened
.iter()
Expand Down Expand Up @@ -436,21 +434,21 @@ impl FlatRequiresDist {
}
}

Self(flattened)
Self(flattened.into_boxed_slice())
}

/// Consume the [`FlatRequiresDist`] and return the inner vector.
pub fn into_inner(self) -> Vec<Requirement> {
/// Consume the [`FlatRequiresDist`] and return the inner requirements.
pub fn into_inner(self) -> Box<[Requirement]> {
self.0
}
}

impl IntoIterator for FlatRequiresDist {
type Item = Requirement;
type IntoIter = std::vec::IntoIter<Requirement>;
type IntoIter = <Box<[Requirement]> as IntoIterator>::IntoIter;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
Box::into_iter(self.0)
}
}

Expand Down Expand Up @@ -750,7 +748,7 @@ mod test {
#[test]
fn test_flat_requires_dist_noop() {
let name = PackageName::from_str("pkg").unwrap();
let requirements = vec![
let requirements = [
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
Expand All @@ -760,25 +758,28 @@ mod test {
.into(),
];

let expected = FlatRequiresDist(vec![
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'dev'")
.unwrap()
.into(),
]);
let expected = FlatRequiresDist(
[
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'dev'")
.unwrap()
.into(),
]
.into(),
);

let actual = FlatRequiresDist::from_requirements(requirements, &name);
let actual = FlatRequiresDist::from_requirements(requirements.into(), &name);

assert_eq!(actual, expected);
}

#[test]
fn test_flat_requires_dist_basic() {
let name = PackageName::from_str("pkg").unwrap();
let requirements = vec![
let requirements = [
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
Expand All @@ -791,20 +792,23 @@ mod test {
.into(),
];

let expected = FlatRequiresDist(vec![
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'dev'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'test'")
.unwrap()
.into(),
]);
let expected = FlatRequiresDist(
[
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'dev'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'test'")
.unwrap()
.into(),
]
.into(),
);

let actual = FlatRequiresDist::from_requirements(requirements, &name);
let actual = FlatRequiresDist::from_requirements(requirements.into(), &name);

assert_eq!(actual, expected);
}
Expand All @@ -825,28 +829,31 @@ mod test {
.into(),
];

let expected = FlatRequiresDist(vec![
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'dev' and sys_platform == 'win32'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'test' and sys_platform == 'win32'")
.unwrap()
.into(),
]);
let expected = FlatRequiresDist(
[
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'dev' and sys_platform == 'win32'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'test' and sys_platform == 'win32'")
.unwrap()
.into(),
]
.into(),
);

let actual = FlatRequiresDist::from_requirements(requirements, &name);
let actual = FlatRequiresDist::from_requirements(requirements.into(), &name);

assert_eq!(actual, expected);
}

#[test]
fn test_flat_requires_dist_self_constraint() {
let name = PackageName::from_str("pkg").unwrap();
let requirements = vec![
let requirements = [
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
Expand All @@ -857,18 +864,21 @@ mod test {
Requirement::from_str("pkg[async]==1.0.0").unwrap().into(),
];

let expected = FlatRequiresDist(vec![
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'dev'")
.unwrap()
.into(),
Requirement::from_str("pkg==1.0.0").unwrap().into(),
]);
let expected = FlatRequiresDist(
[
Requirement::from_str("requests>=2.0.0").unwrap().into(),
Requirement::from_str("pytest; extra == 'test'")
.unwrap()
.into(),
Requirement::from_str("black; extra == 'dev'")
.unwrap()
.into(),
Requirement::from_str("pkg==1.0.0").unwrap().into(),
]
.into(),
);

let actual = FlatRequiresDist::from_requirements(requirements, &name);
let actual = FlatRequiresDist::from_requirements(requirements.into(), &name);

assert_eq!(actual, expected);
}
Expand Down
Loading
Loading