From 891c91dd3a0141f05adea20674f3ea7f4477c510 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Wed, 2 Oct 2024 13:10:45 -0500 Subject: [PATCH] Use an enum for free-threaded Python requests (#7871) Follow-up to #7431 improving readability --- crates/uv-python/src/discovery.rs | 164 ++++++++++++++----------- crates/uv-python/src/downloads.rs | 2 +- crates/uv-python/src/lib.rs | 2 +- crates/uv/src/commands/build.rs | 7 +- crates/uv/src/commands/project/add.rs | 7 +- crates/uv/src/commands/project/init.rs | 34 +++-- crates/uv/src/commands/project/mod.rs | 8 +- crates/uv/src/commands/project/run.rs | 7 +- crates/uv/src/commands/python/find.rs | 9 +- crates/uv/src/commands/venv.rs | 7 +- 10 files changed, 150 insertions(+), 97 deletions(-) diff --git a/crates/uv-python/src/discovery.rs b/crates/uv-python/src/discovery.rs index 3abb060212dd..636ff0f94d66 100644 --- a/crates/uv-python/src/discovery.rs +++ b/crates/uv-python/src/discovery.rs @@ -132,6 +132,13 @@ pub enum EnvironmentPreference { Any, } +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum PythonVariant { + #[default] + Default, + Freethreaded, +} + /// A Python discovery version request. #[derive(Clone, Debug, Default, PartialEq, Eq)] pub enum VersionRequest { @@ -140,11 +147,11 @@ pub enum VersionRequest { Default, /// Allow any Python version. Any, - Major(u8, bool), - MajorMinor(u8, u8, bool), - MajorMinorPatch(u8, u8, u8, bool), - MajorMinorPrerelease(u8, u8, Prerelease, bool), - Range(VersionSpecifiers, bool), + Major(u8, PythonVariant), + MajorMinor(u8, u8, PythonVariant), + MajorMinorPatch(u8, u8, u8, PythonVariant), + MajorMinorPrerelease(u8, u8, Prerelease, PythonVariant), + Range(VersionSpecifiers, PythonVariant), } /// The result of an Python installation search. @@ -1540,7 +1547,7 @@ pub(crate) struct ExecutableName { minor: Option, patch: Option, prerelease: Option, - free_threaded: bool, + variant: PythonVariant, } impl ExecutableName { @@ -1575,8 +1582,8 @@ impl ExecutableName { } #[must_use] - fn with_free_threaded(mut self, free_threaded: bool) -> Self { - self.free_threaded = free_threaded; + fn with_variant(mut self, variant: PythonVariant) -> Self { + self.variant = variant; self } } @@ -1589,7 +1596,7 @@ impl Default for ExecutableName { minor: None, patch: None, prerelease: None, - free_threaded: false, + variant: PythonVariant::Default, } } } @@ -1609,9 +1616,12 @@ impl std::fmt::Display for ExecutableName { if let Some(prerelease) = &self.prerelease { write!(f, "{prerelease}")?; } - if self.free_threaded { - f.write_str("t")?; - } + match self.variant { + PythonVariant::Default => {} + PythonVariant::Freethreaded => { + f.write_str("t")?; + } + }; f.write_str(std::env::consts::EXE_SUFFIX)?; Ok(()) } @@ -1691,9 +1701,9 @@ impl VersionRequest { } // Include free-threaded variants - if self.is_free_threaded_requested() { + if self.is_freethreaded() { for i in 0..names.len() { - let name = names[i].with_free_threaded(true); + let name = names[i].with_variant(PythonVariant::Freethreaded); names.push(name); } } @@ -1766,7 +1776,7 @@ impl VersionRequest { Self::Range(_, _) => (), } - if self.is_free_threaded_requested() { + if self.is_freethreaded() { if let Self::MajorMinor(major, minor, _) = self.clone().without_patch() { if (major, minor) < (3, 13) { return Err(format!( @@ -1781,7 +1791,7 @@ impl VersionRequest { /// Check if a interpreter matches the requested Python version. pub(crate) fn matches_interpreter(&self, interpreter: &Interpreter) -> bool { - if self.is_free_threaded_requested() && !interpreter.gil_disabled() { + if self.is_freethreaded() && !interpreter.gil_disabled() { return false; } match self { @@ -1895,15 +1905,13 @@ impl VersionRequest { match self { Self::Default => Self::Default, Self::Any => Self::Any, - Self::Major(major, free_threaded) => Self::Major(major, free_threaded), - Self::MajorMinor(major, minor, free_threaded) => { - Self::MajorMinor(major, minor, free_threaded) - } - Self::MajorMinorPatch(major, minor, _, free_threaded) => { - Self::MajorMinor(major, minor, free_threaded) + Self::Major(major, variant) => Self::Major(major, variant), + Self::MajorMinor(major, minor, variant) => Self::MajorMinor(major, minor, variant), + Self::MajorMinorPatch(major, minor, _, variant) => { + Self::MajorMinor(major, minor, variant) } - Self::MajorMinorPrerelease(major, minor, prerelease, free_threaded) => { - Self::MajorMinorPrerelease(major, minor, prerelease, free_threaded) + Self::MajorMinorPrerelease(major, minor, prerelease, variant) => { + Self::MajorMinorPrerelease(major, minor, prerelease, variant) } Self::Range(_, _) => self, } @@ -1922,14 +1930,14 @@ impl VersionRequest { } } - pub(crate) fn is_free_threaded_requested(&self) -> bool { + pub(crate) fn is_freethreaded(&self) -> bool { match self { Self::Any | Self::Default => false, - Self::Major(_, free_threaded) => *free_threaded, - Self::MajorMinor(_, _, free_threaded) => *free_threaded, - Self::MajorMinorPatch(_, _, _, free_threaded) => *free_threaded, - Self::MajorMinorPrerelease(_, _, _, free_threaded) => *free_threaded, - Self::Range(_, free_threaded) => *free_threaded, + Self::Major(_, variant) + | Self::MajorMinor(_, _, variant) + | Self::MajorMinorPatch(_, _, _, variant) + | Self::MajorMinorPrerelease(_, _, _, variant) + | Self::Range(_, variant) => variant == &PythonVariant::Freethreaded, } } } @@ -1939,15 +1947,19 @@ impl FromStr for VersionRequest { fn from_str(s: &str) -> Result { // Check if the version request is for a free-threaded Python version - let (s, free_threaded) = s.strip_suffix('t').map_or((s, false), |s| (s, true)); + let (s, variant) = s + .strip_suffix('t') + .map_or((s, PythonVariant::Default), |s| { + (s, PythonVariant::Freethreaded) + }); - if free_threaded && s.ends_with('t') { + if variant == PythonVariant::Freethreaded && s.ends_with('t') { // More than one trailing "t" is not allowed return Err(Error::InvalidVersionRequest(format!("{s}t"))); } let Ok(version) = Version::from_str(s) else { - return parse_version_specifiers_request(s, free_threaded); + return parse_version_specifiers_request(s, variant); }; // Split the release component if it uses the wheel tag format (e.g., `38`) @@ -1972,19 +1984,16 @@ impl FromStr for VersionRequest { if prerelease.is_some() { return Err(Error::InvalidVersionRequest(s.to_string())); } - Ok(Self::Major(*major, free_threaded)) + Ok(Self::Major(*major, variant)) } // e.g. `3.12` or `312` or `3.13rc1` [major, minor] => { if let Some(prerelease) = prerelease { return Ok(Self::MajorMinorPrerelease( - *major, - *minor, - prerelease, - free_threaded, + *major, *minor, prerelease, variant, )); } - Ok(Self::MajorMinor(*major, *minor, free_threaded)) + Ok(Self::MajorMinor(*major, *minor, variant)) } // e.g. `3.12.1` or `3.13.0rc1` [major, minor, patch] => { @@ -1995,27 +2004,27 @@ impl FromStr for VersionRequest { return Err(Error::InvalidVersionRequest(s.to_string())); } return Ok(Self::MajorMinorPrerelease( - *major, - *minor, - prerelease, - free_threaded, + *major, *minor, prerelease, variant, )); } - Ok(Self::MajorMinorPatch(*major, *minor, *patch, free_threaded)) + Ok(Self::MajorMinorPatch(*major, *minor, *patch, variant)) } _ => Err(Error::InvalidVersionRequest(s.to_string())), } } } -fn parse_version_specifiers_request(s: &str, free_threaded: bool) -> Result { +fn parse_version_specifiers_request( + s: &str, + variant: PythonVariant, +) -> Result { let Ok(specifiers) = VersionSpecifiers::from_str(s) else { return Err(Error::InvalidVersionRequest(s.to_string())); }; if specifiers.is_empty() { return Err(Error::InvalidVersionRequest(s.to_string())); } - Ok(VersionRequest::Range(specifiers, free_threaded)) + Ok(VersionRequest::Range(specifiers, variant)) } impl From<&PythonVersion> for VersionRequest { @@ -2030,20 +2039,22 @@ impl fmt::Display for VersionRequest { match self { Self::Any => f.write_str("any"), Self::Default => f.write_str("default"), - Self::Major(major, false) => write!(f, "{major}"), - Self::Major(major, true) => write!(f, "{major}t"), - Self::MajorMinor(major, minor, false) => write!(f, "{major}.{minor}"), - Self::MajorMinor(major, minor, true) => write!(f, "{major}.{minor}t"), - Self::MajorMinorPatch(major, minor, patch, false) => { + Self::Major(major, PythonVariant::Default) => write!(f, "{major}"), + Self::Major(major, PythonVariant::Freethreaded) => write!(f, "{major}t"), + Self::MajorMinor(major, minor, PythonVariant::Default) => write!(f, "{major}.{minor}"), + Self::MajorMinor(major, minor, PythonVariant::Freethreaded) => { + write!(f, "{major}.{minor}t") + } + Self::MajorMinorPatch(major, minor, patch, PythonVariant::Default) => { write!(f, "{major}.{minor}.{patch}") } - Self::MajorMinorPatch(major, minor, patch, true) => { + Self::MajorMinorPatch(major, minor, patch, PythonVariant::Freethreaded) => { write!(f, "{major}.{minor}.{patch}t") } - Self::MajorMinorPrerelease(major, minor, prerelease, false) => { + Self::MajorMinorPrerelease(major, minor, prerelease, PythonVariant::Default) => { write!(f, "{major}.{minor}{prerelease}") } - Self::MajorMinorPrerelease(major, minor, prerelease, true) => { + Self::MajorMinorPrerelease(major, minor, prerelease, PythonVariant::Freethreaded) => { write!(f, "{major}.{minor}{prerelease}t") } Self::Range(specifiers, _) => write!(f, "{specifiers}"), @@ -2211,7 +2222,7 @@ mod tests { implementation::ImplementationName, }; - use super::Error; + use super::{Error, PythonVariant}; #[test] fn interpreter_request_from_str() { @@ -2492,32 +2503,32 @@ mod tests { fn version_request_from_str() { assert_eq!( VersionRequest::from_str("3").unwrap(), - VersionRequest::Major(3, false) + VersionRequest::Major(3, PythonVariant::Default) ); assert_eq!( VersionRequest::from_str("3.12").unwrap(), - VersionRequest::MajorMinor(3, 12, false) + VersionRequest::MajorMinor(3, 12, PythonVariant::Default) ); assert_eq!( VersionRequest::from_str("3.12.1").unwrap(), - VersionRequest::MajorMinorPatch(3, 12, 1, false) + VersionRequest::MajorMinorPatch(3, 12, 1, PythonVariant::Default) ); assert!(VersionRequest::from_str("1.foo.1").is_err()); assert_eq!( VersionRequest::from_str("3").unwrap(), - VersionRequest::Major(3, false) + VersionRequest::Major(3, PythonVariant::Default) ); assert_eq!( VersionRequest::from_str("38").unwrap(), - VersionRequest::MajorMinor(3, 8, false) + VersionRequest::MajorMinor(3, 8, PythonVariant::Default) ); assert_eq!( VersionRequest::from_str("312").unwrap(), - VersionRequest::MajorMinor(3, 12, false) + VersionRequest::MajorMinor(3, 12, PythonVariant::Default) ); assert_eq!( VersionRequest::from_str("3100").unwrap(), - VersionRequest::MajorMinor(3, 100, false) + VersionRequest::MajorMinor(3, 100, PythonVariant::Default) ); assert_eq!( VersionRequest::from_str("3.13a1").unwrap(), @@ -2528,7 +2539,7 @@ mod tests { kind: PrereleaseKind::Alpha, number: 1 }, - false + PythonVariant::Default ) ); assert_eq!( @@ -2540,7 +2551,7 @@ mod tests { kind: PrereleaseKind::Beta, number: 1 }, - false + PythonVariant::Default ) ); assert_eq!( @@ -2552,7 +2563,7 @@ mod tests { kind: PrereleaseKind::Beta, number: 2 }, - false + PythonVariant::Default ) ); assert_eq!( @@ -2564,7 +2575,7 @@ mod tests { kind: PrereleaseKind::Rc, number: 3 }, - false + PythonVariant::Default ) ); assert!( @@ -2611,27 +2622,36 @@ mod tests { ); assert_eq!( VersionRequest::from_str("3t").unwrap(), - VersionRequest::Major(3, true) + VersionRequest::Major(3, PythonVariant::Freethreaded) ); assert_eq!( VersionRequest::from_str("313t").unwrap(), - VersionRequest::MajorMinor(3, 13, true) + VersionRequest::MajorMinor(3, 13, PythonVariant::Freethreaded) ); assert_eq!( VersionRequest::from_str("3.13t").unwrap(), - VersionRequest::MajorMinor(3, 13, true) + VersionRequest::MajorMinor(3, 13, PythonVariant::Freethreaded) ); assert_eq!( VersionRequest::from_str(">=3.13t").unwrap(), - VersionRequest::Range(VersionSpecifiers::from_str(">=3.13").unwrap(), true) + VersionRequest::Range( + VersionSpecifiers::from_str(">=3.13").unwrap(), + PythonVariant::Freethreaded + ) ); assert_eq!( VersionRequest::from_str(">=3.13").unwrap(), - VersionRequest::Range(VersionSpecifiers::from_str(">=3.13").unwrap(), false) + VersionRequest::Range( + VersionSpecifiers::from_str(">=3.13").unwrap(), + PythonVariant::Default + ) ); assert_eq!( VersionRequest::from_str(">=3.12,<3.14t").unwrap(), - VersionRequest::Range(VersionSpecifiers::from_str(">=3.12,<3.14").unwrap(), true) + VersionRequest::Range( + VersionSpecifiers::from_str(">=3.12,<3.14").unwrap(), + PythonVariant::Freethreaded + ) ); assert!(matches!( VersionRequest::from_str("3.13tt"), diff --git a/crates/uv-python/src/downloads.rs b/crates/uv-python/src/downloads.rs index cdf5e5227823..1c919e89c8f1 100644 --- a/crates/uv-python/src/downloads.rs +++ b/crates/uv-python/src/downloads.rs @@ -264,7 +264,7 @@ impl PythonDownloadRequest { if !version.matches_major_minor_patch(key.major, key.minor, key.patch) { return false; } - if version.is_free_threaded_requested() { + if version.is_freethreaded() { debug!("Installing managed free-threaded Python is not yet supported"); return false; } diff --git a/crates/uv-python/src/lib.rs b/crates/uv-python/src/lib.rs index cb8e99f67f62..fc691ddf751e 100644 --- a/crates/uv-python/src/lib.rs +++ b/crates/uv-python/src/lib.rs @@ -3,7 +3,7 @@ use thiserror::Error; pub use crate::discovery::{ find_python_installations, EnvironmentPreference, Error as DiscoveryError, PythonDownloads, - PythonNotFound, PythonPreference, PythonRequest, PythonSource, VersionRequest, + PythonNotFound, PythonPreference, PythonRequest, PythonSource, PythonVariant, VersionRequest, }; pub use crate::environment::{InvalidEnvironment, InvalidEnvironmentKind, PythonEnvironment}; pub use crate::implementation::ImplementationName; diff --git a/crates/uv/src/commands/build.rs b/crates/uv/src/commands/build.rs index 8f2036b24925..0ecabe614c00 100644 --- a/crates/uv/src/commands/build.rs +++ b/crates/uv/src/commands/build.rs @@ -22,7 +22,7 @@ use uv_fs::Simplified; use uv_normalize::PackageName; use uv_python::{ EnvironmentPreference, PythonDownloads, PythonEnvironment, PythonInstallation, - PythonPreference, PythonRequest, PythonVersionFile, VersionRequest, + PythonPreference, PythonRequest, PythonVariant, PythonVersionFile, VersionRequest, }; use uv_requirements::RequirementsSource; use uv_resolver::{ExcludeNewer, FlatIndex, RequiresPython}; @@ -378,7 +378,10 @@ async fn build_package( .as_ref() .map(RequiresPython::specifiers) .map(|specifiers| { - PythonRequest::Version(VersionRequest::Range(specifiers.clone(), false)) + PythonRequest::Version(VersionRequest::Range( + specifiers.clone(), + PythonVariant::Default, + )) }); } } diff --git a/crates/uv/src/commands/project/add.rs b/crates/uv/src/commands/project/add.rs index be0d628d5a80..d40cc70917c1 100644 --- a/crates/uv/src/commands/project/add.rs +++ b/crates/uv/src/commands/project/add.rs @@ -25,7 +25,7 @@ use uv_pep508::{ExtraName, Requirement, UnnamedRequirement, VersionOrUrl}; use uv_pypi_types::{redact_git_credentials, ParsedUrl, RequirementSource, VerbatimParsedUrl}; use uv_python::{ EnvironmentPreference, Interpreter, PythonDownloads, PythonEnvironment, PythonInstallation, - PythonPreference, PythonRequest, PythonVersionFile, VersionRequest, + PythonPreference, PythonRequest, PythonVariant, PythonVersionFile, VersionRequest, }; use uv_requirements::{NamedRequirementsResolver, RequirementsSource, RequirementsSpecification}; use uv_resolver::FlatIndex; @@ -158,7 +158,10 @@ pub(crate) async fn add( .requires_python .clone() .map(|requires_python| { - PythonRequest::Version(VersionRequest::Range(requires_python, false)) + PythonRequest::Version(VersionRequest::Range( + requires_python, + PythonVariant::Default, + )) }) }; diff --git a/crates/uv/src/commands/project/init.rs b/crates/uv/src/commands/project/init.rs index b4a5ed0ee9ac..79a4a8ffc076 100644 --- a/crates/uv/src/commands/project/init.rs +++ b/crates/uv/src/commands/project/init.rs @@ -13,7 +13,7 @@ use uv_pep440::Version; use uv_pep508::PackageName; use uv_python::{ EnvironmentPreference, PythonDownloads, PythonInstallation, PythonPreference, PythonRequest, - PythonVersionFile, VersionRequest, + PythonVariant, PythonVersionFile, VersionRequest, }; use uv_resolver::RequiresPython; use uv_scripts::{Pep723Script, ScriptTag}; @@ -299,7 +299,11 @@ async fn init_project( let (requires_python, python_request) = if let Some(request) = python.as_deref() { // (1) Explicit request from user match PythonRequest::parse(request) { - PythonRequest::Version(VersionRequest::MajorMinor(major, minor, false)) => { + PythonRequest::Version(VersionRequest::MajorMinor( + major, + minor, + PythonVariant::Default, + )) => { let requires_python = RequiresPython::greater_than_equal_version(&Version::new([ u64::from(major), u64::from(minor), @@ -309,13 +313,20 @@ async fn init_project( None } else { Some(PythonRequest::Version(VersionRequest::MajorMinor( - major, minor, false, + major, + minor, + PythonVariant::Default, ))) }; (requires_python, python_request) } - PythonRequest::Version(VersionRequest::MajorMinorPatch(major, minor, patch, false)) => { + PythonRequest::Version(VersionRequest::MajorMinorPatch( + major, + minor, + patch, + PythonVariant::Default, + )) => { let requires_python = RequiresPython::greater_than_equal_version(&Version::new([ u64::from(major), u64::from(minor), @@ -326,7 +337,10 @@ async fn init_project( None } else { Some(PythonRequest::Version(VersionRequest::MajorMinorPatch( - major, minor, patch, false, + major, + minor, + patch, + PythonVariant::Default, ))) }; @@ -354,7 +368,7 @@ async fn init_project( Some(PythonRequest::Version(VersionRequest::MajorMinor( interpreter.python_major(), interpreter.python_minor(), - false, + PythonVariant::Default, ))) }; @@ -382,7 +396,7 @@ async fn init_project( Some(PythonRequest::Version(VersionRequest::MajorMinor( interpreter.python_major(), interpreter.python_minor(), - false, + PythonVariant::Default, ))) }; @@ -396,7 +410,7 @@ async fn init_project( // (2) `Requires-Python` from the workspace let python_request = PythonRequest::Version(VersionRequest::Range( requires_python.specifiers().clone(), - false, + PythonVariant::Default, )); // Pin to the minor version. @@ -418,7 +432,7 @@ async fn init_project( Some(PythonRequest::Version(VersionRequest::MajorMinor( interpreter.python_major(), interpreter.python_minor(), - false, + PythonVariant::Default, ))) }; @@ -447,7 +461,7 @@ async fn init_project( Some(PythonRequest::Version(VersionRequest::MajorMinor( interpreter.python_major(), interpreter.python_minor(), - false, + PythonVariant::Default, ))) }; diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index 14d8fcf61595..699802b92416 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -23,7 +23,8 @@ use uv_pep508::MarkerTreeContents; use uv_pypi_types::Requirement; use uv_python::{ EnvironmentPreference, Interpreter, InvalidEnvironmentKind, PythonDownloads, PythonEnvironment, - PythonInstallation, PythonPreference, PythonRequest, PythonVersionFile, VersionRequest, + PythonInstallation, PythonPreference, PythonRequest, PythonVariant, PythonVersionFile, + VersionRequest, }; use uv_requirements::upgrade::{read_lock_requirements, LockedRequirements}; use uv_requirements::{ @@ -340,7 +341,10 @@ impl WorkspacePython { .as_ref() .map(RequiresPython::specifiers) .map(|specifiers| { - PythonRequest::Version(VersionRequest::Range(specifiers.clone(), false)) + PythonRequest::Version(VersionRequest::Range( + specifiers.clone(), + PythonVariant::Default, + )) }); let source = PythonRequestSource::RequiresPython; (source, request) diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index d6c94592c9d7..5d7a839ad28f 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -23,7 +23,7 @@ use uv_installer::{SatisfiesResult, SitePackages}; use uv_normalize::PackageName; use uv_python::{ EnvironmentPreference, Interpreter, PythonDownloads, PythonEnvironment, PythonInstallation, - PythonPreference, PythonRequest, PythonVersionFile, VersionRequest, + PythonPreference, PythonRequest, PythonVariant, PythonVersionFile, VersionRequest, }; use uv_requirements::{RequirementsSource, RequirementsSpecification}; use uv_resolver::Lock; @@ -128,7 +128,10 @@ pub(crate) async fn run( .requires_python .as_ref() .map(|requires_python| { - PythonRequest::Version(VersionRequest::Range(requires_python.clone(), false)) + PythonRequest::Version(VersionRequest::Range( + requires_python.clone(), + PythonVariant::Default, + )) }); let source = PythonRequestSource::RequiresPython; (source, request) diff --git a/crates/uv/src/commands/python/find.rs b/crates/uv/src/commands/python/find.rs index 851af7c94100..2b3da29efaa0 100644 --- a/crates/uv/src/commands/python/find.rs +++ b/crates/uv/src/commands/python/find.rs @@ -5,8 +5,8 @@ use std::path::Path; use uv_cache::Cache; use uv_fs::Simplified; use uv_python::{ - EnvironmentPreference, PythonInstallation, PythonPreference, PythonRequest, PythonVersionFile, - VersionRequest, + EnvironmentPreference, PythonInstallation, PythonPreference, PythonRequest, PythonVariant, + PythonVersionFile, VersionRequest, }; use uv_resolver::RequiresPython; use uv_warnings::warn_user_once; @@ -59,7 +59,10 @@ pub(crate) async fn find( .as_ref() .map(RequiresPython::specifiers) .map(|specifiers| { - PythonRequest::Version(VersionRequest::Range(specifiers.clone(), false)) + PythonRequest::Version(VersionRequest::Range( + specifiers.clone(), + PythonVariant::Default, + )) }); } } diff --git a/crates/uv/src/commands/venv.rs b/crates/uv/src/commands/venv.rs index 2598aaa2266b..425c0b5a343c 100644 --- a/crates/uv/src/commands/venv.rs +++ b/crates/uv/src/commands/venv.rs @@ -23,7 +23,7 @@ use uv_install_wheel::linker::LinkMode; use uv_pypi_types::Requirement; use uv_python::{ EnvironmentPreference, PythonDownloads, PythonInstallation, PythonPreference, PythonRequest, - PythonVersionFile, VersionRequest, + PythonVariant, PythonVersionFile, VersionRequest, }; use uv_resolver::{ExcludeNewer, FlatIndex, RequiresPython}; use uv_shell::Shell; @@ -203,7 +203,10 @@ async fn venv_impl( .as_ref() .map(RequiresPython::specifiers) .map(|specifiers| { - PythonRequest::Version(VersionRequest::Range(specifiers.clone(), false)) + PythonRequest::Version(VersionRequest::Range( + specifiers.clone(), + PythonVariant::Default, + )) }); } }