Filter out none ABI wheels with mismatched Python versions (#5087)

## Summary

`echo "torch==1.10.0" | cargo run pip compile - -p 3.12 --no-deps` now
correctly fails. Previously, we were accepting the wheel
`torch-1.10.0-cp36-none-macosx_10_9_x86_64.whl` as compatible with
Python 3.10 due to the `none` ABI.

Closes https://github.com/astral-sh/uv/issues/5085.
This commit is contained in:
Charlie Marsh 2024-07-15 21:41:13 -04:00 committed by GitHub
parent 9a44bc1d35
commit 816d70cd23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -67,18 +67,30 @@ impl WheelFilename {
/// sensitivity, we return `true` if the tags are unknown. /// sensitivity, we return `true` if the tags are unknown.
pub fn matches_requires_python(&self, specifiers: &VersionSpecifiers) -> bool { pub fn matches_requires_python(&self, specifiers: &VersionSpecifiers) -> bool {
self.abi_tag.iter().any(|abi_tag| { self.abi_tag.iter().any(|abi_tag| {
if abi_tag == "abi3" || abi_tag == "none" { if abi_tag == "abi3" {
if self
.python_tag
.iter()
.all(|python_tag| python_tag.starts_with("py2"))
{
// Remove `py2-none-any` and `py27-none-any`.
false
} else {
// Universal tags are allowed. // Universal tags are allowed.
true true
} else if abi_tag == "none" {
self.python_tag.iter().any(|python_tag| {
// Remove `py2-none-any` and `py27-none-any`.
if python_tag.starts_with("py2") {
return false;
} }
// Remove (e.g.) `cp36-none-any` if the specifier is `==3.10.*`.
let Some(minor) = python_tag
.strip_prefix("cp3")
.or_else(|| python_tag.strip_prefix("pp3"))
.or_else(|| python_tag.strip_prefix("py3"))
else {
return true;
};
let Ok(minor) = minor.parse::<u64>() else {
return true;
};
let version = Version::new([3, minor]);
specifiers.contains(&version)
})
} else if abi_tag.starts_with("cp2") || abi_tag.starts_with("pypy2") { } else if abi_tag.starts_with("cp2") || abi_tag.starts_with("pypy2") {
// Python 2 is never allowed. // Python 2 is never allowed.
false false
@ -392,13 +404,17 @@ mod tests {
let wheel_names = &[ let wheel_names = &[
"bcrypt-4.1.3-cp37-abi3-macosx_10_12_universal2.whl", "bcrypt-4.1.3-cp37-abi3-macosx_10_12_universal2.whl",
"black-24.4.2-cp310-cp310-win_amd64.whl", "black-24.4.2-cp310-cp310-win_amd64.whl",
"black-24.4.2-cp310-none-win_amd64.whl",
"cbor2-5.6.4-py3-none-any.whl", "cbor2-5.6.4-py3-none-any.whl",
"watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl",
]; ];
for wheel_name in wheel_names { for wheel_name in wheel_names {
assert!(WheelFilename::from_str(wheel_name) assert!(
WheelFilename::from_str(wheel_name)
.unwrap() .unwrap()
.matches_requires_python(&version_specifiers)); .matches_requires_python(&version_specifiers),
"{wheel_name}"
);
} }
} }
@ -410,11 +426,16 @@ mod tests {
"black-24.4.2-cp39-cp39-win_amd64.whl", "black-24.4.2-cp39-cp39-win_amd64.whl",
"psutil-6.0.0-cp36-cp36m-win32.whl", "psutil-6.0.0-cp36-cp36m-win32.whl",
"pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl",
"torch-1.10.0-cp36-none-macosx_10_9_x86_64.whl",
"torch-1.10.0-py36-none-macosx_10_9_x86_64.whl",
]; ];
for wheel_name in wheel_names { for wheel_name in wheel_names {
assert!(!WheelFilename::from_str(wheel_name) assert!(
!WheelFilename::from_str(wheel_name)
.unwrap() .unwrap()
.matches_requires_python(&version_specifiers)); .matches_requires_python(&version_specifiers),
"{wheel_name}"
);
} }
} }
} }