From 88d04584d41f0089bffb4564d479f084c93db349 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 21 Oct 2024 22:56:43 -0400 Subject: [PATCH] Rename dev dependencies to dependency groups in lockfile (#8391) ## Summary This is backwards compatible (we respect `dev-dependencies` as an alias). Part of https://github.com/astral-sh/uv/pull/8272. --- crates/uv-distribution/src/metadata/mod.rs | 8 +- .../src/metadata/requires_dist.rs | 10 +- crates/uv-requirements/src/lookahead.rs | 2 +- crates/uv-resolver/src/lock/mod.rs | 84 ++++----- .../uv-resolver/src/lock/requirements_txt.rs | 2 +- ...r__lock__tests__hash_optional_missing.snap | 6 +- ...r__lock__tests__hash_optional_present.snap | 6 +- ...r__lock__tests__hash_required_present.snap | 6 +- ...missing_dependency_source_unambiguous.snap | 10 +- ...dependency_source_version_unambiguous.snap | 10 +- ...issing_dependency_version_unambiguous.snap | 10 +- ...lock__tests__source_direct_has_subdir.snap | 6 +- ..._lock__tests__source_direct_no_subdir.snap | 6 +- ...solver__lock__tests__source_directory.snap | 6 +- ...esolver__lock__tests__source_editable.snap | 6 +- crates/uv-resolver/src/lock/tree.rs | 12 +- crates/uv-resolver/src/resolution/graph.rs | 4 +- crates/uv-resolver/src/resolver/mod.rs | 4 +- crates/uv/src/commands/project/lock.rs | 2 +- crates/uv/tests/it/edit.rs | 4 +- crates/uv/tests/it/lock.rs | 177 ++++++++++++++++-- ...system__github-wikidata-bot-lock-file.snap | 4 +- .../it__ecosystem__packse-lock-file.snap | 4 +- .../it__ecosystem__warehouse-lock-file.snap | 4 +- ...se_add_remove_existing_package_noop-2.snap | 4 +- ...flow__packse_add_remove_one_package-2.snap | 4 +- ...te_transitive_to_direct_then_remove-2.snap | 4 +- crates/uv/tests/it/workflow.rs | 8 +- 28 files changed, 278 insertions(+), 135 deletions(-) diff --git a/crates/uv-distribution/src/metadata/mod.rs b/crates/uv-distribution/src/metadata/mod.rs index e95a100a657a..be8762b3d7c1 100644 --- a/crates/uv-distribution/src/metadata/mod.rs +++ b/crates/uv-distribution/src/metadata/mod.rs @@ -66,7 +66,7 @@ pub struct Metadata { pub requires_dist: Vec, pub requires_python: Option, pub provides_extras: Vec, - pub dev_dependencies: BTreeMap>, + pub dependency_groups: BTreeMap>, } impl Metadata { @@ -83,7 +83,7 @@ impl Metadata { .collect(), requires_python: metadata.requires_python, provides_extras: metadata.provides_extras, - dev_dependencies: BTreeMap::default(), + dependency_groups: BTreeMap::default(), } } @@ -101,7 +101,7 @@ impl Metadata { name, requires_dist, provides_extras, - dev_dependencies, + dependency_groups, } = RequiresDist::from_project_maybe_workspace( uv_pypi_types::RequiresDist { name: metadata.name, @@ -122,7 +122,7 @@ impl Metadata { requires_dist, requires_python: metadata.requires_python, provides_extras, - dev_dependencies, + dependency_groups, }) } } diff --git a/crates/uv-distribution/src/metadata/requires_dist.rs b/crates/uv-distribution/src/metadata/requires_dist.rs index e655c0e29103..e0eddb15ceb7 100644 --- a/crates/uv-distribution/src/metadata/requires_dist.rs +++ b/crates/uv-distribution/src/metadata/requires_dist.rs @@ -19,7 +19,7 @@ pub struct RequiresDist { pub name: PackageName, pub requires_dist: Vec, pub provides_extras: Vec, - pub dev_dependencies: BTreeMap>, + pub dependency_groups: BTreeMap>, } impl RequiresDist { @@ -34,7 +34,7 @@ impl RequiresDist { .map(uv_pypi_types::Requirement::from) .collect(), provides_extras: metadata.provides_extras, - dev_dependencies: BTreeMap::default(), + dependency_groups: BTreeMap::default(), } } @@ -101,7 +101,7 @@ impl RequiresDist { SourceStrategy::Disabled => &empty, }; - let dev_dependencies = { + let dependency_groups = { // First, collect `tool.uv.dev_dependencies` let dev_dependencies = project_workspace .current_project() @@ -218,7 +218,7 @@ impl RequiresDist { Ok(Self { name: metadata.name, requires_dist, - dev_dependencies, + dependency_groups, provides_extras: metadata.provides_extras, }) } @@ -230,7 +230,7 @@ impl From for RequiresDist { name: metadata.name, requires_dist: metadata.requires_dist, provides_extras: metadata.provides_extras, - dev_dependencies: metadata.dev_dependencies, + dependency_groups: metadata.dependency_groups, } } } diff --git a/crates/uv-requirements/src/lookahead.rs b/crates/uv-requirements/src/lookahead.rs index 80c4da3aad9e..f0b60fa0434f 100644 --- a/crates/uv-requirements/src/lookahead.rs +++ b/crates/uv-requirements/src/lookahead.rs @@ -195,7 +195,7 @@ impl<'a, Context: BuildContext> LookaheadResolver<'a, Context> { .into_iter() .chain( metadata - .dev_dependencies + .dependency_groups .into_iter() .filter_map(|(group, dependencies)| { if self.dev.contains(&group) { diff --git a/crates/uv-resolver/src/lock/mod.rs b/crates/uv-resolver/src/lock/mod.rs index 0f61d39d3a3d..2e928885b4c0 100644 --- a/crates/uv-resolver/src/lock/mod.rs +++ b/crates/uv-resolver/src/lock/mod.rs @@ -211,7 +211,7 @@ impl Lock { continue; }; let marker = edge.weight().clone(); - package.add_dev_dependency( + package.add_group_dependency( &requires_python, group.clone(), dependency_dist, @@ -344,7 +344,7 @@ impl Lock { } // Perform the same validation for dev dependencies. - for (group, dependencies) in &mut package.dev_dependencies { + for (group, dependencies) in &mut package.dependency_groups { dependencies.sort(); for windows in dependencies.windows(2) { let (dep1, dep2) = (&windows[0], &windows[1]); @@ -390,7 +390,7 @@ impl Lock { .dependencies .iter_mut() .chain(dist.optional_dependencies.values_mut().flatten()) - .chain(dist.dev_dependencies.values_mut().flatten()) + .chain(dist.dependency_groups.values_mut().flatten()) { dep.extra.retain(|extra| { extras_by_id @@ -428,7 +428,7 @@ impl Lock { } // Perform the same validation for dev dependencies. - for dependencies in dist.dev_dependencies.values() { + for dependencies in dist.dependency_groups.values() { for dep in dependencies { if !by_id.contains_key(&dep.package_id) { return Err(LockErrorKind::UnrecognizedDependency { @@ -615,7 +615,7 @@ impl Lock { // Add any dev dependencies. for group in dev.iter() { - for dep in root.dev_dependencies.get(group).into_iter().flatten() { + for dep in root.dependency_groups.get(group).into_iter().flatten() { if dep.complexified_marker.evaluate(marker_env, &[]) { let dep_dist = self.find_by_id(&dep.package_id); if seen.insert((&dep.package_id, None)) { @@ -1229,10 +1229,10 @@ impl Lock { } } - // Validate the `dev-dependencies` metadata. + // Validate the `dependency-groups` metadata. { let expected: BTreeMap> = metadata - .dev_dependencies + .dependency_groups .into_iter() .map(|(group, requirements)| { Ok::<_, LockError>(( @@ -1246,7 +1246,7 @@ impl Lock { .collect::>()?; let actual: BTreeMap> = package .metadata - .requires_dev + .dependency_groups .iter() .map(|(group, requirements)| { Ok::<_, LockError>(( @@ -1261,7 +1261,7 @@ impl Lock { .collect::>()?; if expected != actual { - return Ok(SatisfiesResult::MismatchedDevDependencies( + return Ok(SatisfiesResult::MismatchedDependencyGroups( &package.id.name, &package.id.version, expected, @@ -1289,7 +1289,7 @@ impl Lock { } } - for dependencies in package.dev_dependencies.values() { + for dependencies in package.dependency_groups.values() { for dep in dependencies { if seen.insert(&dep.package_id) { let dep_dist = self.find_by_id(&dep.package_id); @@ -1353,8 +1353,8 @@ pub enum SatisfiesResult<'lock> { BTreeSet, BTreeSet, ), - /// A package in the lockfile contains different `dev-dependencies` metadata than expected. - MismatchedDevDependencies( + /// A package in the lockfile contains different `dependency-group` metadata than expected. + MismatchedDependencyGroups( &'lock PackageName, &'lock Version, BTreeMap>, @@ -1524,8 +1524,8 @@ pub struct Package { dependencies: Vec, /// The resolved optional dependencies of the package. optional_dependencies: BTreeMap>, - /// The resolved development dependencies of the package. - dev_dependencies: BTreeMap>, + /// The resolved PEP 735 dependency groups of the package. + dependency_groups: BTreeMap>, /// The exact requirements from the package metadata. metadata: PackageMetadata, } @@ -1553,14 +1553,14 @@ impl Package { .collect::>() .map_err(LockErrorKind::RequirementRelativePath)? }; - let requires_dev = if id.source.is_immutable() { + let dependency_groups = if id.source.is_immutable() { BTreeMap::default() } else { annotated_dist .metadata .as_ref() .expect("metadata is present") - .dev_dependencies + .dependency_groups .iter() .map(|(group, requirements)| { let requirements = requirements @@ -1580,10 +1580,10 @@ impl Package { fork_markers, dependencies: vec![], optional_dependencies: BTreeMap::default(), - dev_dependencies: BTreeMap::default(), + dependency_groups: BTreeMap::default(), metadata: PackageMetadata { requires_dist, - requires_dev, + dependency_groups, }, }) } @@ -1659,18 +1659,18 @@ impl Package { Ok(()) } - /// Add the [`AnnotatedDist`] as a development dependency of the [`Package`]. - fn add_dev_dependency( + /// Add the [`AnnotatedDist`] to a dependency group of the [`Package`]. + fn add_group_dependency( &mut self, requires_python: &RequiresPython, - dev: GroupName, + group: GroupName, annotated_dist: &AnnotatedDist, marker: MarkerTree, root: &Path, ) -> Result<(), LockError> { let dep = Dependency::from_annotated_dist(requires_python, annotated_dist, marker, root)?; - let dev_deps = self.dev_dependencies.entry(dev).or_default(); - for existing_dep in &mut *dev_deps { + let deps = self.dependency_groups.entry(group).or_default(); + for existing_dep in &mut *deps { if existing_dep.package_id == dep.package_id // See note in add_dependency for why we use // simplified markers here. @@ -1681,7 +1681,7 @@ impl Package { } } - dev_deps.push(dep); + deps.push(dep); Ok(()) } @@ -2031,19 +2031,19 @@ impl Package { } } - if !self.dev_dependencies.is_empty() { - let mut dev_dependencies = Table::new(); - for (extra, deps) in &self.dev_dependencies { + if !self.dependency_groups.is_empty() { + let mut dependency_groups = Table::new(); + for (extra, deps) in &self.dependency_groups { let deps = each_element_on_its_line_array(deps.iter().map(|dep| { dep.to_toml(requires_python, dist_count_by_name) .into_inline_table() })); if !deps.is_empty() { - dev_dependencies.insert(extra.as_ref(), value(deps)); + dependency_groups.insert(extra.as_ref(), value(deps)); } } - if !dev_dependencies.is_empty() { - table.insert("dev-dependencies", Item::Table(dev_dependencies)); + if !dependency_groups.is_empty() { + table.insert("dependency-groups", Item::Table(dependency_groups)); } } @@ -2086,9 +2086,9 @@ impl Package { metadata_table.insert("requires-dist", value(requires_dist)); } - if !self.metadata.requires_dev.is_empty() { - let mut requires_dev = Table::new(); - for (extra, deps) in &self.metadata.requires_dev { + if !self.metadata.dependency_groups.is_empty() { + let mut dependency_groups = Table::new(); + for (extra, deps) in &self.metadata.dependency_groups { let deps = deps .iter() .map(|requirement| { @@ -2104,11 +2104,11 @@ impl Package { deps => each_element_on_its_line_array(deps.iter()), }; if !deps.is_empty() { - requires_dev.insert(extra.as_ref(), value(deps)); + dependency_groups.insert(extra.as_ref(), value(deps)); } } - if !requires_dev.is_empty() { - metadata_table.insert("requires-dev", Item::Table(requires_dev)); + if !dependency_groups.is_empty() { + metadata_table.insert("dependency-groups", Item::Table(dependency_groups)); } } @@ -2218,8 +2218,8 @@ struct PackageWire { dependencies: Vec, #[serde(default)] optional_dependencies: BTreeMap>, - #[serde(default)] - dev_dependencies: BTreeMap>, + #[serde(default, alias = "dev-dependencies")] + dependency_groups: BTreeMap>, } #[derive(Clone, Default, Debug, Eq, PartialEq, serde::Deserialize)] @@ -2227,8 +2227,8 @@ struct PackageWire { struct PackageMetadata { #[serde(default)] requires_dist: BTreeSet, - #[serde(default)] - requires_dev: BTreeMap>, + #[serde(default, alias = "requires-dev")] + dependency_groups: BTreeMap>, } impl PackageWire { @@ -2258,8 +2258,8 @@ impl PackageWire { .into_iter() .map(|(extra, deps)| Ok((extra, unwire_deps(deps)?))) .collect::>()?, - dev_dependencies: self - .dev_dependencies + dependency_groups: self + .dependency_groups .into_iter() .map(|(group, deps)| Ok((group, unwire_deps(deps)?))) .collect::>()?, diff --git a/crates/uv-resolver/src/lock/requirements_txt.rs b/crates/uv-resolver/src/lock/requirements_txt.rs index 9c473a8f3856..214b345702d4 100644 --- a/crates/uv-resolver/src/lock/requirements_txt.rs +++ b/crates/uv-resolver/src/lock/requirements_txt.rs @@ -86,7 +86,7 @@ impl<'lock> RequirementsTxtExport<'lock> { // Add any dev dependencies. for group in dev.iter() { - for dep in root.dev_dependencies.get(group).into_iter().flatten() { + for dep in root.dependency_groups.get(group).into_iter().flatten() { let dep_dist = lock.find_by_id(&dep.package_id); // Add the dependency to the graph. diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_optional_missing.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_optional_missing.snap index 9eae35fa0a5e..a17e0270042e 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_optional_missing.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_optional_missing.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -78,10 +78,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_optional_present.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_optional_present.snap index b08ac136e1e8..65aaa5849210 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_optional_present.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_optional_present.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -85,10 +85,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_required_present.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_required_present.snap index 18a9968fa1ae..09dc7df1f3a8 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_required_present.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__hash_required_present.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -81,10 +81,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_source_unambiguous.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_source_unambiguous.snap index df2435de84c5..e93ae3260342 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_source_unambiguous.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_source_unambiguous.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -71,10 +71,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, Package { @@ -136,10 +136,10 @@ Ok( }, ], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_source_version_unambiguous.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_source_version_unambiguous.snap index df2435de84c5..e93ae3260342 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_source_version_unambiguous.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_source_version_unambiguous.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -71,10 +71,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, Package { @@ -136,10 +136,10 @@ Ok( }, ], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_version_unambiguous.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_version_unambiguous.snap index df2435de84c5..e93ae3260342 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_version_unambiguous.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__missing_dependency_version_unambiguous.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -71,10 +71,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, Package { @@ -136,10 +136,10 @@ Ok( }, ], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_direct_has_subdir.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_direct_has_subdir.snap index 3624b1c56f33..8c7ca8d2c0be 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_direct_has_subdir.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_direct_has_subdir.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -55,10 +55,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_direct_no_subdir.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_direct_no_subdir.snap index 1ee52e43d3be..04e3df0ba703 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_direct_no_subdir.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_direct_no_subdir.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -53,10 +53,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_directory.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_directory.snap index 38c5bf51b463..3b0a488c4507 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_directory.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_directory.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -48,10 +48,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_editable.snap b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_editable.snap index c445e4a2932a..2c8a20fd3256 100644 --- a/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_editable.snap +++ b/crates/uv-resolver/src/lock/snapshots/uv_resolver__lock__tests__source_editable.snap @@ -1,5 +1,5 @@ --- -source: crates/uv-resolver/src/lock/mod.rs +source: crates/uv-resolver/src/lock/tests.rs expression: result --- Ok( @@ -48,10 +48,10 @@ Ok( fork_markers: [], dependencies: [], optional_dependencies: {}, - dev_dependencies: {}, + dependency_groups: {}, metadata: PackageMetadata { requires_dist: {}, - requires_dev: {}, + dependency_groups: {}, }, }, ], diff --git a/crates/uv-resolver/src/lock/tree.rs b/crates/uv-resolver/src/lock/tree.rs index 0f4bbb70e38f..31f1bc5692e1 100644 --- a/crates/uv-resolver/src/lock/tree.rs +++ b/crates/uv-resolver/src/lock/tree.rs @@ -22,7 +22,7 @@ pub struct TreeDisplay<'env> { dependencies: FxHashMap<&'env PackageId, Vec>>, optional_dependencies: FxHashMap<&'env PackageId, FxHashMap>>>, - dev_dependencies: FxHashMap<&'env PackageId, FxHashMap>>>, + dependency_groups: FxHashMap<&'env PackageId, FxHashMap>>>, /// Maximum display depth of the dependency tree. depth: usize, /// Whether to include development dependencies in the display. @@ -53,7 +53,7 @@ impl<'env> TreeDisplay<'env> { // support `--invert`, so we might as well build them up in either case. let mut dependencies: FxHashMap<_, Vec<_>> = FxHashMap::default(); let mut optional_dependencies: FxHashMap<_, FxHashMap<_, Vec<_>>> = FxHashMap::default(); - let mut dev_dependencies: FxHashMap<_, FxHashMap<_, Vec<_>>> = FxHashMap::default(); + let mut dependency_groups: FxHashMap<_, FxHashMap<_, Vec<_>>> = FxHashMap::default(); for package in &lock.packages { for dependency in &package.dependencies { @@ -129,7 +129,7 @@ impl<'env> TreeDisplay<'env> { } } - for (group, dependencies) in &package.dev_dependencies { + for (group, dependencies) in &package.dependency_groups { for dependency in dependencies { // Skip dependencies that don't apply to the current environment. if let Some(environment_markers) = markers { @@ -160,7 +160,7 @@ impl<'env> TreeDisplay<'env> { non_roots.insert(child.package_id.clone()); - dev_dependencies + dependency_groups .entry(parent) .or_default() .entry(group.clone()) @@ -182,7 +182,7 @@ impl<'env> TreeDisplay<'env> { roots, dependencies, optional_dependencies, - dev_dependencies, + dependency_groups, depth, dev, prune, @@ -252,7 +252,7 @@ impl<'env> TreeDisplay<'env> { }), ) .chain( - self.dev_dependencies + self.dependency_groups .get(node.package_id()) .into_iter() .flatten() diff --git a/crates/uv-resolver/src/resolution/graph.rs b/crates/uv-resolver/src/resolution/graph.rs index 9e379585000c..6730a34acb44 100644 --- a/crates/uv-resolver/src/resolution/graph.rs +++ b/crates/uv-resolver/src/resolution/graph.rs @@ -355,7 +355,7 @@ impl ResolutionGraph { // Validate the development dependency group. if let Some(dev) = dev { - if !metadata.dev_dependencies.contains_key(dev) { + if !metadata.dependency_groups.contains_key(dev) { diagnostics.push(ResolutionDiagnostic::MissingDev { dist: dist.clone(), dev: dev.clone(), @@ -872,7 +872,7 @@ fn has_lower_bound( for requirement in metadata .requires_dist .iter() - .chain(metadata.dev_dependencies.values().flatten()) + .chain(metadata.dependency_groups.values().flatten()) { if requirement.name != *package_name { continue; diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index 279864f4a04a..843244d96d39 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -1341,7 +1341,7 @@ impl ResolverState ResolverState { + SatisfiesResult::MismatchedDependencyGroups(name, version, expected, actual) => { debug!( "Ignoring existing lockfile due to mismatched dev dependencies for: `{name}=={version}`\n Expected: {:?}\n Actual: {:?}", expected, actual diff --git a/crates/uv/tests/it/edit.rs b/crates/uv/tests/it/edit.rs index 1b40e3e3ef27..7f86f6683a86 100644 --- a/crates/uv/tests/it/edit.rs +++ b/crates/uv/tests/it/edit.rs @@ -1074,14 +1074,14 @@ fn add_remove_dev() -> Result<()> { version = "0.1.0" source = { editable = "." } - [package.dev-dependencies] + [package.dependency-groups] dev = [ { name = "anyio" }, ] [package.metadata] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "anyio", specifier = "==3.7.0" }] [[package]] diff --git a/crates/uv/tests/it/lock.rs b/crates/uv/tests/it/lock.rs index d7b6a1db75e6..57ce0183c6c7 100644 --- a/crates/uv/tests/it/lock.rs +++ b/crates/uv/tests/it/lock.rs @@ -4541,7 +4541,7 @@ fn lock_dev() -> Result<()> { { name = "iniconfig" }, ] - [package.dev-dependencies] + [package.dependency-groups] dev = [ { name = "typing-extensions" }, ] @@ -4549,7 +4549,7 @@ fn lock_dev() -> Result<()> { [package.metadata] requires-dist = [{ name = "iniconfig" }] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "typing-extensions", url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl" }] [[package]] @@ -6153,14 +6153,14 @@ fn lock_dev_transitive() -> Result<()> { version = "0.1.0" source = { editable = "baz" } - [package.dev-dependencies] + [package.dependency-groups] dev = [ { name = "typing-extensions" }, ] [package.metadata] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "typing-extensions", specifier = ">4" }] [[package]] @@ -6170,7 +6170,7 @@ fn lock_dev_transitive() -> Result<()> { [package.metadata] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "anyio" }] [[package]] @@ -7077,7 +7077,7 @@ fn lock_no_sources() -> Result<()> { { name = "anyio" }, ] - [package.dev-dependencies] + [package.dependency-groups] dev = [ { name = "typing-extensions" }, ] @@ -7085,7 +7085,7 @@ fn lock_no_sources() -> Result<()> { [package.metadata] requires-dist = [{ name = "anyio", directory = "anyio" }] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "typing-extensions", specifier = ">4" }] [[package]] @@ -7167,7 +7167,7 @@ fn lock_no_sources() -> Result<()> { { name = "anyio" }, ] - [package.dev-dependencies] + [package.dependency-groups] dev = [ { name = "typing-extensions" }, ] @@ -7175,7 +7175,7 @@ fn lock_no_sources() -> Result<()> { [package.metadata] requires-dist = [{ name = "anyio" }] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "typing-extensions", specifier = ">4" }] [[package]] @@ -10900,6 +10900,149 @@ fn lock_missing_metadata() -> Result<()> { Ok(()) } +/// Test backwards compatibility for `package.dev-dependencies`, which was renamed to +/// `package.dependency-groups`. +#[test] +fn lock_dev_dependencies_alias() -> Result<()> { + let context = TestContext::new("3.12"); + + let pyproject_toml = context.temp_dir.child("pyproject.toml"); + pyproject_toml.write_str( + r#" + [project] + name = "project" + version = "0.1.0" + requires-python = ">=3.12" + dependencies = [] + + [tool.uv] + dev-dependencies = ["iniconfig"] + "#, + )?; + + let lock = context.temp_dir.child("uv.lock"); + + // Write a lockfile with `[package.dev-dependencies]`. + lock.write_str(r#" + version = 1 + requires-python = ">=3.12" + + [options] + exclude-newer = "2024-03-25T00:00:00Z" + + [[package]] + name = "project" + version = "0.1.0" + source = { virtual = "." } + + [package.dev-dependencies] + dev = [{ name = "iniconfig" }] + + [package.metadata] + + [package.metadata.requires-dev] + dev = [{ name = "iniconfig" }] + + [[package]] + name = "iniconfig" + version = "2.0.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, + ] + "#)?; + + // Re-locking should be a no-op. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + "###); + + // If we add a package, re-locking should use `dependency-groups`. + pyproject_toml.write_str( + r#" + [project] + name = "project" + version = "0.1.0" + requires-python = ">=3.12" + dependencies = ["typing-extensions"] + + [tool.uv] + dev-dependencies = ["iniconfig"] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 3 packages in [TIME] + Added typing-extensions v4.10.0 + "###); + + let lock = context.read("uv.lock"); + + insta::with_settings!({ + filters => context.filters(), + }, { + assert_snapshot!( + lock, @r###" + version = 1 + requires-python = ">=3.12" + + [options] + exclude-newer = "2024-03-25T00:00:00Z" + + [[package]] + name = "iniconfig" + version = "2.0.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, + ] + + [[package]] + name = "project" + version = "0.1.0" + source = { virtual = "." } + dependencies = [ + { name = "typing-extensions" }, + ] + + [package.dependency-groups] + dev = [ + { name = "iniconfig" }, + ] + + [package.metadata] + requires-dist = [{ name = "typing-extensions" }] + + [package.metadata.dependency-groups] + dev = [{ name = "iniconfig" }] + + [[package]] + name = "typing-extensions" + version = "4.10.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/16/3a/0d26ce356c7465a19c9ea8814b960f8a36c3b0d07c323176620b7b483e44/typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb", size = 77558 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/de/dc04a3ea60b22624b51c703a84bbe0184abcd1d0b9bc8074b5d6b7ab90bb/typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", size = 33926 }, + ] + "### + ); + }); + + Ok(()) +} + /// Lock a `pyproject.toml`, reorder the dependencies, and ensure that the lockfile is _not_ updated /// on the next run. #[test] @@ -12269,14 +12412,14 @@ fn lock_dropped_dev_extra() -> Result<()> { version = "0.1.0" source = { editable = "." } - [package.dev-dependencies] + [package.dependency-groups] dev = [ { name = "coverage" }, ] [package.metadata] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "coverage", extras = ["toml"] }] "### ); @@ -13188,7 +13331,7 @@ fn lock_explicit_virtual_project() -> Result<()> { { name = "black" }, ] - [package.dev-dependencies] + [package.dependency-groups] dev = [ { name = "anyio" }, ] @@ -13196,7 +13339,7 @@ fn lock_explicit_virtual_project() -> Result<()> { [package.metadata] requires-dist = [{ name = "black" }] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "anyio" }] [[package]] @@ -13405,7 +13548,7 @@ fn lock_implicit_virtual_project() -> Result<()> { { name = "black" }, ] - [package.dev-dependencies] + [package.dependency-groups] dev = [ { name = "anyio" }, ] @@ -13413,7 +13556,7 @@ fn lock_implicit_virtual_project() -> Result<()> { [package.metadata] requires-dist = [{ name = "black" }] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [{ name = "anyio" }] [[package]] @@ -16008,7 +16151,7 @@ fn lock_group_include() -> Result<()> { { name = "typing-extensions" }, ] - [package.dev-dependencies] + [package.dependency-groups] bar = [ { name = "trio" }, ] @@ -16020,7 +16163,7 @@ fn lock_group_include() -> Result<()> { [package.metadata] requires-dist = [{ name = "typing-extensions" }] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] bar = [{ name = "trio" }] foo = [ { name = "anyio" }, diff --git a/crates/uv/tests/it/snapshots/it__ecosystem__github-wikidata-bot-lock-file.snap b/crates/uv/tests/it/snapshots/it__ecosystem__github-wikidata-bot-lock-file.snap index 5fb225ed60e8..5f4e82579f2e 100644 --- a/crates/uv/tests/it/snapshots/it__ecosystem__github-wikidata-bot-lock-file.snap +++ b/crates/uv/tests/it/snapshots/it__ecosystem__github-wikidata-bot-lock-file.snap @@ -116,7 +116,7 @@ dependencies = [ { name = "yarl" }, ] -[package.dev-dependencies] +[package.dependency-groups] dev = [ { name = "httpx" }, { name = "pytest" }, @@ -135,7 +135,7 @@ requires-dist = [ { name = "yarl", specifier = ">=1.9,<2" }, ] -[package.metadata.requires-dev] +[package.metadata.dependency-groups] dev = [ { name = "httpx", specifier = ">=0.27.0,<0.28" }, { name = "pytest", specifier = ">=8.0.0,<9" }, diff --git a/crates/uv/tests/it/snapshots/it__ecosystem__packse-lock-file.snap b/crates/uv/tests/it/snapshots/it__ecosystem__packse-lock-file.snap index 70e94d40c7d6..9d083cd0c6f7 100644 --- a/crates/uv/tests/it/snapshots/it__ecosystem__packse-lock-file.snap +++ b/crates/uv/tests/it/snapshots/it__ecosystem__packse-lock-file.snap @@ -332,7 +332,7 @@ serve = [ { name = "watchfiles" }, ] -[package.dev-dependencies] +[package.dependency-groups] dev = [ { name = "psutil" }, { name = "pytest" }, @@ -352,7 +352,7 @@ requires-dist = [ { name = "watchfiles", marker = "extra == 'serve'", specifier = ">=0.21.0" }, ] -[package.metadata.requires-dev] +[package.metadata.dependency-groups] dev = [ { name = "psutil", specifier = ">=5.9.7" }, { name = "pytest", specifier = ">=7.4.3" }, diff --git a/crates/uv/tests/it/snapshots/it__ecosystem__warehouse-lock-file.snap b/crates/uv/tests/it/snapshots/it__ecosystem__warehouse-lock-file.snap index a8dd7118a200..ef050b15158d 100644 --- a/crates/uv/tests/it/snapshots/it__ecosystem__warehouse-lock-file.snap +++ b/crates/uv/tests/it/snapshots/it__ecosystem__warehouse-lock-file.snap @@ -3889,7 +3889,7 @@ deploy = [ { name = "gunicorn" }, ] -[package.dev-dependencies] +[package.dependency-groups] dev = [ { name = "asyncudp" }, { name = "black" }, @@ -4033,7 +4033,7 @@ requires-dist = [ { name = "zxcvbn" }, ] -[package.metadata.requires-dev] +[package.metadata.dependency-groups] dev = [ { name = "asyncudp", specifier = ">=0.7" }, { name = "black", specifier = "==24.4.2" }, diff --git a/crates/uv/tests/it/snapshots/it__workflow__packse_add_remove_existing_package_noop-2.snap b/crates/uv/tests/it/snapshots/it__workflow__packse_add_remove_existing_package_noop-2.snap index 1724c2885e91..b543a440fe5b 100644 --- a/crates/uv/tests/it/snapshots/it__workflow__packse_add_remove_existing_package_noop-2.snap +++ b/crates/uv/tests/it/snapshots/it__workflow__packse_add_remove_existing_package_noop-2.snap @@ -328,7 +328,7 @@ serve = [ { name = "watchfiles" }, ] -[package.dev-dependencies] +[package.dependency-groups] dev = [ { name = "psutil" }, { name = "pytest" }, @@ -348,7 +348,7 @@ requires-dist = [ { name = "watchfiles", marker = "extra == 'serve'", specifier = ">=0.21.0" }, ] -[package.metadata.requires-dev] +[package.metadata.dependency-groups] dev = [ { name = "psutil", specifier = ">=5.9.7" }, { name = "pytest", specifier = ">=7.4.3" }, diff --git a/crates/uv/tests/it/snapshots/it__workflow__packse_add_remove_one_package-2.snap b/crates/uv/tests/it/snapshots/it__workflow__packse_add_remove_one_package-2.snap index 1724c2885e91..b543a440fe5b 100644 --- a/crates/uv/tests/it/snapshots/it__workflow__packse_add_remove_one_package-2.snap +++ b/crates/uv/tests/it/snapshots/it__workflow__packse_add_remove_one_package-2.snap @@ -328,7 +328,7 @@ serve = [ { name = "watchfiles" }, ] -[package.dev-dependencies] +[package.dependency-groups] dev = [ { name = "psutil" }, { name = "pytest" }, @@ -348,7 +348,7 @@ requires-dist = [ { name = "watchfiles", marker = "extra == 'serve'", specifier = ">=0.21.0" }, ] -[package.metadata.requires-dev] +[package.metadata.dependency-groups] dev = [ { name = "psutil", specifier = ">=5.9.7" }, { name = "pytest", specifier = ">=7.4.3" }, diff --git a/crates/uv/tests/it/snapshots/it__workflow__packse_promote_transitive_to_direct_then_remove-2.snap b/crates/uv/tests/it/snapshots/it__workflow__packse_promote_transitive_to_direct_then_remove-2.snap index 1724c2885e91..b543a440fe5b 100644 --- a/crates/uv/tests/it/snapshots/it__workflow__packse_promote_transitive_to_direct_then_remove-2.snap +++ b/crates/uv/tests/it/snapshots/it__workflow__packse_promote_transitive_to_direct_then_remove-2.snap @@ -328,7 +328,7 @@ serve = [ { name = "watchfiles" }, ] -[package.dev-dependencies] +[package.dependency-groups] dev = [ { name = "psutil" }, { name = "pytest" }, @@ -348,7 +348,7 @@ requires-dist = [ { name = "watchfiles", marker = "extra == 'serve'", specifier = ">=0.21.0" }, ] -[package.metadata.requires-dev] +[package.metadata.dependency-groups] dev = [ { name = "psutil", specifier = ">=5.9.7" }, { name = "pytest", specifier = ">=7.4.3" }, diff --git a/crates/uv/tests/it/workflow.rs b/crates/uv/tests/it/workflow.rs index 204a2137ee95..7dcf9ad4697e 100644 --- a/crates/uv/tests/it/workflow.rs +++ b/crates/uv/tests/it/workflow.rs @@ -72,7 +72,7 @@ fn packse_add_remove_one_package() { { name = "watchfiles", marker = "extra == 'serve'", specifier = ">=0.21.0" }, ] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [ { name = "psutil", specifier = ">=5.9.7" }, { name = "pytest", specifier = ">=7.4.3" }, @@ -160,7 +160,7 @@ fn packse_add_remove_one_package() { { name = "watchfiles", marker = "extra == 'serve'", specifier = ">=0.21.0" }, ] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [ { name = "psutil", specifier = ">=5.9.7" }, { name = "pytest", specifier = ">=7.4.3" }, @@ -315,7 +315,7 @@ fn packse_promote_transitive_to_direct_then_remove() { { name = "watchfiles", marker = "extra == 'serve'", specifier = ">=0.21.0" }, ] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [ { name = "psutil", specifier = ">=5.9.7" }, { name = "pytest", specifier = ">=7.4.3" }, @@ -373,7 +373,7 @@ fn packse_promote_transitive_to_direct_then_remove() { { name = "watchfiles", marker = "extra == 'serve'", specifier = ">=0.21.0" }, ] - [package.metadata.requires-dev] + [package.metadata.dependency-groups] dev = [ { name = "psutil", specifier = ">=5.9.7" }, { name = "pytest", specifier = ">=7.4.3" },