Add prerelease compatibility check (#8020)

## Summary

Closes #7977. Makes `PythonDownloadRequest` account for the prerelease
part if allowed. Also stores the prerelease in `PythonInstallationKey`
directly as a `Prerelease` rather than a string.

## Test Plan

Correctly picks the relevant prerelease (rather than picking the most
recent one):
```
λ cargo run python install 3.13.0rc2
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s
     Running `target/debug/uv python install 3.13.0rc2`
Searching for Python versions matching: Python 3.13rc2
cpython-3.13.0rc2-macos-aarch64-none ------------------------------ 457.81 KiB/14.73 MiB                                                                                                                    ^C

λ cargo run python install 3.13.0rc3                 
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s
     Running `target/debug/uv python install 3.13.0rc3`
Searching for Python versions matching: Python 3.13rc3
Found existing installation for Python 3.13rc3: cpython-3.13.0rc3-macos-aarch64-none
```
This commit is contained in:
trag1c
2024-10-08 23:20:58 +02:00
committed by GitHub
parent cfaa834dee
commit 37273cb4bc
7 changed files with 794 additions and 768 deletions
+14 -8
View File
@@ -1,4 +1,3 @@
use std::borrow::Cow;
use std::fmt;
use std::str::FromStr;
@@ -6,7 +5,7 @@ use tracing::{debug, info};
use uv_cache::Cache;
use uv_client::BaseClientBuilder;
use uv_pep440::Version;
use uv_pep440::{Prerelease, Version};
use crate::discovery::{
find_best_python_installation, find_python_installation, EnvironmentPreference, PythonRequest,
@@ -224,7 +223,7 @@ pub struct PythonInstallationKey {
pub(crate) major: u8,
pub(crate) minor: u8,
pub(crate) patch: u8,
pub(crate) prerelease: Cow<'static, str>,
pub(crate) prerelease: Option<Prerelease>,
pub(crate) os: Os,
pub(crate) arch: Arch,
pub(crate) libc: Libc,
@@ -236,7 +235,7 @@ impl PythonInstallationKey {
major: u8,
minor: u8,
patch: u8,
prerelease: String,
prerelease: Option<Prerelease>,
os: Os,
arch: Arch,
libc: Libc,
@@ -246,7 +245,7 @@ impl PythonInstallationKey {
major,
minor,
patch,
prerelease: Cow::Owned(prerelease),
prerelease,
os,
arch,
libc,
@@ -265,7 +264,7 @@ impl PythonInstallationKey {
major: version.major(),
minor: version.minor(),
patch: version.patch().unwrap_or_default(),
prerelease: Cow::Owned(version.pre().map(|pre| pre.to_string()).unwrap_or_default()),
prerelease: version.pre(),
os,
arch,
libc,
@@ -279,7 +278,12 @@ impl PythonInstallationKey {
pub fn version(&self) -> PythonVersion {
PythonVersion::from_str(&format!(
"{}.{}.{}{}",
self.major, self.minor, self.patch, self.prerelease
self.major,
self.minor,
self.patch,
self.prerelease
.map(|pre| pre.to_string())
.unwrap_or_default()
))
.expect("Python installation keys must have valid Python versions")
}
@@ -306,7 +310,9 @@ impl fmt::Display for PythonInstallationKey {
self.major,
self.minor,
self.patch,
self.prerelease,
self.prerelease
.map(|pre| pre.to_string())
.unwrap_or_default(),
self.os,
self.arch,
self.libc