Compare major-minor specifiers when filtering interpreters (#11952)

## Summary

If we're looking at (e.g.) `python3.12`, and we have a `requires-python:
">=3.12.7, <3.13"`, then checking if the range includes `3.12` will
return `false`. Instead, we need to look at the lower- and upper-bound
major-minors of the `requires-python`.

Closes https://github.com/astral-sh/uv/issues/11825.
This commit is contained in:
Charlie Marsh 2025-03-04 15:29:39 -08:00 committed by GitHub
parent 6578885a45
commit 3a53ec3c5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 65 additions and 2 deletions

View file

@ -12,7 +12,10 @@ use which::{which, which_all};
use uv_cache::Cache;
use uv_fs::which::is_executable;
use uv_fs::Simplified;
use uv_pep440::{Prerelease, Version, VersionSpecifier, VersionSpecifiers};
use uv_pep440::{
release_specifiers_to_ranges, LowerBound, Prerelease, UpperBound, Version, VersionSpecifier,
VersionSpecifiers,
};
use uv_static::EnvVars;
use uv_warnings::warn_user_once;
@ -2178,7 +2181,23 @@ impl VersionRequest {
(*self_major, *self_minor) == (major, minor)
}
Self::Range(specifiers, _) => {
specifiers.contains(&Version::new([u64::from(major), u64::from(minor)]))
let range = release_specifiers_to_ranges(specifiers.clone());
let Some((lower, upper)) = range.bounding_range() else {
return true;
};
let version = Version::new([u64::from(major), u64::from(minor)]);
let lower = LowerBound::new(lower.cloned());
if !lower.major_minor().contains(&version) {
return false;
}
let upper = UpperBound::new(upper.cloned());
if !upper.major_minor().contains(&version) {
return false;
}
true
}
Self::MajorMinorPrerelease(self_major, self_minor, _, _) => {
(*self_major, *self_minor) == (major, minor)