From 44ed1c9d95a15fe4ba964ce78a0fab89bf0e9843 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Wed, 31 Jul 2024 10:09:24 -0400 Subject: [PATCH 01/11] uv-resolver: rewrite forking to be based on overlapping markers Closes #4732 --- crates/uv-resolver/src/resolver/mod.rs | 602 +++++++++---------------- 1 file changed, 212 insertions(+), 390 deletions(-) diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index 1850988cf505..e08088f49cd2 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -704,38 +704,52 @@ impl ResolverState ResolverState result.map(|deps| match deps { - Dependencies::Available(deps) => ForkedDependencies::Unforked(deps), + Dependencies::Available(deps) | Dependencies::Unforkable(deps) => { + ForkedDependencies::Unforked(deps) + } Dependencies::Unavailable(err) => ForkedDependencies::Unavailable(err), }), ResolverMarkers::Universal { .. } | ResolverMarkers::Fork(_) => Ok(result?.fork()), @@ -1298,7 +1314,7 @@ impl ResolverState ResolverState return Ok(Dependencies::Available(Vec::default())), + PubGrubPackageInner::Python(_) => return Ok(Dependencies::Unforkable(Vec::default())), // Add a dependency on both the marker and base package. PubGrubPackageInner::Marker { name, marker } => { - return Ok(Dependencies::Available( + return Ok(Dependencies::Unforkable( [None, Some(marker)] .into_iter() .map(move |marker| PubGrubDependency { @@ -1369,7 +1385,7 @@ impl ResolverState { - return Ok(Dependencies::Available( + return Ok(Dependencies::Unforkable( [None, marker.as_ref()] .into_iter() .dedup() @@ -1395,7 +1411,7 @@ impl ResolverState { - return Ok(Dependencies::Available( + return Ok(Dependencies::Unforkable( [None, marker.as_ref()] .into_iter() .dedup() @@ -1419,7 +1435,32 @@ impl ResolverState), + /// Dependencies that should never result in a fork. + /// + /// For example, the dependencies of a `Marker` package will have the + /// same name and version, but differ according to marker expressions. + /// But we never want this to result in a fork. + Unforkable(Vec), } impl Dependencies { @@ -2634,155 +2681,33 @@ impl Dependencies { /// name *and* those dependency specifications have corresponding marker /// expressions that are completely disjoint with one another. fn fork(self) -> ForkedDependencies { - use std::collections::hash_map::Entry; - let deps = match self { Dependencies::Available(deps) => deps, + Dependencies::Unforkable(deps) => return ForkedDependencies::Unforked(deps), Dependencies::Unavailable(err) => return ForkedDependencies::Unavailable(err), }; - - let mut by_name: FxHashMap<&PackageName, PossibleForks> = FxHashMap::default(); - for (index, dependency) in deps.iter().enumerate() { - // A root can never be a dependency of another package, - // and a `Python` pubgrub package is never returned by - // `get_dependencies`. So a pubgrub package always has a - // name in this context. - let name = dependency - .package - .name() - .expect("dependency always has a name"); - let marker = dependency.package.marker(); - let Some(marker) = marker else { - // When no marker is found, it implies there is a dependency on - // this package that is unconditional with respect to marker - // expressions. Therefore, it should never be the cause of a - // fork since it is necessarily overlapping with every other - // possible marker expression that isn't pathological. - match by_name.entry(name) { - Entry::Vacant(e) => { - e.insert(PossibleForks::NoForkPossible(vec![index])); - } - Entry::Occupied(mut e) => { - e.get_mut().push_unconditional_package(index); - } - } - continue; - }; - let possible_forks = match by_name.entry(name) { - // If one doesn't exist, then this is the first dependency - // with this package name. And since it has a marker, we can - // add it as the initial instance of a possibly forking set of - // dependencies. (A fork will only actually happen if another - // dependency is found with the same package name *and* where - // its marker expression is disjoint with this one.) - Entry::Vacant(e) => { - let possible_fork = PossibleFork { - packages: vec![(index, marker)], - }; - let fork_groups = PossibleForkGroups { - forks: vec![possible_fork], - }; - e.insert(PossibleForks::PossiblyForking(fork_groups)); - continue; - } - // Now that we have a marker, look for an existing entry. If - // one already exists and is "no fork possible," then we know - // we can't fork. - Entry::Occupied(e) => match *e.into_mut() { - PossibleForks::NoForkPossible(ref mut indices) => { - indices.push(index); - continue; - } - PossibleForks::PossiblyForking(ref mut possible_forks) => possible_forks, - }, - }; - // At this point, we know we 1) have a duplicate dependency on - // a package and 2) the original and this one both have marker - // expressions. This still doesn't guarantee that a fork occurs - // though. A fork can only occur when the marker expressions from - // (2) are provably disjoint. Otherwise, we could end up with - // a resolution that would result in installing two different - // versions of the same package. Specifically, this could occur in - // precisely the cases where the marker expressions intersect. - // - // By construction, the marker expressions *in* each fork group - // have some non-empty intersection, and the marker expressions - // *between* each fork group are completely disjoint. So what we do - // is look for a group in which there is some overlap. If so, this - // package gets added to that fork group. Otherwise, we create a - // new fork group. - let Some(possible_fork) = possible_forks.find_overlapping_fork_group(marker) else { - // Create a new fork since there was no overlap. - possible_forks.forks.push(PossibleFork { - packages: vec![(index, marker)], - }); - continue; - }; - // Add to an existing fork since there was overlap. - possible_fork.packages.push((index, marker)); + let mut forks = Forks::default(); + for dep in deps { + forks.add(dep); } - // If all possible forks have exactly 1 group, then there is no forking. - if !by_name.values().any(PossibleForks::has_fork) { - return ForkedDependencies::Unforked(deps); - } - let mut forks = vec![Fork { - dependencies: vec![], - markers: MarkerTree::TRUE, - }]; - let mut diverging_packages = Vec::new(); - for (name, possible_forks) in by_name { - let fork_groups = match possible_forks.finish() { - // 'finish()' guarantees that 'PossiblyForking' implies - // 'DefinitelyForking'. - PossibleForks::PossiblyForking(fork_groups) => fork_groups, - PossibleForks::NoForkPossible(indices) => { - // No fork is provoked by this package, so just add - // everything in this group to each of the forks. - for index in indices { - for fork in &mut forks { - fork.add_nonfork_package(deps[index].clone()); - } - } - continue; - } - }; - assert!(fork_groups.forks.len() >= 2, "expected definitive fork"); - let mut new_forks: Vec = vec![]; - if let Some(markers) = fork_groups.remaining_universe() { - trace!("Adding split to cover possibly incomplete markers: {markers:?}"); - let mut new_forks_for_remaining_universe = forks.clone(); - for fork in &mut new_forks_for_remaining_universe { - fork.markers.and(markers.clone()); - fork.remove_disjoint_packages(); - } - new_forks.extend(new_forks_for_remaining_universe); - } - // Each group has a list of packages whose marker expressions are - // guaranteed to be overlapping. So we must union those marker - // expressions and then intersect them with each existing fork. - for group in fork_groups.forks { - let mut new_forks_for_group = forks.clone(); - for fork in &mut new_forks_for_group { - fork.markers.and(group.union()); - fork.remove_disjoint_packages(); - for &(index, _) in &group.packages { - fork.dependencies.push(deps[index].clone()); - } - } - new_forks.extend(new_forks_for_group); - } - forks = new_forks; - diverging_packages.push(name.clone()); - } - - // Prioritize the forks. Prefer solving forks with lower Python bounds, since they're more - // likely to produce solutions that work for forks with higher Python bounds (whereas the - // inverse is not true). - forks.sort(); - - ForkedDependencies::Forked { - forks, + let Forks { + mut forks, diverging_packages, + } = forks; + if forks.is_empty() { + ForkedDependencies::Unforked(vec![]) + } else if forks.len() == 1 { + ForkedDependencies::Unforked(forks.pop().unwrap().dependencies) + } else { + // Prioritize the forks. Prefer solving forks with lower Python + // bounds, since they're more likely to produce solutions that work + // for forks with higher Python bounds (whereas the inverse is not + // true). + forks.sort(); + ForkedDependencies::Forked { + forks, + diverging_packages, + } } } } @@ -2813,6 +2738,112 @@ enum ForkedDependencies { }, } +/// A list of forks determined from the dependencies of a single package. +/// +/// Any time a marker expression is seen that is not true for all possible +/// marker environments, it is possible for it to introduce a new fork. +#[derive(Debug, Default)] +struct Forks { + /// The forks discovered among the dependencies. + forks: Vec, + /// The package(s) that provoked at least one additional fork. + diverging_packages: Vec, +} + +impl Forks { + /// Add the given dependency to this fork. + fn add(&mut self, dep: PubGrubDependency) { + // A root can never be a dependency of another package, + // and a `Python` pubgrub package is never returned by + // `get_dependencies`. So a pubgrub package always has a + // name in this context. + let name = dep.package.name().expect("dependency always has a name"); + let mut markers = dep.package.marker().cloned().unwrap_or(MarkerTree::TRUE); + if markers.is_false() { + // A marker that we know never matches any environment + // can be skipped entirely because its dependency will + // never be included in any circumstance. + return; + } else if self.forks.is_empty() { + // If we don't have any forks yet, we just seed it with + // two forks from `markers` and `not(markers)`. + if !markers.is_true() { + self.diverging_packages.push(name.clone()); + self.forks.push(Fork { + dependencies: vec![], + markers: markers.negate(), + }); + } + self.forks.push(Fork { + dependencies: vec![dep], + markers, + }); + return; + } else if markers.is_true() { + // If our markers match every marker environment, + // then the dependency should be added to every fork. + for fork in &mut self.forks { + fork.dependencies.push(dep.clone()); + } + return; + } + // Otherwise, we *may* need to add a new fork... + + let mut new = vec![]; + let mut found_overlap = false; + for mut fork in std::mem::take(&mut self.forks) { + if fork.markers.is_disjoint(&markers) { + new.push(fork); + continue; + } + found_overlap = true; + self.diverging_packages.push(name.clone()); + + let not_markers = markers.negate(); + let mut new_markers = markers.clone(); + new_markers.and(fork.markers.negate()); + if !not_markers.is_false() && !fork.markers.is_disjoint(¬_markers) { + new.push(Fork { + markers: { + let mut fork_markers = fork.markers.clone(); + fork_markers.and(not_markers); + fork_markers + }, + dependencies: fork.dependencies.clone(), + }); + } + fork.dependencies.push(dep.clone()); + new.push(Fork { + markers: { + let mut fork_markers = fork.markers; + fork_markers.and(markers); + fork_markers + }, + dependencies: fork.dependencies, + }); + markers = new_markers; + } + // I think ideally this would be truly guaranteed, since + // it should always be the case that a non-trivial marker + // expression ALWAYS overlaps with one of our forks, since the + // markers on our forks should always cover the Universe. But + // in practice, `is_disjoint` might not always produce the + // correct result. So we could technically get here even if the + // above logic is correct. + // + // Arguably we could therefore not assert and let this pass, + // but it seems likely that this would lead to even more + // confusing behavior. So for now, we bleat about this being a + // bug. + assert!( + found_overlap, + "expected to find marker overlap with existing fork, \ + but found none, this is a bug in uv, please report it", + ); + self.forks = new; + } +} + /// A single fork in a list of dependencies. /// /// A fork corresponds to the full list of dependencies for a package, @@ -2887,215 +2918,6 @@ impl PartialOrd for Fork { } } -impl Fork { - /// Add the given dependency to this fork. - /// - /// This works by assuming the given package did *not* provoke a fork. - /// - /// It is only added if the markers on the given package are not disjoint - /// with this fork's markers. - fn add_nonfork_package(&mut self, dependency: PubGrubDependency) { - if dependency - .package - .marker() - .map_or(true, |marker| !marker.is_disjoint(&self.markers)) - { - self.dependencies.push(dependency); - } - } - - /// Removes any dependencies in this fork whose markers are disjoint with - /// its own markers. - fn remove_disjoint_packages(&mut self) { - self.dependencies.retain(|dependency| { - dependency - .package - .marker() - .map_or(true, |pkg_marker| !pkg_marker.is_disjoint(&self.markers)) - }); - } -} - -/// Intermediate state that represents a *possible* grouping of forks -/// for one package name. -/// -/// This accumulates state while examining a `Dependencies` list. In -/// particular, it accumulates conflicting dependency specifications and marker -/// expressions. As soon as a fork can be ruled out, this state is switched to -/// `NoForkPossible`. If, at the end of visiting all `Dependencies`, we still -/// have `PossibleForks::PossiblyForking`, then a fork exists if and only if -/// one of its groups has length bigger than `1`. -/// -/// One common way for a fork to be known to be impossible is if there exists -/// conflicting dependency specifications where at least one is unconditional. -/// For example, `a<2` and `a>=2 ; sys_platform == 'foo'`. In this case, `a<2` -/// has a marker expression that is always true and thus never disjoint with -/// any other marker expression. Therefore, there can be no fork for `a`. -/// -/// Note that we use indices into a `Dependencies` list to represent packages. -/// This avoids excessive cloning. -#[derive(Debug)] -enum PossibleForks<'a> { - /// A group of dependencies (all with the same package name) where it is - /// known that no forks exist. - NoForkPossible(Vec), - /// A group of groups dependencies (all with the same package name) where - /// it is possible for each group to correspond to a fork. - PossiblyForking(PossibleForkGroups<'a>), -} - -impl<'a> PossibleForks<'a> { - /// Returns true if and only if this contains a fork assuming there are - /// no other dependencies to be considered. - fn has_fork(&self) -> bool { - let PossibleForks::PossiblyForking(ref fork_groups) = *self else { - return false; - }; - fork_groups.forks.len() > 1 - } - - /// Consumes this possible set of forks and converts a "possibly forking" - /// variant to a "no fork possible" variant if there are no actual forks. - /// - /// This should be called when all dependencies for one package have been - /// considered. It will normalize this value such that `PossiblyForking` - /// means `DefinitelyForking`. - fn finish(mut self) -> PossibleForks<'a> { - let PossibleForks::PossiblyForking(ref fork_groups) = self else { - return self; - }; - if fork_groups.forks.len() == 1 { - self.make_no_forks_possible(); - return self; - } - self - } - - /// Pushes an unconditional index to a package. - /// - /// If this previously contained possible forks, those are combined into - /// one single set of dependencies that can never be forked. - /// - /// That is, adding an unconditional package means it is not disjoint with - /// all other possible dependencies using the same package name. - fn push_unconditional_package(&mut self, index: usize) { - self.make_no_forks_possible(); - let PossibleForks::NoForkPossible(ref mut indices) = *self else { - unreachable!("all forks should be eliminated") - }; - indices.push(index); - } - - /// Convert this set of possible forks into something that can never fork. - /// - /// This is useful in cases where a dependency on a package is found - /// without any marker expressions at all. In this case, it is never - /// possible for this package to provoke a fork. Since it is unconditional, - /// it implies it is never disjoint with any other dependency specification - /// on the same package. (Except for pathological cases of marker - /// expressions that always evaluate to false. But we generally ignore - /// those.) - fn make_no_forks_possible(&mut self) { - let PossibleForks::PossiblyForking(ref fork_groups) = *self else { - return; - }; - let mut indices = vec![]; - for possible_fork in &fork_groups.forks { - for &(index, _) in &possible_fork.packages { - indices.push(index); - } - } - *self = PossibleForks::NoForkPossible(indices); - } -} - -/// A list of groups of dependencies (all with the same package name), where -/// each group may correspond to a fork. -#[derive(Debug)] -struct PossibleForkGroups<'a> { - /// The list of forks. - forks: Vec>, -} - -impl<'a> PossibleForkGroups<'a> { - /// Given a marker expression, if there is a fork in this set of fork - /// groups with non-empty overlap with it, then that fork group is - /// returned. Otherwise, `None` is returned. - fn find_overlapping_fork_group<'g>( - &'g mut self, - marker: &MarkerTree, - ) -> Option<&'g mut PossibleFork<'a>> { - self.forks - .iter_mut() - .find(|fork| fork.is_overlapping(marker)) - } - - /// Returns a marker tree corresponding to the set of marker expressions - /// outside of this fork group. - /// - /// In many cases, it can be easily known that the set of marker - /// expressions referred to by this marker tree is empty. In this case, - /// `None` is returned. But note that if a marker tree is returned, it is - /// still possible for it to describe exactly zero marker environments. - fn remaining_universe(&self) -> Option { - let mut have = MarkerTree::FALSE; - for fork in &self.forks { - have.or(fork.union()); - } - - let missing = have.negate(); - if missing.is_false() { - return None; - } - Some(missing) - } -} - -/// Intermediate state representing a single possible fork. -/// -/// The key invariant here is that, beyond a singleton fork, for all packages -/// in this fork, its marker expression must be overlapping with at least one -/// other package's marker expression. That is, when considering whether a -/// dependency specification with a conflicting package name provokes a fork -/// or not, one must look at the existing possible groups of forks. If any of -/// those groups have a package with an overlapping marker expression, then -/// the conflicting package name cannot possibly introduce a new fork. But if -/// there is no existing fork with an overlapping marker expression, then the -/// conflict provokes a new fork. -/// -/// As with other intermediate data types, we use indices into a list of -/// `Dependencies` to represent packages to avoid excessive cloning. -#[derive(Debug)] -struct PossibleFork<'a> { - packages: Vec<(usize, &'a MarkerTree)>, -} - -impl<'a> PossibleFork<'a> { - /// Returns true if and only if the given marker expression has a non-empty - /// intersection with *any* of the package markers within this possible - /// fork. - fn is_overlapping(&self, candidate_package_markers: &MarkerTree) -> bool { - for (_, package_markers) in &self.packages { - if !candidate_package_markers.is_disjoint(package_markers) { - return true; - } - } - false - } - - /// Returns the union of all the marker expressions in this possible fork. - /// - /// Each marker expression in the union returned is guaranteed to be overlapping - /// with at least one other expression in the same union. - fn union(&self) -> MarkerTree { - let mut union = MarkerTree::FALSE; - for &(_, marker) in &self.packages { - union.or(marker.clone()); - } - union - } -} - /// Returns true if and only if the given requirement's marker expression has a /// possible true value given the `requires_python` specifier given. /// From 04a62cff106bd266654d9207f4933f58d324be27 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 13:56:28 -0400 Subject: [PATCH 02/11] uv/tests: update snapshot that forks when it previously didn't Previously, since the markers weren't disjoint, this didn't result in a fork. But now that we deal with overlapping markers, this is fine. And seems correct. --- crates/uv/tests/branching_urls.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/uv/tests/branching_urls.rs b/crates/uv/tests/branching_urls.rs index 2481b32073b4..b954bb7ecab3 100644 --- a/crates/uv/tests/branching_urls.rs +++ b/crates/uv/tests/branching_urls.rs @@ -67,7 +67,7 @@ fn branching_urls_overlapping() -> Result<()> { ----- stdout ----- ----- stderr ----- - error: Requirements contain conflicting URLs for package `iniconfig`: + error: Requirements contain conflicting URLs for package `iniconfig` in split `python_version < '3.12' and python_version >= '3.11'`: - https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl - https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl "### @@ -678,7 +678,7 @@ fn branching_urls_of_different_sources_conflict() -> Result<()> { ----- stdout ----- ----- stderr ----- - error: Requirements contain conflicting URLs for package `iniconfig`: + error: Requirements contain conflicting URLs for package `iniconfig` in split `python_version < '3.12' and python_version >= '3.11'`: - git+https://github.com/pytest-dev/iniconfig@93f5930e668c0d1ddf4597e38dd0dea4e2665e7a - https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl "### From a18ccf25a07ebcfc7df37a35983a8be6f88517ec Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 13:47:08 -0400 Subject: [PATCH 03/11] uv/tests: only consider dependency specification for fork matching marker The test in this case has this comment: ``` /// If a dependency requests a prerelease version with an overlapping marker expression, /// we should prefer the prerelease version in both forks. ``` With this setup: ``` let pyproject_toml = context.temp_dir.child("pyproject.toml"); pyproject_toml.write_str(indoc! {r#" [project] name = "example" version = "0.0.0" dependencies = [ "cffi >= 1.17.0rc1 ; os_name == 'Linux'" ] requires-python = ">=3.11" "#})?; let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str(indoc! {" cffi . "})?; ``` The change in this commit _seems_ more correct that what we had, although it does seem to contradict the comment. Namely, in the `os_name != "Linux"` fork, we don't prefer the pre-release version since the `cffi >= 1.17.0rc1` bound doesn't apply. It's not quite clear what to do in this instance. --- crates/uv/tests/pip_compile.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 53ae853a5645..a48789e95d6c 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -7717,13 +7717,15 @@ fn universal_disjoint_prereleases_allow() -> Result<()> { ----- stdout ----- # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal --prerelease allow - cffi==1.16.0rc2 + cffi==1.16.0rc2 ; os_name != 'linux' + # via -r requirements.in + cffi==1.16.0 ; os_name == 'linux' # via -r requirements.in pycparser==2.22 # via cffi ----- stderr ----- - Resolved 2 packages in [TIME] + Resolved 3 packages in [TIME] "### ); @@ -7843,7 +7845,9 @@ fn universal_overlapping_prerelease_requirement() -> Result<()> { ----- stdout ----- # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal - cffi==1.17.0rc1 + cffi==1.16.0 ; os_name != 'Linux' + # via -r requirements.in + cffi==1.17.0rc1 ; os_name == 'Linux' # via # -r requirements.in # example @@ -7853,7 +7857,7 @@ fn universal_overlapping_prerelease_requirement() -> Result<()> { # via cffi ----- stderr ----- - Resolved 3 packages in [TIME] + Resolved 4 packages in [TIME] "### ); From cf09206e45624e44b51a0c0a1bd0016cacd2566a Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 13:36:20 -0400 Subject: [PATCH 04/11] uv/tests: update another test that now succeeds Fixes #4668 --- crates/uv/tests/pip_compile.rs | 39 ++++++---------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index a48789e95d6c..1ad4a1037a0a 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -7975,42 +7975,17 @@ fn universal_requires_python_incomplete() -> Result<()> { .arg("-p") .arg("3.7") .arg("--universal"), @r###" - success: false - exit_code: 1 + success: true + exit_code: 0 ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in -p 3.7 --universal + uv==0.1.24 ; python_version >= '3.8' + # via -r requirements.in ----- stderr ----- warning: The requested Python version 3.7 is not available; 3.12.[X] will be used to build dependencies instead. - × No solution found when resolving dependencies: - ╰─▶ Because only the following versions of uv{python_version >= '3.8'} are available: - uv{python_version >= '3.8'}==0.0.5 - uv{python_version >= '3.8'}==0.1.0 - uv{python_version >= '3.8'}==0.1.1 - uv{python_version >= '3.8'}==0.1.2 - uv{python_version >= '3.8'}==0.1.3 - uv{python_version >= '3.8'}==0.1.4 - uv{python_version >= '3.8'}==0.1.5 - uv{python_version >= '3.8'}==0.1.6 - uv{python_version >= '3.8'}==0.1.7 - uv{python_version >= '3.8'}==0.1.8 - uv{python_version >= '3.8'}==0.1.9 - uv{python_version >= '3.8'}==0.1.10 - uv{python_version >= '3.8'}==0.1.11 - uv{python_version >= '3.8'}==0.1.12 - uv{python_version >= '3.8'}==0.1.13 - uv{python_version >= '3.8'}==0.1.14 - uv{python_version >= '3.8'}==0.1.15 - uv{python_version >= '3.8'}==0.1.16 - uv{python_version >= '3.8'}==0.1.17 - uv{python_version >= '3.8'}==0.1.18 - uv{python_version >= '3.8'}==0.1.19 - uv{python_version >= '3.8'}==0.1.20 - uv{python_version >= '3.8'}==0.1.21 - uv{python_version >= '3.8'}==0.1.22 - uv{python_version >= '3.8'}==0.1.23 - uv{python_version >= '3.8'}==0.1.24 - and the requested Python version (>=3.7) does not satisfy Python>=3.8, we can conclude that all versions of uv{python_version >= '3.8'} are incompatible. - And because you require uv{python_version >= '3.8'}, we can conclude that the requirements are unsatisfiable. + Resolved 1 package in [TIME] "### ); From 3d18567f794884eba93ff4b0ba73a450284440e9 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 13:35:39 -0400 Subject: [PATCH 05/11] uv/tests: update test that expects to find a resolution Fixes #4640 --- crates/uv/tests/pip_compile.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 1ad4a1037a0a..2a2d54a4cea7 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -6803,13 +6803,18 @@ fn universal_multi_version() -> Result<()> { .arg("-c") .arg("constraints.txt") .arg("--universal"), @r###" - success: false - exit_code: 1 + success: true + exit_code: 0 ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in -c constraints.txt --universal + iniconfig==1.0.0 ; python_version == '3.12' + # via -r requirements.in + iniconfig==2.0.0 ; python_version > '3.12' + # via -r requirements.in ----- stderr ----- - × No solution found when resolving dependencies: - ╰─▶ Because you require iniconfig{python_version > '3.12'}==2.0.0 and iniconfig{python_version == '3.12'}==1.0.0, we can conclude that the requirements are unsatisfiable. + Resolved 2 packages in [TIME] "### ); From e5a4fd129fbe6409682225b9abb3f06d4f6f7c9b Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 13:17:11 -0400 Subject: [PATCH 06/11] uv/tests: accept tests that now find a resolution which previously didn't! I wasn't expecting these scenarios to suddenly work, but because of the aggressive forking strategy of overlapping markers, these both now produce a valid resolution. Previously, we *only* forked when there were disjoint markers for the same dependency specification. But now we potentially fork whenever there is any single marker, and this results in different forks reaching what were conflicting dependency specifications. And thus, things work here. --- crates/uv/tests/lock_scenarios.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/crates/uv/tests/lock_scenarios.rs b/crates/uv/tests/lock_scenarios.rs index d086e1fa6a7d..980494bd7877 100644 --- a/crates/uv/tests/lock_scenarios.rs +++ b/crates/uv/tests/lock_scenarios.rs @@ -2707,16 +2707,13 @@ fn fork_non_local_fork_marker_direct() -> Result<()> { cmd.env_remove("UV_EXCLUDE_NEWER"); cmd.arg("--index-url").arg(packse_index_url()); uv_snapshot!(filters, cmd, @r###" - success: false - exit_code: 1 + success: true + exit_code: 0 ----- stdout ----- ----- stderr ----- warning: `uv lock` is experimental and may change without warning - × No solution found when resolving dependencies: - ╰─▶ Because package-b{sys_platform == 'darwin'}==1.0.0 depends on package-c>=2.0.0 and package-a{sys_platform == 'linux'}==1.0.0 depends on package-c<2.0.0, we can conclude that package-a{sys_platform == 'linux'}==1.0.0 and package-b{sys_platform == 'darwin'}==1.0.0 are incompatible. - And because project==0.1.0 depends on package-a{sys_platform == 'linux'}==1.0.0 and package-b{sys_platform == 'darwin'}==1.0.0, we can conclude that project==0.1.0 cannot be used. - And because only project==0.1.0 is available and you require project, we can conclude that the requirements are unsatisfiable. + Resolved 5 packages in [TIME] "### ); @@ -2781,20 +2778,13 @@ fn fork_non_local_fork_marker_transitive() -> Result<()> { cmd.env_remove("UV_EXCLUDE_NEWER"); cmd.arg("--index-url").arg(packse_index_url()); uv_snapshot!(filters, cmd, @r###" - success: false - exit_code: 1 + success: true + exit_code: 0 ----- stdout ----- ----- stderr ----- warning: `uv lock` is experimental and may change without warning - × No solution found when resolving dependencies: - ╰─▶ Because package-b==1.0.0 depends on package-c{sys_platform == 'darwin'}>=2.0.0 and only package-c{sys_platform == 'darwin'}<=2.0.0 is available, we can conclude that package-b==1.0.0 depends on package-c{sys_platform == 'darwin'}==2.0.0. - And because only the following versions of package-c{sys_platform == 'linux'} are available: - package-c{sys_platform == 'linux'}==1.0.0 - package-c{sys_platform == 'linux'}>=2.0.0 - and package-a==1.0.0 depends on package-c{sys_platform == 'linux'}<2.0.0, we can conclude that package-a==1.0.0 and package-b==1.0.0 are incompatible. - And because project==0.1.0 depends on package-a==1.0.0 and package-b==1.0.0, we can conclude that project==0.1.0 cannot be used. - And because only project==0.1.0 is available and you require project, we can conclude that the requirements are unsatisfiable. + Resolved 5 packages in [TIME] "### ); From 2872c4c910af017ab9b0763b787d21b743577932 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 12:56:32 -0400 Subject: [PATCH 07/11] uv/tests: update preferences test From looking at this carefully, I believe the result here is still correct but "different" from the status quo based on the order in which forks are processed. (At time of writing, we do sort forks, but we don't use comprehensive criteria. So at least in some cases, the order depends on the order that the forks were created. Since the overlapping markers code completely changes how we generate forks, that seems plausible here.) --- crates/uv/tests/lock_scenarios.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/uv/tests/lock_scenarios.rs b/crates/uv/tests/lock_scenarios.rs index 980494bd7877..8b5788459887 100644 --- a/crates/uv/tests/lock_scenarios.rs +++ b/crates/uv/tests/lock_scenarios.rs @@ -3710,18 +3710,20 @@ fn preferences_dependent_forking() -> Result<()> { name = "package-bar" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } + environment-markers = [ + "sys_platform != 'linux'", + ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bar-1.0.0.tar.gz", hash = "sha256:7eef4e0c910b9e4cadf6c707e60a2151f7dc6407d815112ec93a467d76226f5e" } wheels = [ { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bar-1.0.0-py3-none-any.whl", hash = "sha256:3cdaac4b0ba330f902d0628c0b1d6e62692f52255d02718d04f46ade7c8ad6a6" }, ] - [[package]] name = "package-cleaver" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } dependencies = [ - { name = "package-bar", marker = "sys_platform != 'linux'" }, - { name = "package-foo", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, + { name = "package-bar", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, + { name = "package-foo", marker = "sys_platform == 'linux'" }, ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_cleaver-1.0.0.tar.gz", hash = "sha256:0347b927fdf7731758ea53e1594309fc6311ca6983f36553bc11654a264062b2" } wheels = [ @@ -3732,9 +3734,6 @@ fn preferences_dependent_forking() -> Result<()> { name = "package-foo" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } - environment-markers = [ - "sys_platform == 'linux'", - ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_foo-1.0.0.tar.gz", hash = "sha256:abf1c0ac825ee5961e683067634916f98c6651a6d4473ff87d8b57c17af8fed2" } wheels = [ { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_foo-1.0.0-py3-none-any.whl", hash = "sha256:85348e8df4892b9f297560c16abcf231828f538dc07339ed121197a00a0626a5" }, @@ -3757,10 +3756,10 @@ fn preferences_dependent_forking() -> Result<()> { version = "0.1.0" source = { editable = "." } dependencies = [ - { name = "package-bar" }, + { name = "package-bar", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, + { name = "package-bar", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, { name = "package-cleaver" }, - { name = "package-foo", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, - { name = "package-foo", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, + { name = "package-foo" }, ] "### ); From 0495d72d07fb5a0cefc9f6ea869d63e48dbd7a55 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 12:35:25 -0400 Subject: [PATCH 08/11] uv/tests: update error message that suggests a fork This is an interesting update that previously used a message without a fork occurring, but now notes a split. The dependencies in this case are: dependencies = [ '''fork-marker-disjoint-a>=2; sys_platform == "linux"''', '''fork-marker-disjoint-a<2; sys_platform == "linux"''', ] In this case, the markers are the same for conflicting dependency specifications. So the "no resolution" result is correct. But previously, we wouldn't fork here, because we wouldn't consider the marker expressions to be disjoint. But with overlapping markers, we are actually forking here. Namely, we consider a fork with `sys_platform == "linux"` and another with `sys_platform != "linux"`. I actually don't think this is even related to overlapping markers. The previous behavior seems not quite right (even though it led to the same result), because it implies we weren't really considering the "linux" and "not linux" cases as distinct in resolution. --- crates/uv/tests/lock_scenarios.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/uv/tests/lock_scenarios.rs b/crates/uv/tests/lock_scenarios.rs index 8b5788459887..1f263ea10b43 100644 --- a/crates/uv/tests/lock_scenarios.rs +++ b/crates/uv/tests/lock_scenarios.rs @@ -1135,7 +1135,7 @@ fn fork_marker_disjoint() -> Result<()> { ----- stderr ----- warning: `uv lock` is experimental and may change without warning - × No solution found when resolving dependencies: + × No solution found when resolving dependencies for split (sys_platform == 'linux'): ╰─▶ Because project==0.1.0 depends on package-a{sys_platform == 'linux'}>=2 and package-a{sys_platform == 'linux'}<2, we can conclude that project==0.1.0 cannot be used. And because only project==0.1.0 is available and you require project, we can conclude that the requirements are unsatisfiable. "### From 462420f2a6f0e1abaa7e55cbd643cb4976074735 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 10:58:43 -0400 Subject: [PATCH 09/11] uv/tests: fix for 'pysocks' optional dependency for 'requests' This comes from this dependency specification: dependencies = ["requests", "requests[socks] ; python_version < '3.10'"] Previously, the `pysocks` dependency was unconditionally included when the `socks` extra was enabled. But it should only be included when `python_version < '3.10'`, which is now reflected here via a marker. --- crates/uv/tests/lock.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index 8247b2f408db..3fe60b96e4c8 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -1508,6 +1508,10 @@ fn lock_conditional_dependency_extra() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.7" + environment-markers = [ + "python_version < '3.10'", + "python_version >= '3.10'", + ] [options] exclude-newer = "2024-03-25 00:00:00 UTC" @@ -1662,7 +1666,7 @@ fn lock_conditional_dependency_extra() -> Result<()> { [package.optional-dependencies] socks = [ - { name = "pysocks" }, + { name = "pysocks", marker = "python_version < '3.10'" }, ] [[package]] From 1aa62a1f4e52af70728afabd272934c5333907a7 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 2 Aug 2024 10:55:09 -0400 Subject: [PATCH 10/11] uv/tests: update snapshots from overlapping marker change This commit is meant to group together test updates that are "uninteresting." That is, most updates are just adding marker expressions that are "always true" or establishing the forks in the lock file. I've tried to split out the interesting snapshot changes into subsequent commits. Some of the marker changes here are quite striking. I checked most of them. Every one I checked, including the big ones, are all just fancy ways of saying, "always true." --- crates/uv/tests/branching_urls.rs | 4 +- crates/uv/tests/edit.rs | 4 + crates/uv/tests/lock.rs | 35 +++- crates/uv/tests/lock_scenarios.rs | 266 +++++++++++++++--------------- crates/uv/tests/tree.rs | 5 +- 5 files changed, 173 insertions(+), 141 deletions(-) diff --git a/crates/uv/tests/branching_urls.rs b/crates/uv/tests/branching_urls.rs index b954bb7ecab3..03151177a939 100644 --- a/crates/uv/tests/branching_urls.rs +++ b/crates/uv/tests/branching_urls.rs @@ -67,7 +67,7 @@ fn branching_urls_overlapping() -> Result<()> { ----- stdout ----- ----- stderr ----- - error: Requirements contain conflicting URLs for package `iniconfig` in split `python_version < '3.12' and python_version >= '3.11'`: + error: Requirements contain conflicting URLs for package `iniconfig` in split `python_version >= '3.11' and python_version < '3.12'`: - https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl - https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl "### @@ -678,7 +678,7 @@ fn branching_urls_of_different_sources_conflict() -> Result<()> { ----- stdout ----- ----- stderr ----- - error: Requirements contain conflicting URLs for package `iniconfig` in split `python_version < '3.12' and python_version >= '3.11'`: + error: Requirements contain conflicting URLs for package `iniconfig` in split `python_version >= '3.11' and python_version < '3.12'`: - git+https://github.com/pytest-dev/iniconfig@93f5930e668c0d1ddf4597e38dd0dea4e2665e7a - https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl "### diff --git a/crates/uv/tests/edit.rs b/crates/uv/tests/edit.rs index 914f5ef9968a..2fc21da0dfb8 100644 --- a/crates/uv/tests/edit.rs +++ b/crates/uv/tests/edit.rs @@ -1580,6 +1580,10 @@ fn update() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.12" + environment-markers = [ + "python_version <= '3.7'", + "python_version > '3.7'", + ] [options] exclude-newer = "2024-03-25 00:00:00 UTC" diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index 3fe60b96e4c8..7dfd3ea9e33a 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -1308,6 +1308,10 @@ fn lock_dependency_extra() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.12" + environment-markers = [ + "platform_system != 'Windows'", + "platform_system == 'Windows'", + ] [options] exclude-newer = "2024-03-25 00:00:00 UTC" @@ -1407,6 +1411,7 @@ fn lock_dependency_extra() -> Result<()> { version = "0.1.0" source = { editable = "." } dependencies = [ + { name = "flask" }, { name = "flask", extra = ["dotenv"] }, ] @@ -1787,6 +1792,10 @@ fn lock_dependency_non_existent_extra() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.12" + environment-markers = [ + "platform_system != 'Windows'", + "platform_system == 'Windows'", + ] [options] exclude-newer = "2024-03-25 00:00:00 UTC" @@ -2683,6 +2692,11 @@ fn lock_requires_python() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.7" + environment-markers = [ + "python_version >= '3.11'", + "python_version < '3.8'", + "python_version >= '3.8' and python_version < '3.11'", + ] [options] exclude-newer = "2024-03-25 00:00:00 UTC" @@ -2728,7 +2742,7 @@ fn lock_requires_python() -> Result<()> { source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_version < '3.8'" }, - { name = "zipp" }, + { name = "zipp", marker = "python_version < '3.8'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a3/82/f6e29c8d5c098b6be61460371c2c5591f4a335923639edec43b3830650a4/importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", size = 53569 } wheels = [ @@ -2834,6 +2848,11 @@ fn lock_requires_python() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.7.9" + environment-markers = [ + "python_version < '3.8'", + "python_version >= '3.11'", + "python_version >= '3.8' and python_version < '3.11'", + ] [options] exclude-newer = "2024-03-25 00:00:00 UTC" @@ -2879,7 +2898,7 @@ fn lock_requires_python() -> Result<()> { source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_version < '3.8'" }, - { name = "zipp" }, + { name = "zipp", marker = "python_version < '3.8'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a3/82/f6e29c8d5c098b6be61460371c2c5591f4a335923639edec43b3830650a4/importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", size = 53569 } wheels = [ @@ -3590,12 +3609,12 @@ fn lock_python_version_marker_complement() -> Result<()> { version = 1 requires-python = ">=3.8" environment-markers = [ - "python_full_version > '3.10' and python_version > '3.10'", - "python_full_version > '3.10' and python_version == '3.10'", "python_full_version > '3.10' and python_version < '3.10'", - "python_full_version <= '3.10' and python_version > '3.10'", - "python_full_version <= '3.10' and python_version == '3.10'", "python_full_version <= '3.10' and python_version < '3.10'", + "python_full_version > '3.10' and python_version == '3.10'", + "python_full_version > '3.10' and python_version > '3.10'", + "python_full_version <= '3.10' and python_version == '3.10'", + "python_full_version <= '3.10' and python_version > '3.10'", ] [options] @@ -3851,6 +3870,10 @@ fn lock_multiple_markers() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.12" + environment-markers = [ + "implementation_name != 'cpython'", + "implementation_name == 'cpython'", + ] [options] exclude-newer = "2024-03-25 00:00:00 UTC" diff --git a/crates/uv/tests/lock_scenarios.rs b/crates/uv/tests/lock_scenarios.rs index 1f263ea10b43..645675d36eac 100644 --- a/crates/uv/tests/lock_scenarios.rs +++ b/crates/uv/tests/lock_scenarios.rs @@ -873,7 +873,8 @@ fn fork_incomplete_markers() -> Result<()> { environment-markers = [ "python_version < '3.10'", "python_version >= '3.11'", - "python_version >= '3.10' and python_version < '3.11'", + "python_version == '3.10'", + "python_version > '3.10' and python_version < '3.11'", ] [[package]] @@ -1018,6 +1019,13 @@ fn fork_marker_accrue() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.8" + environment-markers = [ + "implementation_name != 'cpython' and implementation_name != 'pypy'", + "implementation_name == 'cpython' and sys_platform == 'linux'", + "implementation_name == 'cpython' and sys_platform != 'linux'", + "implementation_name == 'pypy' and sys_platform == 'darwin'", + "implementation_name == 'pypy' and sys_platform != 'darwin'", + ] [[package]] name = "package-a" @@ -2449,9 +2457,13 @@ fn fork_marker_track() -> Result<()> { version = 1 requires-python = ">=3.8" environment-markers = [ - "sys_platform == 'linux'", - "sys_platform == 'darwin'", - "sys_platform != 'darwin' and sys_platform != 'linux'", + "implementation_name == 'pypy' and sys_platform == 'darwin'", + "implementation_name == 'iron' and sys_platform == 'darwin'", + "implementation_name != 'iron' and implementation_name != 'pypy' and sys_platform == 'darwin'", + "implementation_name == 'iron' and sys_platform == 'linux'", + "implementation_name != 'iron' and sys_platform == 'linux'", + "implementation_name == 'iron' and sys_platform != 'darwin' and sys_platform != 'linux'", + "implementation_name != 'iron' and sys_platform != 'darwin' and sys_platform != 'linux'", ] [[package]] @@ -2471,7 +2483,9 @@ fn fork_marker_track() -> Result<()> { version = "2.7" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform == 'darwin'", + "implementation_name == 'pypy' and sys_platform == 'darwin'", + "implementation_name == 'iron' and sys_platform == 'darwin'", + "implementation_name != 'iron' and implementation_name != 'pypy' and sys_platform == 'darwin'", ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_marker_track_b-2.7.tar.gz", hash = "sha256:855bf45837a4ba669a5850b14b0253cb138925fdd2b06a2f15c6582b8fabb8a0" } wheels = [ @@ -2483,7 +2497,8 @@ fn fork_marker_track() -> Result<()> { version = "2.8" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform == 'linux'", + "implementation_name == 'iron' and sys_platform == 'linux'", + "implementation_name != 'iron' and sys_platform == 'linux'", ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_marker_track_b-2.8.tar.gz", hash = "sha256:2e14b0ff1fb7f5cf491bd31d876218adee1d6a208ff197dc30363cdf25262e80" } wheels = [ @@ -2595,6 +2610,11 @@ fn fork_non_fork_marker_transitive() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.8" + environment-markers = [ + "sys_platform == 'darwin'", + "sys_platform == 'linux'", + "sys_platform != 'darwin' and sys_platform != 'linux'", + ] [[package]] name = "package-a" @@ -2886,7 +2906,8 @@ fn fork_overlapping_markers_basic() -> Result<()> { requires-python = ">=3.8" environment-markers = [ "python_version < '3.10'", - "python_version >= '3.10'", + "python_version >= '3.11'", + "python_version >= '3.10' and python_version < '3.11'", ] [[package]] @@ -3033,7 +3054,7 @@ fn preferences_dependent_forking_bistable() -> Result<()> { ----- stderr ----- warning: `uv lock` is experimental and may change without warning - Resolved 8 packages in [TIME] + Resolved 7 packages in [TIME] "### ); @@ -3046,95 +3067,89 @@ fn preferences_dependent_forking_bistable() -> Result<()> { version = 1 requires-python = ">=3.8" environment-markers = [ - "sys_platform != 'linux'", - "sys_platform == 'linux'", + "os_name == 'posix' and sys_platform != 'linux'", + "os_name == 'posix' and sys_platform == 'linux'", + "os_name != 'posix' and sys_platform != 'linux'", + "os_name != 'posix' and sys_platform == 'linux'", ] [[package]] name = "package-cleaver" - version = "1.0.0" + version = "2.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } dependencies = [ - { name = "package-fork-if-not-forked", version = "3.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, - { name = "package-fork-if-not-forked-proxy", marker = "sys_platform != 'linux'" }, - { name = "package-reject-cleaver1", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, - { name = "package-reject-cleaver1-proxy" }, + { name = "package-fork-sys-platform", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, + { name = "package-fork-sys-platform", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, + { name = "package-reject-cleaver2", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "os_name == 'posix'" }, + { name = "package-reject-cleaver2-proxy" }, ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_cleaver-1.0.0.tar.gz", hash = "sha256:64e5ee0c81d6a51fb71ed517fd04cc26c656908ad05073270e67c2f9b92194c5" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_cleaver-2.0.0.tar.gz", hash = "sha256:c524600c2314a0f30f0b21e12429c636af6c92c01b8c3c0fd1749b8f443dc342" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_cleaver-1.0.0-py3-none-any.whl", hash = "sha256:552a061bf303fc4103ff91adb03864391a041f9bdcb9b2f8a552b232efce633b" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_cleaver-2.0.0-py3-none-any.whl", hash = "sha256:d4a53269c01cd4d42cf18b660ac14ea9ea2556315c94a610b5f31423f61ca3a8" }, ] [[package]] - name = "package-fork-if-not-forked" - version = "2.0.0" + name = "package-fork-sys-platform" + version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform != 'linux'", + "os_name == 'posix' and sys_platform == 'linux'", + "os_name != 'posix' and sys_platform == 'linux'", ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_if_not_forked-2.0.0.tar.gz", hash = "sha256:1f130c437449e7f0752938bff562addd287b6df96784122885e83563f7624798" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_sys_platform-1.0.0.tar.gz", hash = "sha256:e581c43c60b65b164338e44e17202882fe90fe126a0ae928d4cea107d87b7430" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_if_not_forked-2.0.0-py3-none-any.whl", hash = "sha256:a3e0a53d855ef38b9bbe2c6de67a1dd5eefc65c40e02b5282319cabf59bac740" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_sys_platform-1.0.0-py3-none-any.whl", hash = "sha256:96a3d64b166b2e31cc45dbf8c9127c171cc854ab65cf19470268f509845d3a3f" }, ] [[package]] - name = "package-fork-if-not-forked" - version = "3.0.0" + name = "package-fork-sys-platform" + version = "2.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform == 'linux'", + "os_name == 'posix' and sys_platform != 'linux'", + "os_name != 'posix' and sys_platform != 'linux'", ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_if_not_forked-3.0.0.tar.gz", hash = "sha256:72aee18148130c3287f2e07f31cd8883f1b35d91d6ef5230961e5fcc57667943" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_sys_platform-2.0.0.tar.gz", hash = "sha256:500e61eb8a64265addcfdb0aead7d951f17fbaaa7d02c03d9c7551341c14a703" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_if_not_forked-3.0.0-py3-none-any.whl", hash = "sha256:45343fd8a37969d5ace1fe0d235341573b1dc84eea099d92f479d41a21e206fa" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_sys_platform-2.0.0-py3-none-any.whl", hash = "sha256:c9e49b07ca2f53e27ab274bd3193e821b0b9c0c2b54236ecb8aefd75ba05dbe4" }, ] [[package]] - name = "package-fork-if-not-forked-proxy" - version = "1.0.0" - source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } - dependencies = [ - { name = "package-fork-if-not-forked", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, - ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_if_not_forked_proxy-1.0.0.tar.gz", hash = "sha256:0ed00a7c8280348225835fadc76db8ecc6b4a9ee11351a6c432c475f8d1579de" } - wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_fork_if_not_forked_proxy-1.0.0-py3-none-any.whl", hash = "sha256:0f6bd3726cd7aa245751f08e176caa797a5de986f020b7d0b8767756eea77d26" }, - ] - - [[package]] - name = "package-reject-cleaver1" + name = "package-reject-cleaver2" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform == 'linux'", + "os_name == 'posix' and sys_platform != 'linux'", + "os_name == 'posix' and sys_platform == 'linux'", ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver1-1.0.0.tar.gz", hash = "sha256:bf19f244de469bb73c7fb9dc438bca2fac829d865e546327694b2f292192c042" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver2-1.0.0.tar.gz", hash = "sha256:dd794f3c53e5ad8b4a73effe1ce7b4b130c34ac615408c67688db7b8ecae4b39" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver1-1.0.0-py3-none-any.whl", hash = "sha256:bda045df120e617d369b8be48e7a489c57968ee2b75e181969593fbc2a789519" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver2-1.0.0-py3-none-any.whl", hash = "sha256:578ed10e365352096767eede4d3329c1de2e87d90619ad3148c4bb9c87129ed8" }, ] [[package]] - name = "package-reject-cleaver1" + name = "package-reject-cleaver2" version = "2.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform != 'linux'", + "os_name != 'posix' and sys_platform != 'linux'", + "os_name != 'posix' and sys_platform == 'linux'", ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver1-2.0.0.tar.gz", hash = "sha256:b671f6112e6829557bec5c1aa86e55e79a9883a28117025523a132ff24cd9be3" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver2-2.0.0.tar.gz", hash = "sha256:8321e824e4e6906922bc17fe90ad71ed85e00a27379772127e0c4cfdfc05c264" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver1-2.0.0-py3-none-any.whl", hash = "sha256:104923522767e447fb2ff3e2cfc730f5d2d4b2040f89a33d1abeb9863ed169ac" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver2-2.0.0-py3-none-any.whl", hash = "sha256:7a786ef110770aecd79fd9c9a07bf403f8bc73c474f8534f0cb54dee48056720" }, ] [[package]] - name = "package-reject-cleaver1-proxy" + name = "package-reject-cleaver2-proxy" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } dependencies = [ - { name = "package-reject-cleaver1", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, + { name = "package-reject-cleaver2", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "os_name != 'posix'" }, ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver1_proxy-1.0.0.tar.gz", hash = "sha256:6b6eaa229d55de992e36084521d2f62dce35120a866e20354d0e5617e16e00ce" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver2_proxy-1.0.0.tar.gz", hash = "sha256:c50705b6e43c07fa916f41a38bf4c343e890ec513b259c7d3367fee7feb70c64" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver1_proxy-1.0.0-py3-none-any.whl", hash = "sha256:08ace26d0f4a74275dd38803fd67101eaf2cb400441fc8d479461ced31a947c1" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bistable_reject_cleaver2_proxy-1.0.0-py3-none-any.whl", hash = "sha256:95222a82e43181e65c2bcb748a3cc5ba07b352e79b04ed842371de42a3e3701f" }, ] [[package]] @@ -3411,7 +3426,7 @@ fn preferences_dependent_forking_tristable() -> Result<()> { ----- stderr ----- warning: `uv lock` is experimental and may change without warning - Resolved 11 packages in [TIME] + Resolved 10 packages in [TIME] "### ); @@ -3424,136 +3439,119 @@ fn preferences_dependent_forking_tristable() -> Result<()> { version = 1 requires-python = ">=3.8" environment-markers = [ - "sys_platform != 'linux'", - "sys_platform == 'linux'", + "os_name == 'posix' and sys_platform == 'linux'", + "os_name != 'posix' and sys_platform == 'linux'", + "os_name == 'posix' and sys_platform != 'linux'", + "os_name != 'posix' and sys_platform != 'linux'", ] [[package]] - name = "package-bar" + name = "package-a" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } dependencies = [ - { name = "package-c", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, - { name = "package-d", marker = "sys_platform != 'linux'" }, - { name = "package-reject-cleaver-1" }, + { name = "package-unrelated-dep3", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "os_name == 'posix'" }, ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_bar-1.0.0.tar.gz", hash = "sha256:5d7142b60729bd25206dde836b8f629c72a29593156dee4c4551ad23b7096e8c" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_a-1.0.0.tar.gz", hash = "sha256:02ddd7b58306ea47c4451d8f76bc1b160c599e46ee9a747ce349d3d86749203d" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_bar-1.0.0-py3-none-any.whl", hash = "sha256:a590cb59852676a12e3537efe2c812c0640a32408a2ea7f6e5611c7190683865" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_a-1.0.0-py3-none-any.whl", hash = "sha256:06451c53321ce0ca9c76fdde06c8174ecd7e7bb899693170aca5bdfae31c9ade" }, ] [[package]] - name = "package-c" - version = "2.0.0" + name = "package-b" + version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } - environment-markers = [ - "sys_platform == 'linux'", + dependencies = [ + { name = "package-unrelated-dep3", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "os_name != 'posix'" }, ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_c-2.0.0.tar.gz", hash = "sha256:f0d941b83146d72e05fde266be4a500400683e6c62ae86dab11af78c2d26587b" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_b-1.0.0.tar.gz", hash = "sha256:a49a4aa1e5fabc6a75921010c2ebfd019a5ef09ff35589e91c144f18b4a594cd" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_c-2.0.0-py3-none-any.whl", hash = "sha256:aaaddb9a24c0827169bd66d4b1b1965ceb375bebdb60047e2d66a05d363df2e3" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_b-1.0.0-py3-none-any.whl", hash = "sha256:fef9a85812aeb2d36aacf5bfde2d9bc5e2e358f87e5485c0ae76e7b80c8c63c5" }, ] [[package]] - name = "package-c" - version = "3.0.0" + name = "package-bar" + version = "2.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } - environment-markers = [ - "sys_platform != 'linux'", - ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_c-3.0.0.tar.gz", hash = "sha256:3531c0ec88cc79cde8106e949c7062854bbd48e3bc60803246372cdc4f4c4864" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_bar-2.0.0.tar.gz", hash = "sha256:cc856e6aca342176e6ba518a298198258b7be3ee7a6b86319c1d8b731e54991e" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_c-3.0.0-py3-none-any.whl", hash = "sha256:c048df9ab2c29bf914684add607dccca9ed7d035608cb92ef789216a15544e8b" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_bar-2.0.0-py3-none-any.whl", hash = "sha256:80195408d22da78f3d6ac3cc955840b5fcb2a76d774120e2aa007c7e7cbc2b4e" }, ] [[package]] name = "package-cleaver" - version = "1.0.0" + version = "2.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } dependencies = [ - { name = "package-bar", marker = "sys_platform != 'linux'" }, - { name = "package-foo", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, + { name = "package-a" }, + { name = "package-b" }, + { name = "package-unrelated-dep", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, + { name = "package-unrelated-dep", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_cleaver-1.0.0.tar.gz", hash = "sha256:49ec5779d0722586652e3ceb4ca2bf053a79dc3fa2d7ccd428a359bcc885a248" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_cleaver-2.0.0.tar.gz", hash = "sha256:433ee6b54459ad67e4b4265270d915f90e985367e66936294f2e14342fd4d8b6" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_cleaver-1.0.0-py3-none-any.whl", hash = "sha256:fb33bd10e4c6a237e7d0488e7ba1c5ee794eb01a1813ff80695bbfc4036f01b7" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_cleaver-2.0.0-py3-none-any.whl", hash = "sha256:5d52ac55a8253363d7a1e376cff78c950c7d3c12086f530eb706fcd546623efb" }, ] [[package]] - name = "package-d" - version = "1.0.0" + name = "package-foo" + version = "2.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } - dependencies = [ - { name = "package-c", version = "3.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, - ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_d-1.0.0.tar.gz", hash = "sha256:690b69acb46d0ebfb11a81f401d2ea2e2e6a8ae97f199d345715e9bd40a7ceba" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_foo-2.0.0.tar.gz", hash = "sha256:1607aa970fac2e237de28636bf53b022b0c391ecc9039e34438638c8743cc83b" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_d-1.0.0-py3-none-any.whl", hash = "sha256:f34e37e7164316c9b9ed3022d1ff378b3dcd895db6e339894f53d2b27a5d6ba0" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_foo-2.0.0-py3-none-any.whl", hash = "sha256:8a757092c63519d20d312dacf83ed3c9cc8156495279305a2249175e0407e4df" }, ] [[package]] - name = "package-foo" + name = "package-unrelated-dep" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform == 'linux'", + "os_name == 'posix' and sys_platform == 'linux'", + "os_name != 'posix' and sys_platform == 'linux'", ] - dependencies = [ - { name = "package-c", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, - { name = "package-reject-cleaver-1", marker = "sys_platform == 'linux'" }, - ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_foo-1.0.0.tar.gz", hash = "sha256:7c1a2ca51dd2156cf36c3400e38595e11b09442052f4bd1d6b3d53eb5b2acf32" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep-1.0.0.tar.gz", hash = "sha256:21270ed2d2b5ba9944dad6157fd877221b9955a6bbcb6b4e87f72c17c3686123" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_foo-1.0.0-py3-none-any.whl", hash = "sha256:524dfd846c31a55bb6d6a0d0cec80d42c0a87c78aabbe0f1d5426c60493bd41b" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep-1.0.0-py3-none-any.whl", hash = "sha256:307363dcac36c5330299be9f22e2caf6bbf54d0391f6381aec98052f1baa65f0" }, ] [[package]] - name = "package-foo" + name = "package-unrelated-dep" version = "2.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform != 'linux'", - ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_foo-2.0.0.tar.gz", hash = "sha256:1607aa970fac2e237de28636bf53b022b0c391ecc9039e34438638c8743cc83b" } - wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_foo-2.0.0-py3-none-any.whl", hash = "sha256:8a757092c63519d20d312dacf83ed3c9cc8156495279305a2249175e0407e4df" }, - ] - - [[package]] - name = "package-reject-cleaver-1" - version = "1.0.0" - source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } - dependencies = [ - { name = "package-unrelated-dep2", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, - { name = "package-unrelated-dep2", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, + "os_name == 'posix' and sys_platform != 'linux'", + "os_name != 'posix' and sys_platform != 'linux'", ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_reject_cleaver_1-1.0.0.tar.gz", hash = "sha256:6ef93ca22db3a054559cb34f574ffa3789951f2f82b213c5502d0e9ff746f15e" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep-2.0.0.tar.gz", hash = "sha256:5e90298d1d9462f3927a6bdeac0ac934a7d38d6760e7a24f674cc0d97ace41bc" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_reject_cleaver_1-1.0.0-py3-none-any.whl", hash = "sha256:b5e5203994245c2b983dd94595281a03ac38c05e14f0a8792d13763f69aa43a8" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep-2.0.0-py3-none-any.whl", hash = "sha256:7ec01ec088471561ab47c534a19d8bcde2bb03a8dce0bc28c886338352f68936" }, ] [[package]] - name = "package-unrelated-dep2" + name = "package-unrelated-dep3" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform == 'linux'", + "os_name == 'posix' and sys_platform == 'linux'", + "os_name == 'posix' and sys_platform != 'linux'", ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep2-1.0.0.tar.gz", hash = "sha256:bbeb0f558aff8c48bac6fdab42ed52f49d68d2b51a7de82ff9357925a6e5023a" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep3-1.0.0.tar.gz", hash = "sha256:b7a24b9773384d8d59a786f021c567a867134c547a5688fd8eb129823e2aeb68" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep2-1.0.0-py3-none-any.whl", hash = "sha256:b36bc1e6f0140fdbf03575eb6bb0873c298b1d44dd7955412909ba9c2650a250" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep3-1.0.0-py3-none-any.whl", hash = "sha256:d5d1b57d779d446300918c785b1575a3874ed3d0667c27e7a864739249da51cd" }, ] [[package]] - name = "package-unrelated-dep2" + name = "package-unrelated-dep3" version = "2.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } environment-markers = [ - "sys_platform != 'linux'", + "os_name != 'posix' and sys_platform == 'linux'", + "os_name != 'posix' and sys_platform != 'linux'", ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep2-2.0.0.tar.gz", hash = "sha256:ac23c6208b6340b2542e730e1df770ed4ca65f234de86d2216add6c2b975f95c" } + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep3-2.0.0.tar.gz", hash = "sha256:20fd10d8e4fcba803b73c57c06348c420bb09d80e09ac94e42d906c3cbbf455e" } wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep2-2.0.0-py3-none-any.whl", hash = "sha256:5fc6d9c0fee066b33df862f31057c8cc2c0c5662ef9949337407e0131aa46e7f" }, + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_tristable_unrelated_dep3-2.0.0-py3-none-any.whl", hash = "sha256:4b4902f83343585e5da3e517051dd0ab09a3493dec653878a512bf4a038601e2" }, ] [[package]] @@ -3563,8 +3561,7 @@ fn preferences_dependent_forking_tristable() -> Result<()> { dependencies = [ { name = "package-bar" }, { name = "package-cleaver" }, - { name = "package-foo", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, - { name = "package-foo", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, + { name = "package-foo" }, ] "### ); @@ -3718,6 +3715,19 @@ fn preferences_dependent_forking() -> Result<()> { { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bar-1.0.0-py3-none-any.whl", hash = "sha256:3cdaac4b0ba330f902d0628c0b1d6e62692f52255d02718d04f46ade7c8ad6a6" }, ] + [[package]] + name = "package-bar" + version = "2.0.0" + source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } + environment-markers = [ + "sys_platform == 'linux'", + ] + sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bar-2.0.0.tar.gz", hash = "sha256:f440dbb8c3b848be467c9d3cd4970963fae3144de12454fd48fe9077eb76e9ea" } + wheels = [ + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_bar-2.0.0-py3-none-any.whl", hash = "sha256:24fd0534fec4053f4cac960244943ef13d1bad26bbb5fffe6944a8cf898f26f0" }, + ] + + [[package]] name = "package-cleaver" version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } @@ -3739,18 +3749,6 @@ fn preferences_dependent_forking() -> Result<()> { { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_foo-1.0.0-py3-none-any.whl", hash = "sha256:85348e8df4892b9f297560c16abcf231828f538dc07339ed121197a00a0626a5" }, ] - [[package]] - name = "package-foo" - version = "2.0.0" - source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } - environment-markers = [ - "sys_platform != 'linux'", - ] - sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_foo-2.0.0.tar.gz", hash = "sha256:ad54d14a4fd931b8ccb6412edef71fe223c36362d0ccfe3fa251c17d4f07e4a9" } - wheels = [ - { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/preferences_dependent_forking_foo-2.0.0-py3-none-any.whl", hash = "sha256:bae278cf259c0e031e52b6cbb537d945e0e606d045e980b90d406d0f1e06aae9" }, - ] - [[package]] name = "project" version = "0.1.0" @@ -4187,6 +4185,10 @@ fn fork_requires_python_patch_overlap() -> Result<()> { lock, @r###" version = 1 requires-python = ">=3.10.1" + environment-markers = [ + "python_version != '3.10'", + "python_version == '3.10'", + ] [[package]] name = "package-a" diff --git a/crates/uv/tests/tree.rs b/crates/uv/tests/tree.rs index e2b440ec57f1..3d44f3fa848f 100644 --- a/crates/uv/tests/tree.rs +++ b/crates/uv/tests/tree.rs @@ -497,7 +497,7 @@ fn optional_dependencies() -> Result<()> { exit_code: 0 ----- stdout ----- project v0.1.0 - ├── flask[dotenv] v3.0.2 + ├── flask v3.0.2 │ ├── blinker v1.7.0 │ ├── click v8.1.7 │ │ └── colorama v0.4.6 @@ -507,10 +507,12 @@ fn optional_dependencies() -> Result<()> { │ ├── werkzeug v3.0.1 │ │ └── markupsafe v2.1.5 │ └── python-dotenv v1.0.1 (extra: dotenv) + ├── flask[dotenv] v3.0.2 (*) ├── iniconfig v2.0.0 └── anyio v4.3.0 (extra: async) ├── idna v3.6 └── sniffio v1.3.1 + (*) Package tree already displayed ----- stderr ----- warning: `uv tree` is experimental and may change without warning @@ -550,6 +552,7 @@ fn optional_dependencies_inverted() -> Result<()> { ----- stdout ----- blinker v1.7.0 └── flask v3.0.2 + ├── project v0.1.0 └── project[dotenv] v0.1.0 colorama v0.4.6 └── click v8.1.7 From 23832ff12cca62b48eac379eacb0c38419283b74 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 9 Aug 2024 14:27:33 -0400 Subject: [PATCH 11/11] uv/tests: WRONG test changes These changes all look wrong and would need to be resolved before merging. --- crates/uv/tests/lock.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index 7dfd3ea9e33a..8800531998b1 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -1442,13 +1442,14 @@ fn lock_dependency_extra() -> Result<()> { // Re-run with `--locked`. uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" - success: true - exit_code: 0 + success: false + exit_code: 2 ----- stdout ----- ----- stderr ----- warning: `uv lock` is experimental and may change without warning Resolved 10 packages in [TIME] + error: The lockfile at `uv.lock` needs to be updated, but `--locked` was provided. To update the lockfile, run `uv lock`. "###); // Install from the lockfile. @@ -1689,13 +1690,14 @@ fn lock_conditional_dependency_extra() -> Result<()> { // Re-run with `--locked`. uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" - success: true - exit_code: 0 + success: false + exit_code: 2 ----- stdout ----- ----- stderr ----- warning: `uv lock` is experimental and may change without warning Resolved 7 packages in [TIME] + error: The lockfile at `uv.lock` needs to be updated, but `--locked` was provided. To update the lockfile, run `uv lock`. "###); // Install from the lockfile. @@ -1724,13 +1726,14 @@ fn lock_conditional_dependency_extra() -> Result<()> { // Re-run with `--locked`. uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" - success: true - exit_code: 0 + success: false + exit_code: 2 ----- stdout ----- ----- stderr ----- warning: `uv lock` is experimental and may change without warning Resolved 7 packages in [TIME] + error: The lockfile at `uv.lock` needs to be updated, but `--locked` was provided. To update the lockfile, run `uv lock`. "###); // Install from the lockfile. @@ -1891,6 +1894,7 @@ fn lock_dependency_non_existent_extra() -> Result<()> { source = { editable = "." } dependencies = [ { name = "flask" }, + { name = "flask" }, ] [[package]]