From 7a119ee4c2c5acfe6912fe7f1776df9fe58e5ac7 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 12 Mar 2024 19:41:54 -0400 Subject: [PATCH] Preserve given version --- crates/pep508-rs/src/marker.rs | 2 +- crates/uv-interpreter/src/interpreter.rs | 8 +++++++- crates/uv-interpreter/src/python_version.rs | 6 ++++-- crates/uv-resolver/src/error.rs | 5 +++-- crates/uv-resolver/src/python_requirement.rs | 17 ++++++++--------- crates/uv-resolver/src/resolver/mod.rs | 5 +++-- crates/uv/tests/pip_compile.rs | 8 ++++---- crates/uv/tests/pip_compile_scenarios.rs | 6 +++--- 8 files changed, 33 insertions(+), 24 deletions(-) diff --git a/crates/pep508-rs/src/marker.rs b/crates/pep508-rs/src/marker.rs index 97289b088cb60..9764099a24fc3 100644 --- a/crates/pep508-rs/src/marker.rs +++ b/crates/pep508-rs/src/marker.rs @@ -319,7 +319,7 @@ impl FromStr for StringVersion { impl Display for StringVersion { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - self.version.fmt(f) + self.string.fmt(f) } } diff --git a/crates/uv-interpreter/src/interpreter.rs b/crates/uv-interpreter/src/interpreter.rs index 6ff3c326d7d52..ad7b8c7e59ba6 100644 --- a/crates/uv-interpreter/src/interpreter.rs +++ b/crates/uv-interpreter/src/interpreter.rs @@ -11,7 +11,7 @@ use tracing::{debug, warn}; use cache_key::digest; use install_wheel_rs::Layout; use pep440_rs::Version; -use pep508_rs::MarkerEnvironment; +use pep508_rs::{MarkerEnvironment, StringVersion}; use platform_host::Platform; use platform_tags::{Tags, TagsError}; use pypi_types::Scheme; @@ -182,6 +182,12 @@ impl Interpreter { &self.markers.python_full_version.version } + /// Returns the `python_full_version` marker corresponding to this Python version. + #[inline] + pub const fn python_full_version(&self) -> &StringVersion { + &self.markers.python_full_version + } + /// Return the major version of this Python version. pub fn python_major(&self) -> u8 { let major = self.markers.python_full_version.version.release()[0]; diff --git a/crates/uv-interpreter/src/python_version.rs b/crates/uv-interpreter/src/python_version.rs index cd1b9a73d71bf..63b5cad057aea 100644 --- a/crates/uv-interpreter/src/python_version.rs +++ b/crates/uv-interpreter/src/python_version.rs @@ -62,7 +62,8 @@ impl PythonVersion { if markers.implementation_name == "cpython" { let python_full_version = self.python_full_version(); markers.implementation_version = StringVersion { - string: python_full_version.to_string(), + // Retain the verbatim representation, provided by the user. + string: self.0.to_string(), version: python_full_version, }; } @@ -70,7 +71,8 @@ impl PythonVersion { // Ex) `python_full_version == "3.12.0"` let python_full_version = self.python_full_version(); markers.python_full_version = StringVersion { - string: python_full_version.to_string(), + // Retain the verbatim representation, provided by the user. + string: self.0.to_string(), version: python_full_version, }; diff --git a/crates/uv-resolver/src/error.rs b/crates/uv-resolver/src/error.rs index be9d3e59e3622..d83ab963cc48b 100644 --- a/crates/uv-resolver/src/error.rs +++ b/crates/uv-resolver/src/error.rs @@ -1,6 +1,7 @@ use std::collections::BTreeSet; use std::convert::Infallible; use std::fmt::Formatter; +use std::ops::Deref; use dashmap::{DashMap, DashSet}; use indexmap::IndexMap; @@ -190,13 +191,13 @@ impl NoSolutionError { PubGrubPackage::Python(PubGrubPython::Installed) => { available_versions.insert( package.clone(), - BTreeSet::from([python_requirement.installed().clone()]), + BTreeSet::from([python_requirement.installed().deref().clone()]), ); } PubGrubPackage::Python(PubGrubPython::Target) => { available_versions.insert( package.clone(), - BTreeSet::from([python_requirement.target().clone()]), + BTreeSet::from([python_requirement.target().deref().clone()]), ); } PubGrubPackage::Package(name, ..) => { diff --git a/crates/uv-resolver/src/python_requirement.rs b/crates/uv-resolver/src/python_requirement.rs index 80f0b84633daa..8c8aa0cfe03a0 100644 --- a/crates/uv-resolver/src/python_requirement.rs +++ b/crates/uv-resolver/src/python_requirement.rs @@ -1,32 +1,31 @@ -use pep440_rs::Version; -use pep508_rs::MarkerEnvironment; +use pep508_rs::{MarkerEnvironment, StringVersion}; use uv_interpreter::Interpreter; -#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct PythonRequirement { /// The installed version of Python. - installed: Version, + installed: StringVersion, /// The target version of Python; that is, the version of Python for which we are resolving /// dependencies. This is typically the same as the installed version, but may be different /// when specifying an alternate Python version for the resolution. - target: Version, + target: StringVersion, } impl PythonRequirement { pub fn new(interpreter: &Interpreter, markers: &MarkerEnvironment) -> Self { Self { - installed: interpreter.python_version().clone(), - target: markers.python_full_version.version.clone(), + installed: interpreter.python_full_version().clone(), + target: markers.python_full_version.clone(), } } /// Return the installed version of Python. - pub fn installed(&self) -> &Version { + pub fn installed(&self) -> &StringVersion { &self.installed } /// Return the target version of Python. - pub fn target(&self) -> &Version { + pub fn target(&self) -> &StringVersion { &self.target } } diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index a0b1c58e46022..a5ad108c206a4 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::fmt::{Display, Formatter}; +use std::ops::Deref; use std::sync::Arc; use anyhow::Result; @@ -554,7 +555,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> { PubGrubPackage::Python(PubGrubPython::Installed) => { let version = self.python_requirement.installed(); if range.contains(version) { - Ok(Some(ResolverVersion::Available(version.clone()))) + Ok(Some(ResolverVersion::Available(version.deref().clone()))) } else { Ok(None) } @@ -563,7 +564,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> { PubGrubPackage::Python(PubGrubPython::Target) => { let version = self.python_requirement.target(); if range.contains(version) { - Ok(Some(ResolverVersion::Available(version.clone()))) + Ok(Some(ResolverVersion::Available(version.deref().clone()))) } else { Ok(None) } diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index 77695cba74eb1..c48718ebdc127 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -664,9 +664,9 @@ fn compile_python_37() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because the requested Python version (3.7.0) does not satisfy - Python>=3.8 and black==23.10.1 depends on Python>=3.8, we can conclude - that black==23.10.1 cannot be used. + ╰─▶ Because the requested Python version (3.7) does not satisfy Python>=3.8 + and black==23.10.1 depends on Python>=3.8, we can conclude that + black==23.10.1 cannot be used. And because you require black==23.10.1, we can conclude that the requirements are unsatisfiable. "###); @@ -4828,7 +4828,7 @@ requires-python = "<=3.8" ----- stdout ----- ----- stderr ----- - error: Editable `example` requires Python <=3.8, but resolution targets Python 3.11.0 + error: Editable `example` requires Python <=3.8, but resolution targets Python 3.11 "### ); diff --git a/crates/uv/tests/pip_compile_scenarios.rs b/crates/uv/tests/pip_compile_scenarios.rs index b2134c93c418a..b2fe1fbd5b17a 100644 --- a/crates/uv/tests/pip_compile_scenarios.rs +++ b/crates/uv/tests/pip_compile_scenarios.rs @@ -134,7 +134,7 @@ fn compatible_python_incompatible_override() -> Result<()> { ----- stderr ----- warning: The requested Python version 3.9 is not available; 3.11.7 will be used to build dependencies instead. × No solution found when resolving dependencies: - ╰─▶ Because the requested Python version (3.9.0) does not satisfy Python>=3.10 and albatross==1.0.0 depends on Python>=3.10, we can conclude that albatross==1.0.0 cannot be used. + ╰─▶ Because the requested Python version (3.9) does not satisfy Python>=3.10 and albatross==1.0.0 depends on Python>=3.10, we can conclude that albatross==1.0.0 cannot be used. And because you require albatross==1.0.0, we can conclude that the requirements are unsatisfiable. "### ); @@ -379,7 +379,7 @@ fn incompatible_python_compatible_override_other_wheel() -> Result<()> { albatross==2.0.0 we can conclude that albatross<2.0.0 cannot be used. (1) - Because the requested Python version (3.11.0) does not satisfy Python>=3.12 and albatross==2.0.0 depends on Python>=3.12, we can conclude that albatross==2.0.0 cannot be used. + Because the requested Python version (3.11) does not satisfy Python>=3.12 and albatross==2.0.0 depends on Python>=3.12, we can conclude that albatross==2.0.0 cannot be used. And because we know from (1) that albatross<2.0.0 cannot be used, we can conclude that all versions of albatross cannot be used. And because you require albatross, we can conclude that the requirements are unsatisfiable. "### @@ -428,7 +428,7 @@ fn python_patch_override_no_patch() -> Result<()> { ----- stderr ----- × No solution found when resolving dependencies: - ╰─▶ Because the requested Python version (3.8.0) does not satisfy Python>=3.8.4 and albatross==1.0.0 depends on Python>=3.8.4, we can conclude that albatross==1.0.0 cannot be used. + ╰─▶ Because the requested Python version (3.8) does not satisfy Python>=3.8.4 and albatross==1.0.0 depends on Python>=3.8.4, we can conclude that albatross==1.0.0 cannot be used. And because you require albatross==1.0.0, we can conclude that the requirements are unsatisfiable. "### );