mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Filter out invalid wheels based on requires-python
(#5084)
## Summary The example in the linked issue doesn't quite work, but I think it has to do with the existing filtering logic. Will follow-up separately. Closes https://github.com/astral-sh/uv/issues/5012.
This commit is contained in:
parent
14a1ea460d
commit
9a44bc1d35
3 changed files with 26 additions and 3 deletions
|
@ -154,6 +154,9 @@ impl<'a, Context: BuildContext, InstalledPackages: InstalledPackagesProvider>
|
||||||
database,
|
database,
|
||||||
flat_index,
|
flat_index,
|
||||||
tags,
|
tags,
|
||||||
|
python_requirement
|
||||||
|
.target()
|
||||||
|
.and_then(|target| target.as_requires_python()),
|
||||||
AllowedYanks::from_manifest(&manifest, markers, options.dependency_mode),
|
AllowedYanks::from_manifest(&manifest, markers, options.dependency_mode),
|
||||||
hasher,
|
hasher,
|
||||||
options.exclude_newer,
|
options.exclude_newer,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use uv_types::{BuildContext, HashStrategy};
|
||||||
use crate::flat_index::FlatIndex;
|
use crate::flat_index::FlatIndex;
|
||||||
use crate::version_map::VersionMap;
|
use crate::version_map::VersionMap;
|
||||||
use crate::yanks::AllowedYanks;
|
use crate::yanks::AllowedYanks;
|
||||||
use crate::ExcludeNewer;
|
use crate::{ExcludeNewer, RequiresPython};
|
||||||
|
|
||||||
pub type PackageVersionsResult = Result<VersionsResponse, uv_client::Error>;
|
pub type PackageVersionsResult = Result<VersionsResponse, uv_client::Error>;
|
||||||
pub type WheelMetadataResult = Result<MetadataResponse, uv_distribution::Error>;
|
pub type WheelMetadataResult = Result<MetadataResponse, uv_distribution::Error>;
|
||||||
|
@ -76,6 +76,7 @@ pub struct DefaultResolverProvider<'a, Context: BuildContext> {
|
||||||
/// These are the entries from `--find-links` that act as overrides for index responses.
|
/// These are the entries from `--find-links` that act as overrides for index responses.
|
||||||
flat_index: FlatIndex,
|
flat_index: FlatIndex,
|
||||||
tags: Option<Tags>,
|
tags: Option<Tags>,
|
||||||
|
requires_python: Option<RequiresPython>,
|
||||||
allowed_yanks: AllowedYanks,
|
allowed_yanks: AllowedYanks,
|
||||||
hasher: HashStrategy,
|
hasher: HashStrategy,
|
||||||
exclude_newer: Option<ExcludeNewer>,
|
exclude_newer: Option<ExcludeNewer>,
|
||||||
|
@ -88,6 +89,7 @@ impl<'a, Context: BuildContext> DefaultResolverProvider<'a, Context> {
|
||||||
fetcher: DistributionDatabase<'a, Context>,
|
fetcher: DistributionDatabase<'a, Context>,
|
||||||
flat_index: &'a FlatIndex,
|
flat_index: &'a FlatIndex,
|
||||||
tags: Option<&'a Tags>,
|
tags: Option<&'a Tags>,
|
||||||
|
requires_python: Option<&'a RequiresPython>,
|
||||||
allowed_yanks: AllowedYanks,
|
allowed_yanks: AllowedYanks,
|
||||||
hasher: &'a HashStrategy,
|
hasher: &'a HashStrategy,
|
||||||
exclude_newer: Option<ExcludeNewer>,
|
exclude_newer: Option<ExcludeNewer>,
|
||||||
|
@ -97,6 +99,7 @@ impl<'a, Context: BuildContext> DefaultResolverProvider<'a, Context> {
|
||||||
fetcher,
|
fetcher,
|
||||||
flat_index: flat_index.clone(),
|
flat_index: flat_index.clone(),
|
||||||
tags: tags.cloned(),
|
tags: tags.cloned(),
|
||||||
|
requires_python: requires_python.cloned(),
|
||||||
allowed_yanks,
|
allowed_yanks,
|
||||||
hasher: hasher.clone(),
|
hasher: hasher.clone(),
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
|
@ -127,6 +130,7 @@ impl<'a, Context: BuildContext> ResolverProvider for DefaultResolverProvider<'a,
|
||||||
package_name,
|
package_name,
|
||||||
&index,
|
&index,
|
||||||
self.tags.as_ref(),
|
self.tags.as_ref(),
|
||||||
|
self.requires_python.as_ref(),
|
||||||
&self.allowed_yanks,
|
&self.allowed_yanks,
|
||||||
&self.hasher,
|
&self.hasher,
|
||||||
self.exclude_newer.as_ref(),
|
self.exclude_newer.as_ref(),
|
||||||
|
|
|
@ -8,7 +8,8 @@ use tracing::instrument;
|
||||||
use distribution_filename::{DistFilename, WheelFilename};
|
use distribution_filename::{DistFilename, WheelFilename};
|
||||||
use distribution_types::{
|
use distribution_types::{
|
||||||
HashComparison, IncompatibleSource, IncompatibleWheel, IndexUrl, PrioritizedDist,
|
HashComparison, IncompatibleSource, IncompatibleWheel, IndexUrl, PrioritizedDist,
|
||||||
RegistryBuiltWheel, RegistrySourceDist, SourceDistCompatibility, WheelCompatibility,
|
PythonRequirementKind, RegistryBuiltWheel, RegistrySourceDist, SourceDistCompatibility,
|
||||||
|
WheelCompatibility,
|
||||||
};
|
};
|
||||||
use pep440_rs::Version;
|
use pep440_rs::Version;
|
||||||
use platform_tags::{TagCompatibility, Tags};
|
use platform_tags::{TagCompatibility, Tags};
|
||||||
|
@ -20,7 +21,7 @@ use uv_types::HashStrategy;
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
use crate::flat_index::FlatDistributions;
|
use crate::flat_index::FlatDistributions;
|
||||||
use crate::{yanks::AllowedYanks, ExcludeNewer};
|
use crate::{yanks::AllowedYanks, ExcludeNewer, RequiresPython};
|
||||||
|
|
||||||
/// A map from versions to distributions.
|
/// A map from versions to distributions.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -44,6 +45,7 @@ impl VersionMap {
|
||||||
package_name: &PackageName,
|
package_name: &PackageName,
|
||||||
index: &IndexUrl,
|
index: &IndexUrl,
|
||||||
tags: Option<&Tags>,
|
tags: Option<&Tags>,
|
||||||
|
requires_python: Option<&RequiresPython>,
|
||||||
allowed_yanks: &AllowedYanks,
|
allowed_yanks: &AllowedYanks,
|
||||||
hasher: &HashStrategy,
|
hasher: &HashStrategy,
|
||||||
exclude_newer: Option<&ExcludeNewer>,
|
exclude_newer: Option<&ExcludeNewer>,
|
||||||
|
@ -105,6 +107,7 @@ impl VersionMap {
|
||||||
no_build: build_options.no_build_package(package_name),
|
no_build: build_options.no_build_package(package_name),
|
||||||
index: index.clone(),
|
index: index.clone(),
|
||||||
tags: tags.cloned(),
|
tags: tags.cloned(),
|
||||||
|
requires_python: requires_python.cloned(),
|
||||||
exclude_newer: exclude_newer.copied(),
|
exclude_newer: exclude_newer.copied(),
|
||||||
allowed_yanks,
|
allowed_yanks,
|
||||||
required_hashes,
|
required_hashes,
|
||||||
|
@ -288,6 +291,8 @@ struct VersionMapLazy {
|
||||||
allowed_yanks: FxHashSet<Version>,
|
allowed_yanks: FxHashSet<Version>,
|
||||||
/// The hashes of allowed distributions.
|
/// The hashes of allowed distributions.
|
||||||
required_hashes: Vec<HashDigest>,
|
required_hashes: Vec<HashDigest>,
|
||||||
|
/// The `requires-python` constraint for the resolution.
|
||||||
|
requires_python: Option<RequiresPython>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VersionMapLazy {
|
impl VersionMapLazy {
|
||||||
|
@ -508,6 +513,17 @@ impl VersionMapLazy {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if the wheel is compatible with the `requires-python` (i.e., the Python ABI tag
|
||||||
|
// is not less than the `requires-python` minimum version).
|
||||||
|
if let Some(requires_python) = self.requires_python.as_ref() {
|
||||||
|
if !filename.matches_requires_python(requires_python.specifiers()) {
|
||||||
|
return WheelCompatibility::Incompatible(IncompatibleWheel::RequiresPython(
|
||||||
|
requires_python.specifiers().clone(),
|
||||||
|
PythonRequirementKind::Target,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Break ties with the build tag.
|
// Break ties with the build tag.
|
||||||
let build_tag = filename.build_tag.clone();
|
let build_tag = filename.build_tag.clone();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue