mirror of
				https://github.com/astral-sh/uv.git
				synced 2025-10-31 20:09:09 +00:00 
			
		
		
		
	Normalize python_version markers to python_full_version (#6126)
				
					
				
			## Summary Normalize all `python_version` markers to their equivalent `python_full_version` form. This avoids false positives in forking because we currently cannot detect any relationships between the two forms. It also avoids subtle bugs due to the truncating semantics of `python_version`. For example, given `requires-python = ">3.12"`, we currently simplify the marker `python_version <= 3.12` to `false`. However, the version `3.12.1` will be truncated to `3.12` for `python_version` comparisons, and thus it satisfies the python requirement and evaluates to `true`. It is possible to simplify back to `python_version` when writing markers to the lockfile. However, the equivalent `python_full_version` markers are often clearer and easier to simplify, so I lean towards leaving them as `python_full_version`. There are *a lot* of snapshot updates from this change. I'd like more eyes on the transformation logic in `python_version_to_full_version` to ensure that they are all correct. Resolves https://github.com/astral-sh/uv/issues/6125.
This commit is contained in:
		
							parent
							
								
									1311127991
								
							
						
					
					
						commit
						e6ddce0246
					
				
					 22 changed files with 1021 additions and 844 deletions
				
			
		|  | @ -119,6 +119,11 @@ impl Operator { | |||
|             _ => None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns `true` if this operator represents a wildcard.
 | ||||
|     pub fn is_star(self) -> bool { | ||||
|         matches!(self, Self::EqualStar | Self::NotEqualStar) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromStr for Operator { | ||||
|  |  | |||
|  | @ -416,6 +416,23 @@ impl VersionSpecifier { | |||
|             version, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// `==<version>.*`
 | ||||
|     pub fn equals_star_version(version: Version) -> Self { | ||||
|         Self { | ||||
|             operator: Operator::EqualStar, | ||||
|             version, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// `!=<version>.*`
 | ||||
|     pub fn not_equals_star_version(version: Version) -> Self { | ||||
|         Self { | ||||
|             operator: Operator::NotEqualStar, | ||||
|             version, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// `!=<version>`
 | ||||
|     pub fn not_equals_version(version: Version) -> Self { | ||||
|         Self { | ||||
|  | @ -465,19 +482,36 @@ impl VersionSpecifier { | |||
|         &self.version | ||||
|     } | ||||
| 
 | ||||
|     /// Get the operator and version parts of this specifier.
 | ||||
|     pub fn into_parts(self) -> (Operator, Version) { | ||||
|         (self.operator, self.version) | ||||
|     } | ||||
| 
 | ||||
|     /// Whether the version marker includes a prerelease.
 | ||||
|     pub fn any_prerelease(&self) -> bool { | ||||
|         self.version.any_prerelease() | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the version specifiers whose union represents the given range.
 | ||||
|     pub fn from_bounds( | ||||
|     ///
 | ||||
|     /// This function is not applicable to ranges involving pre-release versions.
 | ||||
|     pub fn from_release_only_bounds( | ||||
|         bounds: (&Bound<Version>, &Bound<Version>), | ||||
|     ) -> impl Iterator<Item = VersionSpecifier> { | ||||
|         let (b1, b2) = match bounds { | ||||
|             (Bound::Included(v1), Bound::Included(v2)) if v1 == v2 => { | ||||
|                 (Some(VersionSpecifier::equals_version(v1.clone())), None) | ||||
|             } | ||||
|             // `v >= 3.7 && v < 3.8` is equivalent to `v == 3.7.*`
 | ||||
|             (Bound::Included(v1), Bound::Excluded(v2)) | ||||
|                 if v1.release().len() == 2 | ||||
|                     && v2.release() == [v1.release()[0], v1.release()[1] + 1] => | ||||
|             { | ||||
|                 ( | ||||
|                     Some(VersionSpecifier::equals_star_version(v1.clone())), | ||||
|                     None, | ||||
|                 ) | ||||
|             } | ||||
|             (lower, upper) => ( | ||||
|                 VersionSpecifier::from_lower_bound(lower), | ||||
|                 VersionSpecifier::from_upper_bound(upper), | ||||
|  |  | |||
|  | @ -1172,7 +1172,7 @@ mod tests { | |||
| 
 | ||||
|     #[test] | ||||
|     fn basic_examples() { | ||||
|         let input = r"requests[security,tests]>=2.8.1,==2.8.* ; python_version < '2.7'"; | ||||
|         let input = r"requests[security,tests]>=2.8.1,==2.8.* ; python_full_version < '2.7'"; | ||||
|         let requests = Requirement::<Url>::from_str(input).unwrap(); | ||||
|         assert_eq!(input, requests.to_string()); | ||||
|         let expected = Requirement { | ||||
|  | @ -1198,7 +1198,7 @@ mod tests { | |||
|                 .collect(), | ||||
|             )), | ||||
|             marker: MarkerTree::expression(MarkerExpression::Version { | ||||
|                 key: MarkerValueVersion::PythonVersion, | ||||
|                 key: MarkerValueVersion::PythonFullVersion, | ||||
|                 specifier: VersionSpecifier::from_pattern( | ||||
|                     pep440_rs::Operator::LessThan, | ||||
|                     "2.7".parse().unwrap(), | ||||
|  | @ -1788,10 +1788,16 @@ mod tests { | |||
|     #[test] | ||||
|     fn no_space_after_operator() { | ||||
|         let requirement = Requirement::<Url>::from_str("pytest;python_version<='4.0'").unwrap(); | ||||
|         assert_eq!(requirement.to_string(), "pytest ; python_version <= '4.0'"); | ||||
|         assert_eq!( | ||||
|             requirement.to_string(), | ||||
|             "pytest ; python_full_version < '4.1'" | ||||
|         ); | ||||
| 
 | ||||
|         let requirement = Requirement::<Url>::from_str("pytest;'4.0'>=python_version").unwrap(); | ||||
|         assert_eq!(requirement.to_string(), "pytest ; python_version <= '4.0'"); | ||||
|         assert_eq!( | ||||
|             requirement.to_string(), | ||||
|             "pytest ; python_full_version < '4.1'" | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|  |  | |||
|  | @ -51,6 +51,7 @@ use std::sync::Mutex; | |||
| use std::sync::MutexGuard; | ||||
| 
 | ||||
| use itertools::Either; | ||||
| use pep440_rs::Operator; | ||||
| use pep440_rs::{Version, VersionSpecifier}; | ||||
| use pubgrub::Range; | ||||
| use rustc_hash::FxHashMap; | ||||
|  | @ -156,10 +157,21 @@ impl InternerGuard<'_> { | |||
|     /// Returns a decision node for a single marker expression.
 | ||||
|     pub(crate) fn expression(&mut self, expr: MarkerExpression) -> NodeId { | ||||
|         let (var, children) = match expr { | ||||
|             // Normalize `python_version` markers to `python_full_version` nodes.
 | ||||
|             MarkerExpression::Version { | ||||
|                 key: MarkerValueVersion::PythonVersion, | ||||
|                 specifier, | ||||
|             } => match python_version_to_full_version(normalize_specifier(specifier)) { | ||||
|                 Ok(specifier) => ( | ||||
|                     Variable::Version(MarkerValueVersion::PythonFullVersion), | ||||
|                     Edges::from_specifier(specifier), | ||||
|                 ), | ||||
|                 Err(node) => return node, | ||||
|             }, | ||||
|             // A variable representing the output of a version key. Edges correspond
 | ||||
|             // to disjoint version ranges.
 | ||||
|             MarkerExpression::Version { key, specifier } => { | ||||
|                 (Variable::Version(key), Edges::from_specifier(&specifier)) | ||||
|                 (Variable::Version(key), Edges::from_specifier(specifier)) | ||||
|             } | ||||
|             // The `in` and `contains` operators are a bit different than other operators.
 | ||||
|             // In particular, they do not represent a particular value for the corresponding
 | ||||
|  | @ -532,18 +544,9 @@ impl Edges { | |||
|     } | ||||
| 
 | ||||
|     /// Returns the [`Edges`] for a version specifier.
 | ||||
|     fn from_specifier(specifier: &VersionSpecifier) -> Edges { | ||||
|         // The decision diagram relies on the assumption that the negation of a marker tree is
 | ||||
|         // the complement of the marker space. However, pre-release versions violate this assumption.
 | ||||
|         // For example, the marker `python_full_version > '3.9' or python_full_version <= '3.9'`
 | ||||
|         // does not match `python_full_version == 3.9.0a0`. However, it's negation,
 | ||||
|         // `python_full_version > '3.9' and python_full_version <= '3.9'` also does not include
 | ||||
|         // `3.9.0a0`, and is actually `false`.
 | ||||
|         //
 | ||||
|         // For this reason we ignore pre-release versions entirely when evaluating markers.
 | ||||
|         // Note that `python_version` cannot take on pre-release values so this is necessary for
 | ||||
|         // simplifying ranges, but for `python_full_version` this decision is a semantic change.
 | ||||
|         let specifier = PubGrubSpecifier::from_release_specifier(specifier).unwrap(); | ||||
|     fn from_specifier(specifier: VersionSpecifier) -> Edges { | ||||
|         let specifier = | ||||
|             PubGrubSpecifier::from_release_specifier(&normalize_specifier(specifier)).unwrap(); | ||||
|         Edges::Version { | ||||
|             edges: Edges::from_range(&specifier.into()), | ||||
|         } | ||||
|  | @ -748,6 +751,110 @@ impl Edges { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| // Normalize a [`VersionSpecifier`] before adding it to the tree.
 | ||||
| fn normalize_specifier(specifier: VersionSpecifier) -> VersionSpecifier { | ||||
|     let (operator, version) = specifier.into_parts(); | ||||
| 
 | ||||
|     // The decision diagram relies on the assumption that the negation of a marker tree is
 | ||||
|     // the complement of the marker space. However, pre-release versions violate this assumption.
 | ||||
|     // For example, the marker `python_full_version > '3.9' or python_full_version <= '3.9'`
 | ||||
|     // does not match `python_full_version == 3.9.0a0`. However, it's negation,
 | ||||
|     // `python_full_version > '3.9' and python_full_version <= '3.9'` also does not include
 | ||||
|     // `3.9.0a0`, and is actually `false`.
 | ||||
|     //
 | ||||
|     // For this reason we ignore pre-release versions entirely when evaluating markers.
 | ||||
|     // Note that `python_version` cannot take on pre-release values so this is necessary for
 | ||||
|     // simplifying ranges, but for `python_full_version` this decision is a semantic change.
 | ||||
|     let mut release = version.release(); | ||||
| 
 | ||||
|     // Strip any trailing `0`s.
 | ||||
|     //
 | ||||
|     // The [`Version`] type ignores trailing `0`s for equality, but still preserves them in it's
 | ||||
|     // [`Display`] output. We must normalize all versions by stripping trailing `0`s to remove the
 | ||||
|     // distinction between versions like `3.9` and `3.9.0`, whose output will depend on which form
 | ||||
|     // was added to the global marker interner first.
 | ||||
|     //
 | ||||
|     // Note that we cannot strip trailing `0`s for star equality, as `==3.0.*` is different from `==3.*`.
 | ||||
|     if !operator.is_star() { | ||||
|         if let Some(end) = release.iter().rposition(|segment| *segment != 0) { | ||||
|             if end > 0 { | ||||
|                 release = &release[..=end]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     VersionSpecifier::from_version(operator, Version::new(release)).unwrap() | ||||
| } | ||||
| 
 | ||||
| /// Returns the equivalent `python_full_version` specifier for a `python_version` comparison.
 | ||||
| ///
 | ||||
| /// Returns `Err` with a constant node if the equivalent comparison is always `true` or `false`.
 | ||||
| fn python_version_to_full_version(specifier: VersionSpecifier) -> Result<VersionSpecifier, NodeId> { | ||||
|     let major_minor = match *specifier.version().release() { | ||||
|         // `python_version == 3.*` is equivalent to `python_full_version == 3.*`
 | ||||
|         // and adding a trailing `0` would be incorrect.
 | ||||
|         [_major] if specifier.operator().is_star() => return Ok(specifier), | ||||
|         // Note that `python_version == 3` matches `3.0.1`, `3.0.2`, etc.
 | ||||
|         [major] => Some((major, 0)), | ||||
|         [major, minor] => Some((major, minor)), | ||||
|         _ => None, | ||||
|     }; | ||||
| 
 | ||||
|     if let Some((major, minor)) = major_minor { | ||||
|         let version = Version::new([major, minor]); | ||||
| 
 | ||||
|         Ok(match specifier.operator() { | ||||
|             // `python_version == 3.7` is equivalent to `python_full_version == 3.7.*`.
 | ||||
|             Operator::Equal | Operator::ExactEqual => { | ||||
|                 VersionSpecifier::equals_star_version(version) | ||||
|             } | ||||
|             // `python_version != 3.7` is equivalent to `python_full_version != 3.7.*`.
 | ||||
|             Operator::NotEqual => VersionSpecifier::not_equals_star_version(version), | ||||
| 
 | ||||
|             // `python_version > 3.7` is equivalent to `python_full_version >= 3.8`.
 | ||||
|             Operator::GreaterThan => { | ||||
|                 VersionSpecifier::greater_than_equal_version(Version::new([major, minor + 1])) | ||||
|             } | ||||
|             // `python_version < 3.7` is equivalent to `python_full_version < 3.7`.
 | ||||
|             Operator::LessThan => specifier, | ||||
|             // `python_version >= 3.7` is equivalent to `python_full_version >= 3.7`.
 | ||||
|             Operator::GreaterThanEqual => specifier, | ||||
|             // `python_version <= 3.7` is equivalent to `python_full_version < 3.8`.
 | ||||
|             Operator::LessThanEqual => { | ||||
|                 VersionSpecifier::less_than_version(Version::new([major, minor + 1])) | ||||
|             } | ||||
| 
 | ||||
|             // `==3.7.*`, `!=3.7.*`, `~=3.7` already represent the equivalent `python_full_version`
 | ||||
|             // comparison.
 | ||||
|             Operator::EqualStar | Operator::NotEqualStar | Operator::TildeEqual => specifier, | ||||
|         }) | ||||
|     } else { | ||||
|         let &[major, minor, ..] = specifier.version().release() else { | ||||
|             unreachable!() | ||||
|         }; | ||||
| 
 | ||||
|         Ok(match specifier.operator() { | ||||
|             // `python_version` cannot have more than two release segments, so equality is impossible.
 | ||||
|             Operator::Equal | Operator::ExactEqual | Operator::EqualStar | Operator::TildeEqual => { | ||||
|                 return Err(NodeId::FALSE) | ||||
|             } | ||||
| 
 | ||||
|             // Similarly, inequalities are always `true`.
 | ||||
|             Operator::NotEqual | Operator::NotEqualStar => return Err(NodeId::TRUE), | ||||
| 
 | ||||
|             // `python_version {<,<=} 3.7.8` is equivalent to `python_full_version < 3.8`.
 | ||||
|             Operator::LessThan | Operator::LessThanEqual => { | ||||
|                 VersionSpecifier::less_than_version(Version::new([major, minor + 1])) | ||||
|             } | ||||
| 
 | ||||
|             // `python_version {>,>=} 3.7.8` is equivalent to `python_full_version >= 3.8`.
 | ||||
|             Operator::GreaterThan | Operator::GreaterThanEqual => { | ||||
|                 VersionSpecifier::greater_than_equal_version(Version::new([major, minor + 1])) | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Compares the start of two ranges that are known to be disjoint.
 | ||||
| fn compare_disjoint_range_start<T>(range1: &Range<T>, range2: &Range<T>) -> Ordering | ||||
| where | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ use std::ops::Bound; | |||
| 
 | ||||
| use indexmap::IndexMap; | ||||
| use itertools::Itertools; | ||||
| use pep440_rs::VersionSpecifier; | ||||
| use pep440_rs::{Version, VersionSpecifier}; | ||||
| use pubgrub::Range; | ||||
| use rustc_hash::FxBuildHasher; | ||||
| 
 | ||||
|  | @ -61,9 +61,21 @@ fn collect_dnf( | |||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 // Detect whether the range for this edge can be simplified as a star inequality.
 | ||||
|                 if let Some(specifier) = star_range_inequality(&range) { | ||||
|                     path.push(MarkerExpression::Version { | ||||
|                         key: marker.key().clone(), | ||||
|                         specifier, | ||||
|                     }); | ||||
| 
 | ||||
|                     collect_dnf(&tree, dnf, path); | ||||
|                     path.pop(); | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 for bounds in range.iter() { | ||||
|                     let current = path.len(); | ||||
|                     for specifier in VersionSpecifier::from_bounds(bounds) { | ||||
|                     for specifier in VersionSpecifier::from_release_only_bounds(bounds) { | ||||
|                         path.push(MarkerExpression::Version { | ||||
|                             key: marker.key().clone(), | ||||
|                             specifier, | ||||
|  | @ -307,7 +319,7 @@ where | |||
| /// Returns `Some` if the expression can be simplified as an inequality consisting
 | ||||
| /// of the given values.
 | ||||
| ///
 | ||||
| /// For example, `os_name < 'Linux'` and `os_name > 'Linux'` can be simplified to
 | ||||
| /// For example, `os_name < 'Linux' or os_name > 'Linux'` can be simplified to
 | ||||
| /// `os_name != 'Linux'`.
 | ||||
| fn range_inequality<T>(range: &Range<T>) -> Option<Vec<&T>> | ||||
| where | ||||
|  | @ -328,6 +340,25 @@ where | |||
|     Some(excluded) | ||||
| } | ||||
| 
 | ||||
| /// Returns `Some` if the version expression can be simplified as a star inequality with the given
 | ||||
| /// specifier.
 | ||||
| ///
 | ||||
| /// For example, `python_full_version < '3.8' or python_full_version >= '3.9'` can be simplified to
 | ||||
| /// `python_full_version != '3.8.*'`.
 | ||||
| fn star_range_inequality(range: &Range<Version>) -> Option<VersionSpecifier> { | ||||
|     let (b1, b2) = range.iter().collect_tuple()?; | ||||
| 
 | ||||
|     match (b1, b2) { | ||||
|         ((Bound::Unbounded, Bound::Excluded(v1)), (Bound::Included(v2), Bound::Unbounded)) | ||||
|             if v1.release().len() == 2 | ||||
|                 && v2.release() == [v1.release()[0], v1.release()[1] + 1] => | ||||
|         { | ||||
|             Some(VersionSpecifier::not_equals_star_version(v1.clone())) | ||||
|         } | ||||
|         _ => None, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Returns `true` if the LHS is the negation of the RHS, or vice versa.
 | ||||
| fn is_negation(left: &MarkerExpression, right: &MarkerExpression) -> bool { | ||||
|     match left { | ||||
|  |  | |||
|  | @ -1067,15 +1067,11 @@ impl MarkerTree { | |||
|     /// the marker will be simplified to `sys_platform == 'linux'`.
 | ||||
|     #[must_use] | ||||
|     #[allow(clippy::needless_pass_by_value)] | ||||
|     pub fn simplify_python_versions( | ||||
|         self, | ||||
|         python_version: Range<Version>, | ||||
|         full_python_version: Range<Version>, | ||||
|     ) -> MarkerTree { | ||||
|     pub fn simplify_python_versions(self, python_version: Range<Version>) -> MarkerTree { | ||||
|         MarkerTree(INTERNER.lock().restrict_versions(self.0, &|var| match var { | ||||
|             Variable::Version(MarkerValueVersion::PythonVersion) => Some(python_version.clone()), | ||||
|             // Note that `python_version` is normalized to `python_full_version`.
 | ||||
|             Variable::Version(MarkerValueVersion::PythonFullVersion) => { | ||||
|                 Some(full_python_version.clone()) | ||||
|                 Some(python_version.clone()) | ||||
|             } | ||||
|             _ => None, | ||||
|         })) | ||||
|  | @ -1452,62 +1448,49 @@ mod test { | |||
| 
 | ||||
|         assert_eq!( | ||||
|             m("(python_version <= '3.11' and sys_platform == 'win32') or python_version > '3.11'") | ||||
|                 .simplify_python_versions( | ||||
|                     Range::from_range_bounds(( | ||||
|                         Bound::Excluded(Version::new([3, 12])), | ||||
|                         Bound::Unbounded, | ||||
|                     )), | ||||
|                     Range::from_range_bounds(( | ||||
|                         Bound::Excluded(Version::new([3, 12])), | ||||
|                         Bound::Unbounded, | ||||
|                     )), | ||||
|                 ), | ||||
|                 .simplify_python_versions(Range::from_range_bounds(( | ||||
|                     Bound::Excluded(Version::new([3, 12])), | ||||
|                     Bound::Unbounded, | ||||
|                 ))), | ||||
|             MarkerTree::TRUE | ||||
|         ); | ||||
| 
 | ||||
|         assert_eq!( | ||||
|             m("python_version < '3.10'") | ||||
|                 .simplify_python_versions( | ||||
|                     Range::from_range_bounds(( | ||||
|                         Bound::Excluded(Version::new([3, 7])), | ||||
|                         Bound::Unbounded, | ||||
|                     )), | ||||
|                     Range::from_range_bounds(( | ||||
|                         Bound::Excluded(Version::new([3, 7])), | ||||
|                         Bound::Unbounded, | ||||
|                     )), | ||||
|                 ) | ||||
|                 .simplify_python_versions(Range::from_range_bounds(( | ||||
|                     Bound::Excluded(Version::new([3, 7])), | ||||
|                     Bound::Unbounded, | ||||
|                 ))) | ||||
|                 .try_to_string() | ||||
|                 .unwrap(), | ||||
|             "python_version < '3.10'" | ||||
|             "python_full_version < '3.10'" | ||||
|         ); | ||||
| 
 | ||||
|         // Note that `3.12.1` will still match.
 | ||||
|         assert_eq!( | ||||
|             m("python_version <= '3.12'") | ||||
|                 .simplify_python_versions(Range::from_range_bounds(( | ||||
|                     Bound::Excluded(Version::new([3, 12])), | ||||
|                     Bound::Unbounded, | ||||
|                 ))) | ||||
|                 .try_to_string() | ||||
|                 .unwrap(), | ||||
|             "python_full_version < '3.13'" | ||||
|         ); | ||||
| 
 | ||||
|         assert_eq!( | ||||
|             m("python_version <= '3.12'").simplify_python_versions( | ||||
|                 Range::from_range_bounds(( | ||||
|                     Bound::Excluded(Version::new([3, 12])), | ||||
|                     Bound::Unbounded, | ||||
|                 )), | ||||
|                 Range::from_range_bounds(( | ||||
|                     Bound::Excluded(Version::new([3, 12])), | ||||
|                     Bound::Unbounded, | ||||
|                 )), | ||||
|             ), | ||||
|             m("python_full_version <= '3.12'").simplify_python_versions(Range::from_range_bounds( | ||||
|                 (Bound::Excluded(Version::new([3, 12])), Bound::Unbounded,) | ||||
|             )), | ||||
|             MarkerTree::FALSE | ||||
|         ); | ||||
| 
 | ||||
|         assert_eq!( | ||||
|             m("python_full_version <= '3.12.1'") | ||||
|                 .simplify_python_versions( | ||||
|                     Range::from_range_bounds(( | ||||
|                         Bound::Excluded(Version::new([3, 12])), | ||||
|                         Bound::Unbounded, | ||||
|                     )), | ||||
|                     Range::from_range_bounds(( | ||||
|                         Bound::Excluded(Version::new([3, 12])), | ||||
|                         Bound::Unbounded, | ||||
|                     )), | ||||
|                 ) | ||||
|                 .simplify_python_versions(Range::from_range_bounds(( | ||||
|                     Bound::Excluded(Version::new([3, 12])), | ||||
|                     Bound::Unbounded, | ||||
|                 ))) | ||||
|                 .try_to_string() | ||||
|                 .unwrap(), | ||||
|             "python_full_version <= '3.12.1'" | ||||
|  | @ -1727,7 +1710,7 @@ mod test { | |||
|             .contents() | ||||
|             .unwrap() | ||||
|             .to_string(), | ||||
|             "python_full_version >= '3.7' and python_version <= '3.7' and 'nt' in os_name", | ||||
|             "python_full_version == '3.7.*' and 'nt' in os_name", | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|  | @ -1820,60 +1803,75 @@ mod test { | |||
| 
 | ||||
|     #[test] | ||||
|     fn test_marker_simplification() { | ||||
|         assert_simplifies("python_version == '3.9'", "python_full_version == '3.9.*'"); | ||||
|         assert_simplifies( | ||||
|             "python_version == '3.9' or python_version == '3.9'", | ||||
|             "python_version == '3.9'", | ||||
|             "python_version == '3.9.0'", | ||||
|             "python_full_version == '3.9.*'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies("python_version != '3.9'", "python_full_version != '3.9.*'"); | ||||
| 
 | ||||
|         assert_simplifies("python_version >= '3.9.0'", "python_full_version >= '3.9'"); | ||||
|         assert_simplifies("python_version <= '3.9.0'", "python_full_version < '3.10'"); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version == '3.*'", | ||||
|             "python_full_version >= '3' and python_full_version < '4'", | ||||
|         ); | ||||
|         assert_simplifies( | ||||
|             "python_version == '3.0.*'", | ||||
|             "python_full_version == '3.0.*'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version < '3.17' or python_version < '3.18'", | ||||
|             "python_version < '3.18'", | ||||
|             "python_full_version < '3.18'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version > '3.17' or python_version > '3.18' or python_version > '3.12'", | ||||
|             "python_version > '3.12'", | ||||
|             "python_full_version >= '3.13'", | ||||
|         ); | ||||
| 
 | ||||
|         // a quirk of how pubgrub works, but this is considered part of normalization
 | ||||
|         assert_simplifies( | ||||
|             "python_version > '3.17.post4' or python_version > '3.18.post4'", | ||||
|             "python_version > '3.17'", | ||||
|             "python_full_version >= '3.18'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version < '3.17' and python_version < '3.18'", | ||||
|             "python_version < '3.17'", | ||||
|             "python_full_version < '3.17'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version <= '3.18' and python_version == '3.18'", | ||||
|             "python_version == '3.18'", | ||||
|             "python_full_version == '3.18.*'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version <= '3.18' or python_version == '3.18'", | ||||
|             "python_version <= '3.18'", | ||||
|             "python_full_version < '3.19'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version <= '3.15' or (python_version <= '3.17' and python_version < '3.16')", | ||||
|             "python_version < '3.16'", | ||||
|             "python_full_version < '3.16'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "(python_version > '3.17' or python_version > '3.16') and python_version > '3.15'", | ||||
|             "python_version > '3.16'", | ||||
|             "python_full_version >= '3.17'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|              "(python_version > '3.17' or python_version > '3.16') and python_version > '3.15' and implementation_version == '1'", | ||||
|              "implementation_version == '1' and python_version > '3.16'", | ||||
|              "implementation_version == '1' and python_full_version >= '3.17'", | ||||
|          ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|              "('3.17' < python_version or '3.16' < python_version) and '3.15' < python_version and implementation_version == '1'", | ||||
|              "implementation_version == '1' and python_version > '3.16'", | ||||
|              "implementation_version == '1' and python_full_version >= '3.17'", | ||||
|          ); | ||||
| 
 | ||||
|         assert_simplifies("extra == 'a' or extra == 'a'", "extra == 'a'"); | ||||
|  | @ -1929,7 +1927,7 @@ mod test { | |||
|         // post-normalization filtering
 | ||||
|         assert_simplifies( | ||||
|              "(python_version < '3.1' or python_version < '3.2') and (python_version < '3.2' or python_version == '3.3')", | ||||
|              "python_version < '3.2'", | ||||
|              "python_full_version < '3.2'", | ||||
|          ); | ||||
| 
 | ||||
|         // normalize out redundant ranges
 | ||||
|  | @ -1949,17 +1947,17 @@ mod test { | |||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version != '3.10' or python_version > '3.12'", | ||||
|             "python_version != '3.10'", | ||||
|             "python_full_version != '3.10.*'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version != '3.8' and python_version < '3.10'", | ||||
|             "python_version < '3.8' or (python_version > '3.8' and python_version < '3.10')", | ||||
|             "python_full_version < '3.8' or python_full_version == '3.9.*'", | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "python_version != '3.8' and python_version != '3.9'", | ||||
|             "python_version != '3.8' and python_version != '3.9'", | ||||
|             "python_full_version < '3.8' or python_full_version >= '3.10'", | ||||
|         ); | ||||
| 
 | ||||
|         // normalize out redundant expressions
 | ||||
|  | @ -2089,20 +2087,22 @@ mod test { | |||
|             "(os_name != 'Linux' and sys_platform == 'x') or (platform_system != 'win32' and sys_platform == 'x') or (os_name == 'Linux' and platform_system == 'win32')" | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies("python_version > '3.7'", "python_version > '3.7'"); | ||||
|         assert_simplifies("python_version > '3.7'", "python_full_version >= '3.8'"); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|             "(python_version <= '3.7' and os_name == 'Linux') or python_version > '3.7'", | ||||
|             "os_name == 'Linux' or python_version > '3.7'", | ||||
|             "os_name == 'Linux' or python_full_version >= '3.8'", | ||||
|         ); | ||||
| 
 | ||||
|         // Again, the extra `<3.7` and `>=3.9` expressions cannot be seen as redundant due to them being interdependent.
 | ||||
|         // TODO(ibraheem): We might be able to simplify these by checking for the negation of the combined ranges before we split them.
 | ||||
|         assert_simplifies( | ||||
|             "(os_name == 'Linux' and sys_platform == 'win32') \ | ||||
|                 or (os_name != 'Linux' and sys_platform == 'win32' and python_version == '3.7') \ | ||||
|                 or (os_name != 'Linux' and sys_platform == 'win32' and python_version == '3.8')",
 | ||||
|             "(os_name == 'Linux' and sys_platform == 'win32') \ | ||||
|                 or (python_version == '3.7' and sys_platform == 'win32') \ | ||||
|                 or (python_version == '3.8' and sys_platform == 'win32')",
 | ||||
|             "(python_full_version < '3.7' and os_name == 'Linux' and sys_platform == 'win32') \ | ||||
|                 or (python_full_version >= '3.9' and os_name == 'Linux' and sys_platform == 'win32') \ | ||||
|                 or (python_full_version >= '3.7' and python_full_version < '3.9' and sys_platform == 'win32')" | ||||
|         ); | ||||
| 
 | ||||
|         assert_simplifies( | ||||
|  | @ -2139,10 +2139,10 @@ mod test { | |||
|     #[test] | ||||
|     fn test_requires_python() { | ||||
|         fn simplified(marker: &str) -> MarkerTree { | ||||
|             m(marker).simplify_python_versions( | ||||
|                 Range::from_range_bounds((Bound::Included(Version::new([3, 8])), Bound::Unbounded)), | ||||
|                 Range::from_range_bounds((Bound::Included(Version::new([3, 8])), Bound::Unbounded)), | ||||
|             ) | ||||
|             m(marker).simplify_python_versions(Range::from_range_bounds(( | ||||
|                 Bound::Included(Version::new([3, 8])), | ||||
|                 Bound::Unbounded, | ||||
|             ))) | ||||
|         } | ||||
| 
 | ||||
|         assert_eq!(simplified("python_version >= '3.8'"), MarkerTree::TRUE); | ||||
|  | @ -2160,14 +2160,14 @@ mod test { | |||
|             simplified("python_version == '3.8'") | ||||
|                 .try_to_string() | ||||
|                 .unwrap(), | ||||
|             "python_version == '3.8'" | ||||
|             "python_full_version < '3.9'" | ||||
|         ); | ||||
| 
 | ||||
|         assert_eq!( | ||||
|             simplified("python_version <= '3.10'") | ||||
|                 .try_to_string() | ||||
|                 .unwrap(), | ||||
|             "python_version <= '3.10'" | ||||
|             "python_full_version < '3.11'" | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|  | @ -2190,7 +2190,7 @@ mod test { | |||
|         // is always `true` and not disjoint.
 | ||||
|         assert!(!is_disjoint( | ||||
|             "python_version == 'Linux'", | ||||
|             "python_version == '3.7.1'" | ||||
|             "python_full_version == '3.7.1'" | ||||
|         )); | ||||
|     } | ||||
| 
 | ||||
|  | @ -2198,14 +2198,14 @@ mod test { | |||
|     fn test_version_disjointness() { | ||||
|         assert!(!is_disjoint( | ||||
|             "os_name == 'Linux'", | ||||
|             "python_version == '3.7.1'" | ||||
|             "python_full_version == '3.7.1'" | ||||
|         )); | ||||
| 
 | ||||
|         test_version_bounds_disjointness("python_version"); | ||||
|         test_version_bounds_disjointness("python_full_version"); | ||||
| 
 | ||||
|         assert!(!is_disjoint( | ||||
|             "python_version == '3.7.*'", | ||||
|             "python_version == '3.7.1'" | ||||
|             "python_full_version == '3.7.*'", | ||||
|             "python_full_version == '3.7.1'" | ||||
|         )); | ||||
|     } | ||||
| 
 | ||||
|  | @ -2217,7 +2217,7 @@ mod test { | |||
|         )); | ||||
|         assert!(!is_disjoint( | ||||
|             "implementation_version == '3.7.0'", | ||||
|             "python_version == '3.7.1'" | ||||
|             "python_full_version == '3.7.1'" | ||||
|         )); | ||||
| 
 | ||||
|         // basic version bounds checking should still work with lexicographical comparisons
 | ||||
|  | @ -2355,8 +2355,8 @@ mod test { | |||
|     } | ||||
| 
 | ||||
|     fn assert_simplifies(left: &str, right: &str) { | ||||
|         assert_eq!(m(left), m(right)); | ||||
|         assert_eq!(m(left).try_to_string().unwrap(), right); | ||||
|         assert_eq!(m(left), m(right), "{left} != {right}"); | ||||
|         assert_eq!(m(left).try_to_string().unwrap(), right, "{left} != {right}"); | ||||
|     } | ||||
| 
 | ||||
|     fn assert_true(marker: &str) { | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  | @ -54,7 +54,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  | @ -85,7 +85,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0' and platform_system == 'Windows', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0' and platform_system == 'Windows', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  | @ -116,7 +116,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  | @ -148,7 +148,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  | @ -54,7 +54,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  | @ -85,7 +85,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0' and platform_system == 'Windows', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0' and platform_system == 'Windows', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  | @ -116,7 +116,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  | @ -148,7 +148,7 @@ RequirementsTxt { | |||
|                             ), | ||||
|                         ), | ||||
|                     ), | ||||
|                     marker: python_version >= '3.8' and python_version < '4.0', | ||||
|                     marker: python_full_version >= '3.8' and python_full_version < '4.0', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/poetry-with-hashes.txt", | ||||
|  |  | |||
|  | @ -167,7 +167,7 @@ RequirementsTxt { | |||
|                             "dev", | ||||
|                         ), | ||||
|                     ], | ||||
|                     marker: python_version >= '3.9' and os_name == 'posix', | ||||
|                     marker: python_full_version >= '3.9' and os_name == 'posix', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/editable.txt", | ||||
|  | @ -224,7 +224,7 @@ RequirementsTxt { | |||
|                             "dev", | ||||
|                         ), | ||||
|                     ], | ||||
|                     marker: python_version >= '3.9' and os_name == 'posix', | ||||
|                     marker: python_full_version >= '3.9' and os_name == 'posix', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/editable.txt", | ||||
|  | @ -274,7 +274,7 @@ RequirementsTxt { | |||
|                         }, | ||||
|                     }, | ||||
|                     extras: [], | ||||
|                     marker: python_version >= '3.9' and os_name == 'posix', | ||||
|                     marker: python_full_version >= '3.9' and os_name == 'posix', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/editable.txt", | ||||
|  |  | |||
|  | @ -167,7 +167,7 @@ RequirementsTxt { | |||
|                             "dev", | ||||
|                         ), | ||||
|                     ], | ||||
|                     marker: python_version >= '3.9' and os_name == 'posix', | ||||
|                     marker: python_full_version >= '3.9' and os_name == 'posix', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/editable.txt", | ||||
|  | @ -224,7 +224,7 @@ RequirementsTxt { | |||
|                             "dev", | ||||
|                         ), | ||||
|                     ], | ||||
|                     marker: python_version >= '3.9' and os_name == 'posix', | ||||
|                     marker: python_full_version >= '3.9' and os_name == 'posix', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/editable.txt", | ||||
|  | @ -274,7 +274,7 @@ RequirementsTxt { | |||
|                         }, | ||||
|                     }, | ||||
|                     extras: [], | ||||
|                     marker: python_version >= '3.9' and os_name == 'posix', | ||||
|                     marker: python_full_version >= '3.9' and os_name == 'posix', | ||||
|                     origin: Some( | ||||
|                         File( | ||||
|                             "<REQUIREMENTS_DIR>/editable.txt", | ||||
|  |  | |||
|  | @ -97,7 +97,7 @@ impl RequiresPython { | |||
|         // Convert back to PEP 440 specifiers.
 | ||||
|         let specifiers = range | ||||
|             .iter() | ||||
|             .flat_map(VersionSpecifier::from_bounds) | ||||
|             .flat_map(VersionSpecifier::from_release_only_bounds) | ||||
|             .collect(); | ||||
| 
 | ||||
|         Ok(Some(Self { specifiers, bound })) | ||||
|  |  | |||
|  | @ -1515,7 +1515,6 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                 // supported by the root, skip it.
 | ||||
|                 let requirement = if let Some(requires_python) = python_requirement.target().and_then(|target| target.as_requires_python()).filter(|_| !requirement.marker.is_true()) { | ||||
|                     let marker = requirement.marker.clone().simplify_python_versions( | ||||
|                         Range::from(requires_python.bound_major_minor().clone()), | ||||
|                         Range::from(requires_python.bound().clone()), | ||||
|                     ); | ||||
| 
 | ||||
|  | @ -1582,7 +1581,6 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                             // supported by the root, skip it.
 | ||||
|                             let constraint = if let Some(requires_python) = python_requirement.target().and_then(|target| target.as_requires_python()).filter(|_| !constraint.marker.is_true()) { | ||||
|                                 let mut marker = constraint.marker.clone().simplify_python_versions( | ||||
|                                     Range::from(requires_python.bound_major_minor().clone()), | ||||
|                                     Range::from(requires_python.bound().clone()), | ||||
|                                 ); | ||||
|                                 marker.and(requirement.marker.clone()); | ||||
|  | @ -2888,10 +2886,7 @@ fn simplify_python(marker: MarkerTree, python_requirement: &PythonRequirement) - | |||
|         .target() | ||||
|         .and_then(|target| target.as_requires_python()) | ||||
|     { | ||||
|         marker.simplify_python_versions( | ||||
|             Range::from(requires_python.bound_major_minor().clone()), | ||||
|             Range::from(requires_python.bound().clone()), | ||||
|         ) | ||||
|         marker.simplify_python_versions(Range::from(requires_python.bound().clone())) | ||||
|     } else { | ||||
|         marker | ||||
|     } | ||||
|  |  | |||
|  | @ -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'`: | ||||
|     error: Requirements contain conflicting URLs for package `iniconfig` in split `python_full_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
 | ||||
|     "###
 | ||||
|  | @ -133,7 +133,7 @@ fn root_package_splits_but_transitive_conflict() -> Result<()> { | |||
|     ----- stdout ----- | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     error: Requirements contain conflicting URLs for package `iniconfig` in split `python_version < '3.12'`: | ||||
|     error: Requirements contain conflicting URLs for package `iniconfig` in split `python_full_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
 | ||||
|     "###
 | ||||
|  | @ -209,8 +209,8 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = 1 | ||||
|     requires-python = ">=3.11, <3.13" | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
| 
 | ||||
|     [options] | ||||
|  | @ -221,15 +221,15 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { editable = "." } | ||||
|     dependencies = [ | ||||
|         { name = "anyio", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '3.12'" }, | ||||
|         { name = "anyio", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_version >= '3.12'" }, | ||||
|         { name = "anyio", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, | ||||
|         { name = "anyio", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, | ||||
|         { name = "b" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|     requires-dist = [ | ||||
|         { name = "anyio", marker = "python_version < '3.12'", specifier = "==4.2.0" }, | ||||
|         { name = "anyio", marker = "python_version >= '3.12'", specifier = "==4.3.0" }, | ||||
|         { name = "anyio", marker = "python_full_version < '3.12'", specifier = "==4.2.0" }, | ||||
|         { name = "anyio", marker = "python_full_version >= '3.12'", specifier = "==4.3.0" }, | ||||
|         { name = "b", directory = "b" }, | ||||
|     ] | ||||
| 
 | ||||
|  | @ -238,11 +238,11 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = "4.2.0" | ||||
|     source = { registry = "https://pypi.org/simple" } | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|     ] | ||||
|     dependencies = [ | ||||
|         { name = "idna", marker = "python_version < '3.12'" }, | ||||
|         { name = "sniffio", marker = "python_version < '3.12'" }, | ||||
|         { name = "idna", marker = "python_full_version < '3.12'" }, | ||||
|         { name = "sniffio", marker = "python_full_version < '3.12'" }, | ||||
|     ] | ||||
|     sdist = { url = "https://files.pythonhosted.org/packages/2d/b8/7333d87d5f03247215d86a86362fd3e324111788c6cdd8d2e6196a6ba833/anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f", size = 158770 } | ||||
|     wheels = [ | ||||
|  | @ -254,11 +254,11 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = "4.3.0" | ||||
|     source = { registry = "https://pypi.org/simple" } | ||||
|     environment-markers = [ | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
|     dependencies = [ | ||||
|         { name = "idna", marker = "python_version >= '3.12'" }, | ||||
|         { name = "sniffio", marker = "python_version >= '3.12'" }, | ||||
|         { name = "idna", marker = "python_full_version >= '3.12'" }, | ||||
|         { name = "sniffio", marker = "python_full_version >= '3.12'" }, | ||||
|     ] | ||||
|     sdist = { url = "https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6", size = 159642 } | ||||
|     wheels = [ | ||||
|  | @ -270,14 +270,14 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { directory = "b" } | ||||
|     dependencies = [ | ||||
|         { name = "b1", marker = "python_version < '3.12'" }, | ||||
|         { name = "b2", marker = "python_version >= '3.12'" }, | ||||
|         { name = "b1", marker = "python_full_version < '3.12'" }, | ||||
|         { name = "b2", marker = "python_full_version >= '3.12'" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|     requires-dist = [ | ||||
|         { name = "b1", marker = "python_version < '3.12'", directory = "../b1" }, | ||||
|         { name = "b2", marker = "python_version >= '3.12'", directory = "../b2" }, | ||||
|         { name = "b1", marker = "python_full_version < '3.12'", directory = "../b1" }, | ||||
|         { name = "b2", marker = "python_full_version >= '3.12'", directory = "../b2" }, | ||||
|     ] | ||||
| 
 | ||||
|     [[package]] | ||||
|  | @ -285,7 +285,7 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { directory = "../b1" } | ||||
|     dependencies = [ | ||||
|         { name = "iniconfig", version = "1.1.1", source = { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" }, marker = "python_version < '3.12'" }, | ||||
|         { name = "iniconfig", version = "1.1.1", source = { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" }, marker = "python_full_version < '3.12'" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|  | @ -296,7 +296,7 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { directory = "../b2" } | ||||
|     dependencies = [ | ||||
|         { name = "iniconfig", version = "2.0.0", source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }, marker = "python_version >= '3.12'" }, | ||||
|         { name = "iniconfig", version = "2.0.0", source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }, marker = "python_full_version >= '3.12'" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|  | @ -316,7 +316,7 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = "1.1.1" | ||||
|     source = { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" } | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|     ] | ||||
|     wheels = [ | ||||
|         { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3" }, | ||||
|  | @ -327,7 +327,7 @@ fn root_package_splits_transitive_too() -> Result<()> { | |||
|     version = "2.0.0" | ||||
|     source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" } | ||||
|     environment-markers = [ | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
|     wheels = [ | ||||
|         { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" }, | ||||
|  | @ -404,8 +404,8 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { | |||
|     version = 1 | ||||
|     requires-python = ">=3.11, <3.13" | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
| 
 | ||||
|     [options] | ||||
|  | @ -416,18 +416,18 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { editable = "." } | ||||
|     dependencies = [ | ||||
|         { name = "anyio", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '3.12'" }, | ||||
|         { name = "anyio", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_version >= '3.12'" }, | ||||
|         { name = "b1", marker = "python_version < '3.12'" }, | ||||
|         { name = "b2", marker = "python_version >= '3.12'" }, | ||||
|         { name = "anyio", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, | ||||
|         { name = "anyio", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, | ||||
|         { name = "b1", marker = "python_full_version < '3.12'" }, | ||||
|         { name = "b2", marker = "python_full_version >= '3.12'" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|     requires-dist = [ | ||||
|         { name = "anyio", marker = "python_version < '3.12'", specifier = "==4.2.0" }, | ||||
|         { name = "anyio", marker = "python_version >= '3.12'", specifier = "==4.3.0" }, | ||||
|         { name = "b1", marker = "python_version < '3.12'", directory = "b1" }, | ||||
|         { name = "b2", marker = "python_version >= '3.12'", directory = "b2" }, | ||||
|         { name = "anyio", marker = "python_full_version < '3.12'", specifier = "==4.2.0" }, | ||||
|         { name = "anyio", marker = "python_full_version >= '3.12'", specifier = "==4.3.0" }, | ||||
|         { name = "b1", marker = "python_full_version < '3.12'", directory = "b1" }, | ||||
|         { name = "b2", marker = "python_full_version >= '3.12'", directory = "b2" }, | ||||
|     ] | ||||
| 
 | ||||
|     [[package]] | ||||
|  | @ -435,11 +435,11 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { | |||
|     version = "4.2.0" | ||||
|     source = { registry = "https://pypi.org/simple" } | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|     ] | ||||
|     dependencies = [ | ||||
|         { name = "idna", marker = "python_version < '3.12'" }, | ||||
|         { name = "sniffio", marker = "python_version < '3.12'" }, | ||||
|         { name = "idna", marker = "python_full_version < '3.12'" }, | ||||
|         { name = "sniffio", marker = "python_full_version < '3.12'" }, | ||||
|     ] | ||||
|     sdist = { url = "https://files.pythonhosted.org/packages/2d/b8/7333d87d5f03247215d86a86362fd3e324111788c6cdd8d2e6196a6ba833/anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f", size = 158770 } | ||||
|     wheels = [ | ||||
|  | @ -451,11 +451,11 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { | |||
|     version = "4.3.0" | ||||
|     source = { registry = "https://pypi.org/simple" } | ||||
|     environment-markers = [ | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
|     dependencies = [ | ||||
|         { name = "idna", marker = "python_version >= '3.12'" }, | ||||
|         { name = "sniffio", marker = "python_version >= '3.12'" }, | ||||
|         { name = "idna", marker = "python_full_version >= '3.12'" }, | ||||
|         { name = "sniffio", marker = "python_full_version >= '3.12'" }, | ||||
|     ] | ||||
|     sdist = { url = "https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6", size = 159642 } | ||||
|     wheels = [ | ||||
|  | @ -467,7 +467,7 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { directory = "b1" } | ||||
|     dependencies = [ | ||||
|         { name = "iniconfig", version = "1.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '3.12'" }, | ||||
|         { name = "iniconfig", version = "1.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|  | @ -478,7 +478,7 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { directory = "b2" } | ||||
|     dependencies = [ | ||||
|         { name = "iniconfig", version = "2.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_version >= '3.12'" }, | ||||
|         { name = "iniconfig", version = "2.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|  | @ -498,7 +498,7 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { | |||
|     version = "1.1.1" | ||||
|     source = { registry = "https://pypi.org/simple" } | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|     ] | ||||
|     sdist = { url = "https://files.pythonhosted.org/packages/23/a2/97899f6bd0e873fed3a7e67ae8d3a08b21799430fb4da15cfedf10d6e2c2/iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32", size = 8104 } | ||||
|     wheels = [ | ||||
|  | @ -510,7 +510,7 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { | |||
|     version = "2.0.0" | ||||
|     source = { registry = "https://pypi.org/simple" } | ||||
|     environment-markers = [ | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
|     sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } | ||||
|     wheels = [ | ||||
|  | @ -565,8 +565,8 @@ fn branching_between_registry_and_direct_url() -> Result<()> { | |||
|     version = 1 | ||||
|     requires-python = ">=3.11, <3.13" | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
| 
 | ||||
|     [options] | ||||
|  | @ -577,14 +577,14 @@ fn branching_between_registry_and_direct_url() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { editable = "." } | ||||
|     dependencies = [ | ||||
|         { name = "iniconfig", version = "1.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '3.12'" }, | ||||
|         { name = "iniconfig", version = "2.0.0", source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }, marker = "python_version >= '3.12'" }, | ||||
|         { name = "iniconfig", version = "1.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, | ||||
|         { name = "iniconfig", version = "2.0.0", source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }, marker = "python_full_version >= '3.12'" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|     requires-dist = [ | ||||
|         { name = "iniconfig", marker = "python_version < '3.12'", specifier = "==1.1.1" }, | ||||
|         { name = "iniconfig", marker = "python_version >= '3.12'", url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }, | ||||
|         { name = "iniconfig", marker = "python_full_version < '3.12'", specifier = "==1.1.1" }, | ||||
|         { name = "iniconfig", marker = "python_full_version >= '3.12'", url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }, | ||||
|     ] | ||||
| 
 | ||||
|     [[package]] | ||||
|  | @ -592,7 +592,7 @@ fn branching_between_registry_and_direct_url() -> Result<()> { | |||
|     version = "1.1.1" | ||||
|     source = { registry = "https://pypi.org/simple" } | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|     ] | ||||
|     sdist = { url = "https://files.pythonhosted.org/packages/23/a2/97899f6bd0e873fed3a7e67ae8d3a08b21799430fb4da15cfedf10d6e2c2/iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32", size = 8104 } | ||||
|     wheels = [ | ||||
|  | @ -604,7 +604,7 @@ fn branching_between_registry_and_direct_url() -> Result<()> { | |||
|     version = "2.0.0" | ||||
|     source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" } | ||||
|     environment-markers = [ | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
|     wheels = [ | ||||
|         { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" }, | ||||
|  | @ -650,8 +650,8 @@ fn branching_urls_of_different_sources_disjoint() -> Result<()> { | |||
|     version = 1 | ||||
|     requires-python = ">=3.11, <3.13" | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
| 
 | ||||
|     [options] | ||||
|  | @ -662,14 +662,14 @@ fn branching_urls_of_different_sources_disjoint() -> Result<()> { | |||
|     version = "0.1.0" | ||||
|     source = { editable = "." } | ||||
|     dependencies = [ | ||||
|         { name = "iniconfig", version = "1.1.1", source = { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" }, marker = "python_version < '3.12'" }, | ||||
|         { name = "iniconfig", version = "2.0.0", source = { git = "https://github.com/pytest-dev/iniconfig?rev=93f5930e668c0d1ddf4597e38dd0dea4e2665e7a#93f5930e668c0d1ddf4597e38dd0dea4e2665e7a" }, marker = "python_version >= '3.12'" }, | ||||
|         { name = "iniconfig", version = "1.1.1", source = { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" }, marker = "python_full_version < '3.12'" }, | ||||
|         { name = "iniconfig", version = "2.0.0", source = { git = "https://github.com/pytest-dev/iniconfig?rev=93f5930e668c0d1ddf4597e38dd0dea4e2665e7a#93f5930e668c0d1ddf4597e38dd0dea4e2665e7a" }, marker = "python_full_version >= '3.12'" }, | ||||
|     ] | ||||
| 
 | ||||
|     [package.metadata] | ||||
|     requires-dist = [ | ||||
|         { name = "iniconfig", marker = "python_version < '3.12'", url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" }, | ||||
|         { name = "iniconfig", marker = "python_version >= '3.12'", git = "https://github.com/pytest-dev/iniconfig?rev=93f5930e668c0d1ddf4597e38dd0dea4e2665e7a#93f5930e668c0d1ddf4597e38dd0dea4e2665e7a" }, | ||||
|         { name = "iniconfig", marker = "python_full_version < '3.12'", url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" }, | ||||
|         { name = "iniconfig", marker = "python_full_version >= '3.12'", git = "https://github.com/pytest-dev/iniconfig?rev=93f5930e668c0d1ddf4597e38dd0dea4e2665e7a#93f5930e668c0d1ddf4597e38dd0dea4e2665e7a" }, | ||||
|     ] | ||||
| 
 | ||||
|     [[package]] | ||||
|  | @ -677,7 +677,7 @@ fn branching_urls_of_different_sources_disjoint() -> Result<()> { | |||
|     version = "1.1.1" | ||||
|     source = { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" } | ||||
|     environment-markers = [ | ||||
|         "python_version < '3.12'", | ||||
|         "python_full_version < '3.12'", | ||||
|     ] | ||||
|     wheels = [ | ||||
|         { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3" }, | ||||
|  | @ -688,7 +688,7 @@ fn branching_urls_of_different_sources_disjoint() -> Result<()> { | |||
|     version = "2.0.0" | ||||
|     source = { git = "https://github.com/pytest-dev/iniconfig?rev=93f5930e668c0d1ddf4597e38dd0dea4e2665e7a#93f5930e668c0d1ddf4597e38dd0dea4e2665e7a" } | ||||
|     environment-markers = [ | ||||
|         "python_version >= '3.12'", | ||||
|         "python_full_version >= '3.12'", | ||||
|     ] | ||||
|     "###);
 | ||||
| 
 | ||||
|  | @ -723,7 +723,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'`: | ||||
|     error: Requirements contain conflicting URLs for package `iniconfig` in split `python_full_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
 | ||||
|     "###
 | ||||
|  |  | |||
|  | @ -1770,7 +1770,7 @@ fn update() -> Result<()> { | |||
|         version = "0.1.0" | ||||
|         requires-python = ">=3.12" | ||||
|         dependencies = [ | ||||
|             "requests[security,socks,use-chardet-on-py3]==2.31.0 ; python_version > '3.7'", | ||||
|             "requests[security,socks,use-chardet-on-py3]==2.31.0 ; python_full_version >= '3.8'", | ||||
|         ] | ||||
|         "###
 | ||||
|         ); | ||||
|  | @ -1808,7 +1808,7 @@ fn update() -> Result<()> { | |||
|         version = "0.1.0" | ||||
|         requires-python = ">=3.12" | ||||
|         dependencies = [ | ||||
|             "requests[security,socks,use-chardet-on-py3]==2.31.0 ; python_version > '3.7'", | ||||
|             "requests[security,socks,use-chardet-on-py3]==2.31.0 ; python_full_version >= '3.8'", | ||||
|         ] | ||||
| 
 | ||||
|         [tool.uv.sources] | ||||
|  | @ -1890,7 +1890,7 @@ fn update() -> Result<()> { | |||
|         ] | ||||
| 
 | ||||
|         [package.metadata] | ||||
|         requires-dist = [{ name = "requests", extras = ["security", "socks", "use-chardet-on-py3"], marker = "python_version > '3.7'", git = "https://github.com/psf/requests?tag=v2.32.3" }] | ||||
|         requires-dist = [{ name = "requests", extras = ["security", "socks", "use-chardet-on-py3"], marker = "python_full_version >= '3.8'", git = "https://github.com/psf/requests?tag=v2.32.3" }] | ||||
| 
 | ||||
|         [[package]] | ||||
|         name = "pysocks" | ||||
|  |  | |||
|  | @ -881,7 +881,7 @@ fn lock_wheel_url() -> Result<()> { | |||
|         requires-dist = [ | ||||
|             { name = "anyio", extras = ["trio"], marker = "extra == 'test'" }, | ||||
|             { name = "coverage", extras = ["toml"], marker = "extra == 'test'", specifier = ">=7" }, | ||||
|             { name = "exceptiongroup", marker = "python_version < '3.11'", specifier = ">=1.0.2" }, | ||||
|             { name = "exceptiongroup", marker = "python_full_version < '3.11'", specifier = ">=1.0.2" }, | ||||
|             { name = "exceptiongroup", marker = "extra == 'test'", specifier = ">=1.2.0" }, | ||||
|             { name = "hypothesis", marker = "extra == 'test'", specifier = ">=4.0" }, | ||||
|             { name = "idna", specifier = ">=2.8" }, | ||||
|  | @ -895,7 +895,7 @@ fn lock_wheel_url() -> Result<()> { | |||
|             { name = "sphinx-rtd-theme", marker = "extra == 'doc'" }, | ||||
|             { name = "trio", marker = "extra == 'trio'", specifier = ">=0.23" }, | ||||
|             { name = "trustme", marker = "extra == 'test'" }, | ||||
|             { name = "typing-extensions", marker = "python_version < '3.11'", specifier = ">=4.1" }, | ||||
|             { name = "typing-extensions", marker = "python_full_version < '3.11'", specifier = ">=4.1" }, | ||||
|             { name = "uvloop", marker = "platform_python_implementation == 'CPython' and platform_system != 'Windows' and extra == 'test'", specifier = ">=0.17" }, | ||||
|         ] | ||||
| 
 | ||||
|  | @ -1026,7 +1026,7 @@ fn lock_sdist_url() -> Result<()> { | |||
|         requires-dist = [ | ||||
|             { name = "anyio", extras = ["trio"], marker = "extra == 'test'" }, | ||||
|             { name = "coverage", extras = ["toml"], marker = "extra == 'test'", specifier = ">=7" }, | ||||
|             { name = "exceptiongroup", marker = "python_version < '3.11'", specifier = ">=1.0.2" }, | ||||
|             { name = "exceptiongroup", marker = "python_full_version < '3.11'", specifier = ">=1.0.2" }, | ||||
|             { name = "exceptiongroup", marker = "extra == 'test'", specifier = ">=1.2.0" }, | ||||
|             { name = "hypothesis", marker = "extra == 'test'", specifier = ">=4.0" }, | ||||
|             { name = "idna", specifier = ">=2.8" }, | ||||
|  | @ -1040,7 +1040,7 @@ fn lock_sdist_url() -> Result<()> { | |||
|             { name = "sphinx-rtd-theme", marker = "extra == 'doc'" }, | ||||
|             { name = "trio", marker = "extra == 'trio'", specifier = ">=0.23" }, | ||||
|             { name = "trustme", marker = "extra == 'test'" }, | ||||
|             { name = "typing-extensions", marker = "python_version < '3.11'", specifier = ">=4.1" }, | ||||
|             { name = "typing-extensions", marker = "python_full_version < '3.11'", specifier = ">=4.1" }, | ||||
|             { name = "uvloop", marker = "platform_python_implementation == 'CPython' and platform_system != 'Windows' and extra == 'test'", specifier = ">=0.17" }, | ||||
|         ] | ||||
| 
 | ||||
|  | @ -1611,8 +1611,8 @@ fn lock_conditional_dependency_extra() -> Result<()> { | |||
|         version = 1 | ||||
|         requires-python = ">=3.7" | ||||
|         environment-markers = [ | ||||
|             "python_version < '3.10'", | ||||
|             "python_version >= '3.10'", | ||||
|             "python_full_version < '3.10'", | ||||
|             "python_full_version >= '3.10'", | ||||
|         ] | ||||
| 
 | ||||
|         [options] | ||||
|  | @ -1739,13 +1739,13 @@ fn lock_conditional_dependency_extra() -> Result<()> { | |||
|         source = { editable = "." } | ||||
|         dependencies = [ | ||||
|             { name = "requests" }, | ||||
|             { name = "requests", extra = ["socks"], marker = "python_version < '3.10'" }, | ||||
|             { name = "requests", extra = ["socks"], marker = "python_full_version < '3.10'" }, | ||||
|         ] | ||||
| 
 | ||||
|         [package.metadata] | ||||
|         requires-dist = [ | ||||
|             { name = "requests" }, | ||||
|             { name = "requests", extras = ["socks"], marker = "python_version < '3.10'" }, | ||||
|             { name = "requests", extras = ["socks"], marker = "python_full_version < '3.10'" }, | ||||
|         ] | ||||
| 
 | ||||
|         [[package]] | ||||
|  | @ -1774,7 +1774,7 @@ fn lock_conditional_dependency_extra() -> Result<()> { | |||
| 
 | ||||
|         [package.optional-dependencies] | ||||
|         socks = [ | ||||
|             { name = "pysocks", marker = "python_version < '3.10'" }, | ||||
|             { name = "pysocks", marker = "python_full_version < '3.10'" }, | ||||
|         ] | ||||
| 
 | ||||
|         [[package]] | ||||
|  | @ -2747,7 +2747,7 @@ fn lock_requires_python() -> Result<()> { | |||
|         version = "23.2.0" | ||||
|         source = { registry = "https://pypi.org/simple" } | ||||
|         dependencies = [ | ||||
|             { name = "importlib-metadata", marker = "python_version < '3.8'" }, | ||||
|             { name = "importlib-metadata", marker = "python_full_version < '3.8'" }, | ||||
|         ] | ||||
|         sdist = { url = "https://files.pythonhosted.org/packages/e3/fc/f800d51204003fa8ae392c4e8278f256206e7a919b708eef054f5f4b650d/attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", size = 780820 } | ||||
|         wheels = [ | ||||
|  | @ -2760,8 +2760,8 @@ fn lock_requires_python() -> Result<()> { | |||
|         source = { registry = "https://pypi.org/simple" } | ||||
|         dependencies = [ | ||||
|             { name = "attrs" }, | ||||
|             { name = "exceptiongroup", marker = "python_version < '3.11'" }, | ||||
|             { name = "typing-extensions", marker = "python_version < '3.11'" }, | ||||
|             { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, | ||||
|             { name = "typing-extensions", marker = "python_full_version < '3.11'" }, | ||||
|         ] | ||||
|         sdist = { url = "https://files.pythonhosted.org/packages/68/d4/27f9fd840e74d51b6d6a024d39ff495b56ffde71d28eb82758b7b85d0617/cattrs-23.1.2.tar.gz", hash = "sha256:db1c821b8c537382b2c7c66678c3790091ca0275ac486c76f3c8f3920e83c657", size = 39998 } | ||||
|         wheels = [ | ||||
|  | @ -2782,7 +2782,7 @@ fn lock_requires_python() -> Result<()> { | |||
|         version = "6.7.0" | ||||
|         source = { registry = "https://pypi.org/simple" } | ||||
|         dependencies = [ | ||||
|             { name = "typing-extensions", marker = "python_version < '3.8'" }, | ||||
|             { name = "typing-extensions", marker = "python_full_version < '3.8'" }, | ||||
|             { name = "zipp" }, | ||||
|         ] | ||||
|         sdist = { url = "https://files.pythonhosted.org/packages/a3/82/f6e29c8d5c098b6be61460371c2c5591f4a335923639edec43b3830650a4/importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", size = 53569 } | ||||
|  | @ -2899,7 +2899,7 @@ fn lock_requires_python() -> Result<()> { | |||
|         version = "23.2.0" | ||||
|         source = { registry = "https://pypi.org/simple" } | ||||
|         dependencies = [ | ||||
|             { name = "importlib-metadata", marker = "python_version < '3.8'" }, | ||||
|             { name = "importlib-metadata", marker = "python_full_version < '3.8'" }, | ||||
|         ] | ||||
|         sdist = { url = "https://files.pythonhosted.org/packages/e3/fc/f800d51204003fa8ae392c4e8278f256206e7a919b708eef054f5f4b650d/attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", size = 780820 } | ||||
|         wheels = [ | ||||
|  | @ -2912,8 +2912,8 @@ fn lock_requires_python() -> Result<()> { | |||
|         source = { registry = "https://pypi.org/simple" } | ||||
|         dependencies = [ | ||||
|             { name = "attrs" }, | ||||
|             { name = "exceptiongroup", marker = "python_version < '3.11'" }, | ||||
|             { name = "typing-extensions", marker = "python_version < '3.11'" }, | ||||
|             { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, | ||||
|             { name = "typing-extensions", marker = "python_full_version < '3.11'" }, | ||||
|         ] | ||||
|         sdist = { url = "https://files.pythonhosted.org/packages/68/d4/27f9fd840e74d51b6d6a024d39ff495b56ffde71d28eb82758b7b85d0617/cattrs-23.1.2.tar.gz", hash = "sha256:db1c821b8c537382b2c7c66678c3790091ca0275ac486c76f3c8f3920e83c657", size = 39998 } | ||||
|         wheels = [ | ||||
|  | @ -2934,7 +2934,7 @@ fn lock_requires_python() -> Result<()> { | |||
|         version = "6.7.0" | ||||
|         source = { registry = "https://pypi.org/simple" } | ||||
|         dependencies = [ | ||||
|             { name = "typing-extensions", marker = "python_version < '3.8'" }, | ||||
|             { name = "typing-extensions", marker = "python_full_version < '3.8'" }, | ||||
|             { name = "zipp" }, | ||||
|         ] | ||||
|         sdist = { url = "https://files.pythonhosted.org/packages/a3/82/f6e29c8d5c098b6be61460371c2c5591f4a335923639edec43b3830650a4/importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", size = 53569 } | ||||
|  | @ -3175,7 +3175,7 @@ fn lock_requires_python_wheels() -> Result<()> { | |||
|         assert_snapshot!( | ||||
|             lock, @r###" | ||||
|         version = 1 | ||||
|         requires-python = ">=3.12, <3.13" | ||||
|         requires-python = "==3.12.*" | ||||
| 
 | ||||
|         [options] | ||||
|         exclude-newer = "2024-03-25 00:00:00 UTC" | ||||
|  | @ -3260,7 +3260,7 @@ fn lock_requires_python_wheels() -> Result<()> { | |||
|         assert_snapshot!( | ||||
|             lock, @r###" | ||||
|         version = 1 | ||||
|         requires-python = ">=3.11, <3.12" | ||||
|         requires-python = "==3.11.*" | ||||
| 
 | ||||
|         [options] | ||||
|         exclude-newer = "2024-03-25 00:00:00 UTC" | ||||
|  | @ -3370,7 +3370,7 @@ fn lock_requires_python_star() -> Result<()> { | |||
|         assert_snapshot!( | ||||
|             lock, @r###" | ||||
|         version = 1 | ||||
|         requires-python = ">=3.11, <3.12" | ||||
|         requires-python = "==3.11.*" | ||||
| 
 | ||||
|         [options] | ||||
|         exclude-newer = "2024-03-25 00:00:00 UTC" | ||||
|  | @ -3711,12 +3711,10 @@ 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'", | ||||
|             "python_full_version == '3.10'", | ||||
|             "python_full_version > '3.10' and python_full_version < '3.11'", | ||||
|             "python_full_version >= '3.11'", | ||||
|         ] | ||||
| 
 | ||||
|         [options] | ||||
|  | @ -3752,10 +3750,10 @@ fn lock_python_version_marker_complement() -> Result<()> { | |||
| 
 | ||||
|         [package.metadata] | ||||
|         requires-dist = [ | ||||
|             { name = "attrs", marker = "python_version <= '3.10'" }, | ||||
|             { name = "attrs", marker = "python_version > '3.10'" }, | ||||
|             { name = "iniconfig", marker = "python_version < '3.10'" }, | ||||
|             { name = "iniconfig", marker = "python_version >= '3.10'" }, | ||||
|             { name = "attrs", marker = "python_full_version < '3.11'" }, | ||||
|             { name = "attrs", marker = "python_full_version >= '3.11'" }, | ||||
|             { name = "iniconfig", marker = "python_full_version < '3.10'" }, | ||||
|             { name = "iniconfig", marker = "python_full_version >= '3.10'" }, | ||||
|             { name = "typing-extensions", marker = "python_full_version <= '3.10'" }, | ||||
|             { name = "typing-extensions", marker = "python_full_version > '3.10'" }, | ||||
|         ] | ||||
|  | @ -3966,7 +3964,7 @@ fn lock_conditional_unconditional() -> Result<()> { | |||
|         [package.metadata] | ||||
|         requires-dist = [ | ||||
|             { name = "iniconfig" }, | ||||
|             { name = "iniconfig", marker = "python_version < '3.12'" }, | ||||
|             { name = "iniconfig", marker = "python_full_version < '3.12'" }, | ||||
|         ] | ||||
|         "###
 | ||||
|         ); | ||||
|  | @ -4045,7 +4043,7 @@ fn lock_multiple_markers() -> Result<()> { | |||
|         [package.metadata] | ||||
|         requires-dist = [ | ||||
|             { name = "iniconfig", marker = "implementation_name == 'cpython'" }, | ||||
|             { name = "iniconfig", marker = "python_version < '3.12'" }, | ||||
|             { name = "iniconfig", marker = "python_full_version < '3.12'" }, | ||||
|         ] | ||||
|         "###
 | ||||
|         ); | ||||
|  | @ -9747,9 +9745,9 @@ fn lock_narrowed_python_version() -> Result<()> { | |||
|         version = 1 | ||||
|         requires-python = ">=3.7" | ||||
|         environment-markers = [ | ||||
|             "python_version < '3.9'", | ||||
|             "python_version >= '3.9' and python_version <= '3.10'", | ||||
|             "python_version > '3.10'", | ||||
|             "python_full_version < '3.9'", | ||||
|             "python_full_version >= '3.9' and python_full_version < '3.11'", | ||||
|             "python_full_version >= '3.11'", | ||||
|         ] | ||||
| 
 | ||||
|         [options] | ||||
|  | @ -9760,7 +9758,7 @@ fn lock_narrowed_python_version() -> Result<()> { | |||
|         version = "0.1.0" | ||||
|         source = { directory = "dependency" } | ||||
|         dependencies = [ | ||||
|             { name = "iniconfig", marker = "python_version < '3.9' or python_version > '3.10'" }, | ||||
|             { name = "iniconfig", marker = "python_full_version < '3.9' or python_full_version >= '3.11'" }, | ||||
|         ] | ||||
| 
 | ||||
|         [package.metadata] | ||||
|  | @ -9780,13 +9778,13 @@ fn lock_narrowed_python_version() -> Result<()> { | |||
|         version = "0.1.0" | ||||
|         source = { editable = "." } | ||||
|         dependencies = [ | ||||
|             { name = "dependency", marker = "python_version < '3.9' or python_version > '3.10'" }, | ||||
|             { name = "dependency", marker = "python_full_version < '3.9' or python_full_version >= '3.11'" }, | ||||
|         ] | ||||
| 
 | ||||
|         [package.metadata] | ||||
|         requires-dist = [ | ||||
|             { name = "dependency", marker = "python_version < '3.9'", directory = "dependency" }, | ||||
|             { name = "dependency", marker = "python_version > '3.10'", directory = "dependency" }, | ||||
|             { name = "dependency", marker = "python_full_version < '3.9'", directory = "dependency" }, | ||||
|             { name = "dependency", marker = "python_full_version >= '3.11'", directory = "dependency" }, | ||||
|         ] | ||||
|         "###
 | ||||
|         ); | ||||
|  | @ -9883,7 +9881,7 @@ fn lock_exclude_unnecessary_python_forks() -> Result<()> { | |||
|         [package.metadata] | ||||
|         requires-dist = [ | ||||
|             { name = "anyio", marker = "sys_platform == 'darwin'" }, | ||||
|             { name = "anyio", marker = "python_version > '3.10'" }, | ||||
|             { name = "anyio", marker = "python_full_version >= '3.11'" }, | ||||
|         ] | ||||
| 
 | ||||
|         [[package]] | ||||
|  |  | |||
|  | @ -893,9 +893,9 @@ fn fork_incomplete_markers() -> Result<()> { | |||
|         version = 1 | ||||
|         requires-python = ">=3.8" | ||||
|         environment-markers = [ | ||||
|             "python_version < '3.10'", | ||||
|             "python_version >= '3.10' and python_version < '3.11'", | ||||
|             "python_version >= '3.11'", | ||||
|             "python_full_version < '3.10'", | ||||
|             "python_full_version == '3.10.*'", | ||||
|             "python_full_version >= '3.11'", | ||||
|         ] | ||||
| 
 | ||||
|         [[package]] | ||||
|  | @ -903,7 +903,7 @@ fn fork_incomplete_markers() -> Result<()> { | |||
|         version = "1.0.0" | ||||
|         source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } | ||||
|         environment-markers = [ | ||||
|             "python_version < '3.10'", | ||||
|             "python_full_version < '3.10'", | ||||
|         ] | ||||
|         sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_incomplete_markers_a-1.0.0.tar.gz", hash = "sha256:dd56de2e560b3f95c529c44cbdae55d9b1ada826ddd3e19d3ea45438224ad603" } | ||||
|         wheels = [ | ||||
|  | @ -915,7 +915,7 @@ fn fork_incomplete_markers() -> Result<()> { | |||
|         version = "2.0.0" | ||||
|         source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } | ||||
|         environment-markers = [ | ||||
|             "python_version >= '3.11'", | ||||
|             "python_full_version >= '3.11'", | ||||
|         ] | ||||
|         sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_incomplete_markers_a-2.0.0.tar.gz", hash = "sha256:580f1454a172036c89f5cfbefe52f175b011806a61f243eb476526bcc186e0be" } | ||||
|         wheels = [ | ||||
|  | @ -927,7 +927,7 @@ fn fork_incomplete_markers() -> Result<()> { | |||
|         version = "1.0.0" | ||||
|         source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } | ||||
|         dependencies = [ | ||||
|             { name = "package-c", marker = "python_version == '3.10'" }, | ||||
|             { name = "package-c", marker = "python_full_version < '3.11'" }, | ||||
|         ] | ||||
|         sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_incomplete_markers_b-1.0.0.tar.gz", hash = "sha256:c4deba44768923473d077bdc0e177033fcb6e6fd406d56830d7ee6f4ffad68c1" } | ||||
|         wheels = [ | ||||
|  | @ -948,15 +948,15 @@ fn fork_incomplete_markers() -> Result<()> { | |||
|         version = "0.1.0" | ||||
|         source = { editable = "." } | ||||
|         dependencies = [ | ||||
|             { name = "package-a", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "python_version < '3.10'" }, | ||||
|             { name = "package-a", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "python_version >= '3.11'" }, | ||||
|             { name = "package-a", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "python_full_version < '3.10'" }, | ||||
|             { name = "package-a", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "python_full_version >= '3.11'" }, | ||||
|             { name = "package-b" }, | ||||
|         ] | ||||
| 
 | ||||
|         [package.metadata] | ||||
|         requires-dist = [ | ||||
|             { name = "package-a", marker = "python_version < '3.10'", specifier = "==1" }, | ||||
|             { name = "package-a", marker = "python_version >= '3.11'", specifier = "==2" }, | ||||
|             { name = "package-a", marker = "python_full_version < '3.10'", specifier = "==1" }, | ||||
|             { name = "package-a", marker = "python_full_version >= '3.11'", specifier = "==2" }, | ||||
|             { name = "package-b" }, | ||||
|         ] | ||||
|         "###
 | ||||
|  | @ -2978,9 +2978,9 @@ fn fork_overlapping_markers_basic() -> Result<()> { | |||
|         version = 1 | ||||
|         requires-python = ">=3.8" | ||||
|         environment-markers = [ | ||||
|             "python_version < '3.10'", | ||||
|             "python_version >= '3.10' and python_version < '3.11'", | ||||
|             "python_version >= '3.11'", | ||||
|             "python_full_version < '3.10'", | ||||
|             "python_full_version == '3.10.*'", | ||||
|             "python_full_version >= '3.11'", | ||||
|         ] | ||||
| 
 | ||||
|         [[package]] | ||||
|  | @ -3002,9 +3002,9 @@ fn fork_overlapping_markers_basic() -> Result<()> { | |||
| 
 | ||||
|         [package.metadata] | ||||
|         requires-dist = [ | ||||
|             { name = "package-a", marker = "python_version < '3.10'", specifier = ">=1.0.0" }, | ||||
|             { name = "package-a", marker = "python_version >= '3.10'", specifier = ">=1.1.0" }, | ||||
|             { name = "package-a", marker = "python_version >= '3.11'", specifier = ">=1.2.0" }, | ||||
|             { name = "package-a", marker = "python_full_version < '3.10'", specifier = ">=1.0.0" }, | ||||
|             { name = "package-a", marker = "python_full_version >= '3.10'", specifier = ">=1.1.0" }, | ||||
|             { name = "package-a", marker = "python_full_version >= '3.11'", specifier = ">=1.2.0" }, | ||||
|         ] | ||||
|         "###
 | ||||
|         ); | ||||
|  | @ -4326,11 +4326,11 @@ fn fork_requires_python_patch_overlap() -> Result<()> { | |||
|         version = "0.1.0" | ||||
|         source = { editable = "." } | ||||
|         dependencies = [ | ||||
|             { name = "package-a", marker = "python_version == '3.10'" }, | ||||
|             { name = "package-a", marker = "python_full_version < '3.11'" }, | ||||
|         ] | ||||
| 
 | ||||
|         [package.metadata] | ||||
|         requires-dist = [{ name = "package-a", marker = "python_version == '3.10'", specifier = "==1.0.0" }] | ||||
|         requires-dist = [{ name = "package-a", marker = "python_full_version == '3.10.*'", specifier = "==1.0.0" }] | ||||
|         "###
 | ||||
|         ); | ||||
|     }); | ||||
|  | @ -4412,7 +4412,7 @@ fn fork_requires_python() -> Result<()> { | |||
|         source = { editable = "." } | ||||
| 
 | ||||
|         [package.metadata] | ||||
|         requires-dist = [{ name = "package-a", marker = "python_version == '3.9'", specifier = "==1.0.0" }] | ||||
|         requires-dist = [{ name = "package-a", marker = "python_full_version == '3.9.*'", specifier = "==1.0.0" }] | ||||
|         "###
 | ||||
|         ); | ||||
|     }); | ||||
|  |  | |||
|  | @ -6443,11 +6443,11 @@ fn no_strip_markers() -> Result<()> { | |||
|     ----- stdout ----- | ||||
|     # This file was autogenerated by uv via the following command: | ||||
|     #    uv pip compile --cache-dir [CACHE_DIR] requirements.in --no-strip-markers --python-platform linux | ||||
|     anyio==4.3.0 ; python_version > '3.11' | ||||
|     anyio==4.3.0 ; python_full_version >= '3.12' | ||||
|         # via -r requirements.in | ||||
|     idna==3.6 ; python_version > '3.11' | ||||
|     idna==3.6 ; python_full_version >= '3.12' | ||||
|         # via anyio | ||||
|     sniffio==1.3.1 ; python_version > '3.11' | ||||
|     sniffio==1.3.1 ; python_full_version >= '3.12' | ||||
|         # via anyio | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|  | @ -6479,23 +6479,23 @@ fn no_strip_markers_multiple_markers() -> Result<()> { | |||
|     ----- stdout ----- | ||||
|     # This file was autogenerated by uv via the following command: | ||||
|     #    uv pip compile --cache-dir [CACHE_DIR] requirements.in --no-strip-markers --python-platform windows | ||||
|     attrs==23.2.0 ; sys_platform == 'win32' or python_version > '3.11' | ||||
|     attrs==23.2.0 ; sys_platform == 'win32' or python_full_version >= '3.12' | ||||
|         # via | ||||
|         #   outcome | ||||
|         #   trio | ||||
|     cffi==1.16.0 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'win32') or (python_version > '3.11' and implementation_name != 'pypy' and os_name == 'nt') | ||||
|     cffi==1.16.0 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version >= '3.12' and implementation_name != 'pypy' and os_name == 'nt') | ||||
|         # via trio | ||||
|     idna==3.6 ; sys_platform == 'win32' or python_version > '3.11' | ||||
|     idna==3.6 ; sys_platform == 'win32' or python_full_version >= '3.12' | ||||
|         # via trio | ||||
|     outcome==1.3.0.post0 ; sys_platform == 'win32' or python_version > '3.11' | ||||
|     outcome==1.3.0.post0 ; sys_platform == 'win32' or python_full_version >= '3.12' | ||||
|         # via trio | ||||
|     pycparser==2.21 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'win32') or (python_version > '3.11' and implementation_name != 'pypy' and os_name == 'nt') | ||||
|     pycparser==2.21 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version >= '3.12' and implementation_name != 'pypy' and os_name == 'nt') | ||||
|         # via cffi | ||||
|     sniffio==1.3.1 ; sys_platform == 'win32' or python_version > '3.11' | ||||
|     sniffio==1.3.1 ; sys_platform == 'win32' or python_full_version >= '3.12' | ||||
|         # via trio | ||||
|     sortedcontainers==2.4.0 ; sys_platform == 'win32' or python_version > '3.11' | ||||
|     sortedcontainers==2.4.0 ; sys_platform == 'win32' or python_full_version >= '3.12' | ||||
|         # via trio | ||||
|     trio==0.25.0 ; sys_platform == 'win32' or python_version > '3.11' | ||||
|     trio==0.25.0 ; sys_platform == 'win32' or python_full_version >= '3.12' | ||||
|         # via -r requirements.in | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|  | @ -6524,23 +6524,23 @@ fn no_strip_markers_transitive_marker() -> Result<()> { | |||
|     ----- stdout ----- | ||||
|     # This file was autogenerated by uv via the following command: | ||||
|     #    uv pip compile --cache-dir [CACHE_DIR] requirements.in --no-strip-markers --python-platform windows | ||||
|     attrs==23.2.0 ; python_version > '3.11' | ||||
|     attrs==23.2.0 ; python_full_version >= '3.12' | ||||
|         # via | ||||
|         #   outcome | ||||
|         #   trio | ||||
|     cffi==1.16.0 ; python_version > '3.11' and implementation_name != 'pypy' and os_name == 'nt' | ||||
|     cffi==1.16.0 ; python_full_version >= '3.12' and implementation_name != 'pypy' and os_name == 'nt' | ||||
|         # via trio | ||||
|     idna==3.6 ; python_version > '3.11' | ||||
|     idna==3.6 ; python_full_version >= '3.12' | ||||
|         # via trio | ||||
|     outcome==1.3.0.post0 ; python_version > '3.11' | ||||
|     outcome==1.3.0.post0 ; python_full_version >= '3.12' | ||||
|         # via trio | ||||
|     pycparser==2.21 ; python_version > '3.11' and implementation_name != 'pypy' and os_name == 'nt' | ||||
|     pycparser==2.21 ; python_full_version >= '3.12' and implementation_name != 'pypy' and os_name == 'nt' | ||||
|         # via cffi | ||||
|     sniffio==1.3.1 ; python_version > '3.11' | ||||
|     sniffio==1.3.1 ; python_full_version >= '3.12' | ||||
|         # via trio | ||||
|     sortedcontainers==2.4.0 ; python_version > '3.11' | ||||
|     sortedcontainers==2.4.0 ; python_full_version >= '3.12' | ||||
|         # via trio | ||||
|     trio==0.25.0 ; python_version > '3.11' | ||||
|     trio==0.25.0 ; python_full_version >= '3.12' | ||||
|         # via -r requirements.in | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|  | @ -6816,9 +6816,9 @@ fn universal_multi_version() -> Result<()> { | |||
|     ----- 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' | ||||
|     iniconfig==1.0.0 ; python_full_version < '3.13' | ||||
|         # via -r requirements.in | ||||
|     iniconfig==2.0.0 ; python_version > '3.12' | ||||
|     iniconfig==2.0.0 ; python_full_version >= '3.13' | ||||
|         # via -r requirements.in | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|  | @ -7222,7 +7222,7 @@ fn universal_disjoint_base_or_local_requirement() -> Result<()> { | |||
|     ----- stdout ----- | ||||
|     # This file was autogenerated by uv via the following command: | ||||
|     #    uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal | ||||
|     cmake==3.28.4 ; python_version >= '3.11' and python_version <= '3.12' and platform_machine == 'x86_64' and platform_system == 'Linux' | ||||
|     cmake==3.28.4 ; python_full_version >= '3.11' and python_full_version < '3.13' and platform_machine == 'x86_64' and platform_system == 'Linux' | ||||
|         # via triton | ||||
|     . | ||||
|         # via -r requirements.in | ||||
|  | @ -7232,7 +7232,7 @@ fn universal_disjoint_base_or_local_requirement() -> Result<()> { | |||
|         #   triton | ||||
|     jinja2==3.1.3 | ||||
|         # via torch | ||||
|     lit==18.1.2 ; python_version >= '3.11' and python_version <= '3.12' and platform_machine == 'x86_64' and platform_system == 'Linux' | ||||
|     lit==18.1.2 ; python_full_version >= '3.11' and python_full_version < '3.13' and platform_machine == 'x86_64' and platform_system == 'Linux' | ||||
|         # via triton | ||||
|     markupsafe==2.1.5 | ||||
|         # via jinja2 | ||||
|  | @ -7242,20 +7242,20 @@ fn universal_disjoint_base_or_local_requirement() -> Result<()> { | |||
|         # via torch | ||||
|     sympy==1.12 | ||||
|         # via torch | ||||
|     torch==2.0.0 ; python_version < '3.11' | ||||
|     torch==2.0.0 ; python_full_version < '3.11' | ||||
|         # via | ||||
|         #   -r requirements.in | ||||
|         #   example | ||||
|     torch==2.0.0+cpu ; python_version > '3.12' | ||||
|     torch==2.0.0+cpu ; python_full_version >= '3.13' | ||||
|         # via | ||||
|         #   -r requirements.in | ||||
|         #   example | ||||
|     torch==2.0.0+cu118 ; python_version >= '3.11' and python_version <= '3.12' | ||||
|     torch==2.0.0+cu118 ; python_full_version >= '3.11' and python_full_version < '3.13' | ||||
|         # via | ||||
|         #   -r requirements.in | ||||
|         #   example | ||||
|         #   triton | ||||
|     triton==2.0.0 ; python_version >= '3.11' and python_version <= '3.12' and platform_machine == 'x86_64' and platform_system == 'Linux' | ||||
|     triton==2.0.0 ; python_full_version >= '3.11' and python_full_version < '3.13' and platform_machine == 'x86_64' and platform_system == 'Linux' | ||||
|         # via torch | ||||
|     typing-extensions==4.10.0 | ||||
|         # via torch | ||||
|  | @ -7954,9 +7954,9 @@ fn universal_requires_python() -> Result<()> { | |||
|     ----- stdout ----- | ||||
|     # This file was autogenerated by uv via the following command: | ||||
|     #    uv pip compile --cache-dir [CACHE_DIR] requirements.in -p 3.8 --universal | ||||
|     numpy==1.24.4 ; python_version < '3.9' | ||||
|     numpy==1.24.4 ; python_full_version < '3.9' | ||||
|         # via -r requirements.in | ||||
|     numpy==1.26.4 ; python_version >= '3.9' | ||||
|     numpy==1.26.4 ; python_full_version >= '3.9' | ||||
|         # via -r requirements.in | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|  | @ -7993,35 +7993,35 @@ fn universal_requires_python_incomplete() -> Result<()> { | |||
|     ----- 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 your requirements are unsatisfiable. | ||||
|       ╰─▶ Because only the following versions of uv{python_full_version >= '3.8'} are available: | ||||
|               uv{python_full_version >= '3.8'}==0.0.5 | ||||
|               uv{python_full_version >= '3.8'}==0.1.0 | ||||
|               uv{python_full_version >= '3.8'}==0.1.1 | ||||
|               uv{python_full_version >= '3.8'}==0.1.2 | ||||
|               uv{python_full_version >= '3.8'}==0.1.3 | ||||
|               uv{python_full_version >= '3.8'}==0.1.4 | ||||
|               uv{python_full_version >= '3.8'}==0.1.5 | ||||
|               uv{python_full_version >= '3.8'}==0.1.6 | ||||
|               uv{python_full_version >= '3.8'}==0.1.7 | ||||
|               uv{python_full_version >= '3.8'}==0.1.8 | ||||
|               uv{python_full_version >= '3.8'}==0.1.9 | ||||
|               uv{python_full_version >= '3.8'}==0.1.10 | ||||
|               uv{python_full_version >= '3.8'}==0.1.11 | ||||
|               uv{python_full_version >= '3.8'}==0.1.12 | ||||
|               uv{python_full_version >= '3.8'}==0.1.13 | ||||
|               uv{python_full_version >= '3.8'}==0.1.14 | ||||
|               uv{python_full_version >= '3.8'}==0.1.15 | ||||
|               uv{python_full_version >= '3.8'}==0.1.16 | ||||
|               uv{python_full_version >= '3.8'}==0.1.17 | ||||
|               uv{python_full_version >= '3.8'}==0.1.18 | ||||
|               uv{python_full_version >= '3.8'}==0.1.19 | ||||
|               uv{python_full_version >= '3.8'}==0.1.20 | ||||
|               uv{python_full_version >= '3.8'}==0.1.21 | ||||
|               uv{python_full_version >= '3.8'}==0.1.22 | ||||
|               uv{python_full_version >= '3.8'}==0.1.23 | ||||
|               uv{python_full_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_full_version >= '3.8'} are incompatible. | ||||
|           And because you require uv{python_full_version >= '3.8'}, we can conclude that your requirements are unsatisfiable. | ||||
|     "###
 | ||||
|     ); | ||||
| 
 | ||||
|  | @ -8075,7 +8075,7 @@ fn universal_no_repeated_unconditional_distributions_1() -> Result<()> { | |||
|         # via requests | ||||
|     imagesize==1.4.1 | ||||
|         # via sphinx | ||||
|     importlib-metadata==7.1.0 ; python_version < '3.10' | ||||
|     importlib-metadata==7.1.0 ; python_full_version < '3.10' | ||||
|         # via sphinx | ||||
|     isort==5.13.2 | ||||
|         # via pylint | ||||
|  | @ -8093,7 +8093,7 @@ fn universal_no_repeated_unconditional_distributions_1() -> Result<()> { | |||
|         # via sphinx | ||||
|     pylint==3.1.0 | ||||
|         # via -r requirements.in | ||||
|     pytz==2024.1 ; python_version < '3.9' | ||||
|     pytz==2024.1 ; python_full_version < '3.9' | ||||
|         # via babel | ||||
|     requests==2.31.0 | ||||
|         # via sphinx | ||||
|  | @ -8113,17 +8113,17 @@ fn universal_no_repeated_unconditional_distributions_1() -> Result<()> { | |||
|         # via sphinx | ||||
|     sphinxcontrib-serializinghtml==1.1.5 | ||||
|         # via sphinx | ||||
|     tomli==2.0.1 ; python_version < '3.11' | ||||
|     tomli==2.0.1 ; python_full_version < '3.11' | ||||
|         # via pylint | ||||
|     tomlkit==0.12.4 | ||||
|         # via pylint | ||||
|     typing-extensions==4.10.0 ; python_version < '3.11' | ||||
|     typing-extensions==4.10.0 ; python_full_version < '3.11' | ||||
|         # via | ||||
|         #   astroid | ||||
|         #   pylint | ||||
|     urllib3==2.2.1 | ||||
|         # via requests | ||||
|     zipp==3.18.1 ; python_version < '3.10' | ||||
|     zipp==3.18.1 ; python_full_version < '3.10' | ||||
|         # via importlib-metadata | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|  | @ -8226,11 +8226,11 @@ fn universal_prefer_upper_bounds() -> Result<()> { | |||
|         # via pylint | ||||
|     pylint==2.17.7 | ||||
|         # via -r requirements.in | ||||
|     tomli==2.0.1 ; python_version < '3.11' | ||||
|     tomli==2.0.1 ; python_full_version < '3.11' | ||||
|         # via pylint | ||||
|     tomlkit==0.12.4 | ||||
|         # via pylint | ||||
|     typing-extensions==4.10.0 ; python_version < '3.11' | ||||
|     typing-extensions==4.10.0 ; python_full_version < '3.11' | ||||
|         # via | ||||
|         #   astroid | ||||
|         #   pylint | ||||
|  | @ -10030,7 +10030,7 @@ fn emit_marker_expression_exciting_linux() -> Result<()> { | |||
|     # This file was autogenerated by uv via the following command: | ||||
|     #    uv pip compile --cache-dir [CACHE_DIR] requirements.in --emit-marker-expression | ||||
|     # Pinned dependencies known to be valid for: | ||||
|     #    python_version == '3.12' and platform_python_implementation == 'CPython' and platform_system == 'Linux' | ||||
|     #    python_full_version == '3.12.1' and platform_python_implementation == 'CPython' and platform_system == 'Linux' | ||||
|     anyio==4.3.0 | ||||
|         # via -r requirements.in | ||||
|     idna==3.6 | ||||
|  | @ -10067,7 +10067,7 @@ fn emit_marker_expression_direct() -> Result<()> { | |||
|     # This file was autogenerated by uv via the following command: | ||||
|     #    uv pip compile --cache-dir [CACHE_DIR] requirements.in --emit-marker-expression | ||||
|     # Pinned dependencies known to be valid for: | ||||
|     #    python_version == '3.12' and platform_python_implementation == 'CPython' and platform_system == 'Linux' and sys_platform == 'linux' | ||||
|     #    python_full_version == '3.12.1' and platform_python_implementation == 'CPython' and platform_system == 'Linux' and sys_platform == 'linux' | ||||
|     anyio==4.3.0 | ||||
|         # via -r requirements.in | ||||
|     idna==3.6 | ||||
|  | @ -10147,7 +10147,7 @@ fn emit_marker_expression_pypy() -> Result<()> { | |||
|     # This file was autogenerated by uv via the following command: | ||||
|     #    uv pip compile --cache-dir [CACHE_DIR] requirements.in --emit-marker-expression | ||||
|     # Pinned dependencies known to be valid for: | ||||
|     #    python_version == '3.12' and implementation_name == 'cpython' | ||||
|     #    python_full_version == '3.12.1' and implementation_name == 'cpython' | ||||
|     pendulum==3.0.0 | ||||
|         # via -r requirements.in | ||||
|     python-dateutil==2.9.0.post0 | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ source = { registry = "https://pypi.org/simple" } | |||
| dependencies = [ | ||||
|     { name = "aiohappyeyeballs" }, | ||||
|     { name = "aiosignal" }, | ||||
|     { name = "async-timeout", marker = "python_version < '3.11'" }, | ||||
|     { name = "async-timeout", marker = "python_full_version < '3.11'" }, | ||||
|     { name = "attrs" }, | ||||
|     { name = "frozenlist" }, | ||||
|     { name = "multidict" }, | ||||
|  | @ -183,8 +183,8 @@ dependencies = [ | |||
|     { name = "packaging" }, | ||||
|     { name = "pathspec" }, | ||||
|     { name = "platformdirs" }, | ||||
|     { name = "tomli", marker = "python_version < '3.11'" }, | ||||
|     { name = "typing-extensions", marker = "python_version < '3.11'" }, | ||||
|     { name = "tomli", marker = "python_full_version < '3.11'" }, | ||||
|     { name = "typing-extensions", marker = "python_full_version < '3.11'" }, | ||||
| ] | ||||
| 
 | ||||
| [package.optional-dependencies] | ||||
|  | @ -214,8 +214,8 @@ requires-dist = [ | |||
|     { name = "pathspec", specifier = ">=0.9.0" }, | ||||
|     { name = "platformdirs", specifier = ">=2" }, | ||||
|     { name = "tokenize-rt", marker = "extra == 'jupyter'", specifier = ">=3.2.0" }, | ||||
|     { name = "tomli", marker = "python_version < '3.11'", specifier = ">=1.1.0" }, | ||||
|     { name = "typing-extensions", marker = "python_version < '3.11'", specifier = ">=4.0.1" }, | ||||
|     { name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=1.1.0" }, | ||||
|     { name = "typing-extensions", marker = "python_full_version < '3.11'", specifier = ">=4.0.1" }, | ||||
|     { name = "uvloop", marker = "extra == 'uvloop'", specifier = ">=0.15.2" }, | ||||
| ] | ||||
| 
 | ||||
|  | @ -368,7 +368,7 @@ dependencies = [ | |||
|     { name = "pygments" }, | ||||
|     { name = "stack-data" }, | ||||
|     { name = "traitlets" }, | ||||
|     { name = "typing-extensions", marker = "python_version < '3.10'" }, | ||||
|     { name = "typing-extensions", marker = "python_full_version < '3.10'" }, | ||||
| ] | ||||
| sdist = { url = "https://files.pythonhosted.org/packages/9e/6a/44ef299b1762f5a73841e87fae8a73a8cc8aee538d6dc8c77a5afe1fd2ce/ipython-8.12.3.tar.gz", hash = "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363", size = 5470171 } | ||||
| wheels = [ | ||||
|  |  | |||
|  | @ -5,8 +5,8 @@ expression: lock | |||
| version = 1 | ||||
| requires-python = ">=3.12" | ||||
| environment-markers = [ | ||||
|     "python_version < '3.13'", | ||||
|     "python_version >= '3.13'", | ||||
|     "python_full_version < '3.13'", | ||||
|     "python_full_version >= '3.13'", | ||||
| ] | ||||
| 
 | ||||
| [options] | ||||
|  |  | |||
|  | @ -1196,7 +1196,7 @@ name = "sqlalchemy" | |||
| version = "2.0.31" | ||||
| source = { registry = "https://pypi.org/simple" } | ||||
| dependencies = [ | ||||
|     { name = "greenlet", marker = "(python_version < '3.13' and platform_machine == 'AMD64') or (python_version < '3.13' and platform_machine == 'WIN32') or (python_version < '3.13' and platform_machine == 'aarch64') or (python_version < '3.13' and platform_machine == 'amd64') or (python_version < '3.13' and platform_machine == 'ppc64le') or (python_version < '3.13' and platform_machine == 'win32') or (python_version < '3.13' and platform_machine == 'x86_64')" }, | ||||
|     { name = "greenlet", marker = "(python_full_version < '3.13' and platform_machine == 'AMD64') or (python_full_version < '3.13' and platform_machine == 'WIN32') or (python_full_version < '3.13' and platform_machine == 'aarch64') or (python_full_version < '3.13' and platform_machine == 'amd64') or (python_full_version < '3.13' and platform_machine == 'ppc64le') or (python_full_version < '3.13' and platform_machine == 'win32') or (python_full_version < '3.13' and platform_machine == 'x86_64')" }, | ||||
|     { name = "typing-extensions" }, | ||||
| ] | ||||
| sdist = { url = "https://files.pythonhosted.org/packages/ba/7d/e3312ae374fe7a4af7e1494735125a714a0907317c829ab8d8a31d89ded4/SQLAlchemy-2.0.31.tar.gz", hash = "sha256:b607489dd4a54de56984a0c7656247504bd5523d9d0ba799aef59d4add009484", size = 9524110 } | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -3,11 +3,12 @@ source: crates/uv/tests/ecosystem.rs | |||
| expression: lock | ||||
| --- | ||||
| version = 1 | ||||
| requires-python = ">=3.11, <3.12" | ||||
| requires-python = "==3.11.*" | ||||
| environment-markers = [ | ||||
|     "python_version < '3.12'", | ||||
|     "python_version < '3.13'", | ||||
|     "python_version >= '3.13'", | ||||
|     "python_full_version < '3.12'", | ||||
|     "python_full_version < '3.13'", | ||||
|     "python_full_version >= '3.13' and python_full_version < '4'", | ||||
|     "python_full_version >= '4'", | ||||
| ] | ||||
| 
 | ||||
| [options] | ||||
|  | @ -194,7 +195,7 @@ dependencies = [ | |||
|     { name = "annotated-types" }, | ||||
|     { name = "logfury" }, | ||||
|     { name = "requests" }, | ||||
|     { name = "typing-extensions", marker = "python_version < '3.12'" }, | ||||
|     { name = "typing-extensions", marker = "python_full_version < '3.12'" }, | ||||
| ] | ||||
| sdist = { url = "https://files.pythonhosted.org/packages/ce/53/2b4ac6ef318444bde570c36219ff0c8cd2207fb2fd8183d88fdf4f0445ab/b2sdk-2.5.0.tar.gz", hash = "sha256:d7c20125e64508a730e56307d75284790079cdb88e63851fff820a09b24fb1d9", size = 203212 } | ||||
| wheels = [ | ||||
|  | @ -321,7 +322,7 @@ source = { registry = "https://pypi.org/simple" } | |||
| dependencies = [ | ||||
|     { name = "botocore-stubs" }, | ||||
|     { name = "types-s3transfer" }, | ||||
|     { name = "typing-extensions", marker = "python_version < '3.12'" }, | ||||
|     { name = "typing-extensions", marker = "python_full_version < '3.12'" }, | ||||
| ] | ||||
| sdist = { url = "https://files.pythonhosted.org/packages/6e/d6/da4a554a6436944cb47cfb84754e8a2e37b04e3ff6dfea3c4958e2eb93ed/boto3_stubs-1.34.156.tar.gz", hash = "sha256:c34220a00b6bd00a3cd326bc5d7e3296b7d1dab1a15660df6f8fba4ae307ff39", size = 88866 } | ||||
| wheels = [ | ||||
|  | @ -3143,7 +3144,7 @@ name = "redis" | |||
| version = "5.0.8" | ||||
| source = { registry = "https://pypi.org/simple" } | ||||
| dependencies = [ | ||||
|     { name = "async-timeout", marker = "python_full_version < '3.11.[X]' and python_version < '3.12'" }, | ||||
|     { name = "async-timeout", marker = "python_full_version < '3.11.[X]'" }, | ||||
| ] | ||||
| sdist = { url = "https://files.pythonhosted.org/packages/48/10/defc227d65ea9c2ff5244645870859865cba34da7373477c8376629746ec/redis-5.0.8.tar.gz", hash = "sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870", size = 4595651 } | ||||
| wheels = [ | ||||
|  | @ -3643,7 +3644,7 @@ name = "sqlalchemy" | |||
| version = "2.0.32" | ||||
| source = { registry = "https://pypi.org/simple" } | ||||
| dependencies = [ | ||||
|     { name = "greenlet", marker = "(python_version < '3.13' and platform_machine == 'AMD64') or (python_version < '3.13' and platform_machine == 'WIN32') or (python_version < '3.13' and platform_machine == 'aarch64') or (python_version < '3.13' and platform_machine == 'amd64') or (python_version < '3.13' and platform_machine == 'ppc64le') or (python_version < '3.13' and platform_machine == 'win32') or (python_version < '3.13' and platform_machine == 'x86_64')" }, | ||||
|     { name = "greenlet", marker = "(python_full_version < '3.13' and platform_machine == 'AMD64') or (python_full_version < '3.13' and platform_machine == 'WIN32') or (python_full_version < '3.13' and platform_machine == 'aarch64') or (python_full_version < '3.13' and platform_machine == 'amd64') or (python_full_version < '3.13' and platform_machine == 'ppc64le') or (python_full_version < '3.13' and platform_machine == 'win32') or (python_full_version < '3.13' and platform_machine == 'x86_64')" }, | ||||
|     { name = "typing-extensions" }, | ||||
| ] | ||||
| sdist = { url = "https://files.pythonhosted.org/packages/af/6f/967e987683908af816aa3072c1a6997ac9933cf38d66b0474fb03f253323/SQLAlchemy-2.0.32.tar.gz", hash = "sha256:c1b88cc8b02b6a5f0efb0345a03672d4c897dc7d92585176f88c67346f565ea8", size = 9546691 } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ibraheem Ahmed
						Ibraheem Ahmed