mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-17 18:57:30 +00:00
Fix handling of Python requests with pre-releases in ranges
This commit is contained in:
parent
24ebdf02c0
commit
fb7d5361b0
2 changed files with 122 additions and 2 deletions
|
|
@ -2,6 +2,7 @@ use itertools::{Either, Itertools};
|
|||
use regex::Regex;
|
||||
use rustc_hash::{FxBuildHasher, FxHashSet};
|
||||
use same_file::is_same_file;
|
||||
use std::borrow::Cow;
|
||||
use std::env::consts::EXE_SUFFIX;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::{env, io, iter};
|
||||
|
|
@ -2692,7 +2693,16 @@ impl VersionRequest {
|
|||
&& variant.matches_interpreter(interpreter)
|
||||
}
|
||||
Self::Range(specifiers, variant) => {
|
||||
let version = interpreter.python_version().only_release();
|
||||
// If the specifier contains pre-releases, use the full version for comparison.
|
||||
// Otherwise, strip pre-release so that, e.g., `>=3.14` matches `3.14.0rc3`.
|
||||
let version = if specifiers
|
||||
.iter()
|
||||
.any(uv_pep440::VersionSpecifier::any_prerelease)
|
||||
{
|
||||
Cow::Borrowed(interpreter.python_version())
|
||||
} else {
|
||||
Cow::Owned(interpreter.python_version().only_release())
|
||||
};
|
||||
specifiers.contains(&version) && variant.matches_interpreter(interpreter)
|
||||
}
|
||||
Self::MajorMinorPrerelease(major, minor, prerelease, variant) => {
|
||||
|
|
@ -2725,7 +2735,19 @@ impl VersionRequest {
|
|||
(version.major(), version.minor(), version.patch())
|
||||
== (*major, *minor, Some(*patch))
|
||||
}
|
||||
Self::Range(specifiers, _) => specifiers.contains(&version.version.only_release()),
|
||||
Self::Range(specifiers, _) => {
|
||||
// If the specifier contains pre-releases, use the full version for comparison.
|
||||
// Otherwise, strip pre-release so that, e.g., `>=3.14` matches `3.14.0rc3`.
|
||||
let version = if specifiers
|
||||
.iter()
|
||||
.any(uv_pep440::VersionSpecifier::any_prerelease)
|
||||
{
|
||||
Cow::Borrowed(&version.version)
|
||||
} else {
|
||||
Cow::Owned(version.version.only_release())
|
||||
};
|
||||
specifiers.contains(&version)
|
||||
}
|
||||
Self::MajorMinorPrerelease(major, minor, prerelease, _) => {
|
||||
(version.major(), version.minor(), version.pre())
|
||||
== (*major, *minor, Some(*prerelease))
|
||||
|
|
|
|||
|
|
@ -1335,3 +1335,101 @@ fn python_find_freethreaded_314() {
|
|||
----- stderr -----
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn python_find_prerelease_version_specifiers() {
|
||||
let context: TestContext = TestContext::new_with_versions(&[])
|
||||
.with_filtered_python_keys()
|
||||
.with_filtered_python_sources()
|
||||
.with_managed_python_dirs()
|
||||
.with_python_download_cache()
|
||||
.with_filtered_python_install_bin()
|
||||
.with_filtered_python_names()
|
||||
.with_filtered_exe_suffix();
|
||||
|
||||
context.python_install().arg("3.14.0rc2").assert().success();
|
||||
context.python_install().arg("3.14.0rc3").assert().success();
|
||||
|
||||
// `>=3.14` should allow pre-release versions
|
||||
uv_snapshot!(context.filters(), context.python_find().arg(">=3.14"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
[TEMP_DIR]/managed/cpython-3.14.0rc3-[PLATFORM]/[INSTALL-BIN]/[PYTHON]
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
|
||||
// `>3.14rc2` should not match rc2
|
||||
uv_snapshot!(context.filters(), context.python_find().arg(">3.14.0rc2"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
[TEMP_DIR]/managed/cpython-3.14.0rc3-[PLATFORM]/[INSTALL-BIN]/[PYTHON]
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
|
||||
// `>3.14rc3` should not match rc3
|
||||
uv_snapshot!(context.filters(), context.python_find().arg(">3.14.0rc3"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: No interpreter found for Python >3.14.0rc3 in [PYTHON SOURCES]
|
||||
");
|
||||
|
||||
// `>=3.14.0rc3` should match rc3
|
||||
uv_snapshot!(context.filters(), context.python_find().arg(">=3.14.0rc3"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
[TEMP_DIR]/managed/cpython-3.14.0rc3-[PLATFORM]/[INSTALL-BIN]/[PYTHON]
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
|
||||
// `<3.14.0rc3` should match rc2
|
||||
uv_snapshot!(context.filters(), context.python_find().arg("<3.14.0rc3"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
[TEMP_DIR]/managed/cpython-3.14.0rc2-[PLATFORM]/[INSTALL-BIN]/[PYTHON]
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
|
||||
// `<=3.14.0rc3` should match rc3
|
||||
uv_snapshot!(context.filters(), context.python_find().arg("<=3.14.0rc3"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
[TEMP_DIR]/managed/cpython-3.14.0rc3-[PLATFORM]/[INSTALL-BIN]/[PYTHON]
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
|
||||
// Install the stable version
|
||||
context.python_install().arg("3.14.0").assert().success();
|
||||
|
||||
// `>=3.14` should prefer stable
|
||||
uv_snapshot!(context.filters(), context.python_find().arg(">=3.14"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
[TEMP_DIR]/managed/cpython-3.14.0-[PLATFORM]/[INSTALL-BIN]/[PYTHON]
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
|
||||
// `>3.14rc2` should prefer stable
|
||||
uv_snapshot!(context.filters(), context.python_find().arg(">3.14.0rc2"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
[TEMP_DIR]/managed/cpython-3.14.0-[PLATFORM]/[INSTALL-BIN]/[PYTHON]
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue