mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-29 11:07:59 +00:00
Make direct dependency detection respect markers (#2207)
## Summary When determining "direct" dependencies, we need to ensure that we respect markers. In the linked issue, the user had an optional dependency like: ```toml [project.optional-dependencies] dev = [ "setuptools>=64", "setuptools_scm>=8" ] ``` By not respecting markers, we tried to resolve `setuptools` to the lowest-available version. However, since `setuptools>=64` _isn't_ enabled (since it's optional), we won't respect _that_ constraint. To be consistent, we need to omit optional dependencies just as we will at resolution time. Closes https://github.com/astral-sh/uv/issues/2203. ## Test Plan `cargo test`
This commit is contained in:
parent
7f07ada24c
commit
8620b5a52f
6 changed files with 135 additions and 57 deletions
|
|
@ -1,28 +1,33 @@
|
|||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use pep440_rs::Version;
|
||||
use pep508_rs::Requirement;
|
||||
use pep508_rs::MarkerEnvironment;
|
||||
use uv_normalize::PackageName;
|
||||
|
||||
use crate::Manifest;
|
||||
|
||||
/// A set of package versions that are permitted, even if they're marked as yanked by the
|
||||
/// relevant index.
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct AllowedYanks(FxHashMap<PackageName, FxHashSet<Version>>);
|
||||
|
||||
impl AllowedYanks {
|
||||
/// Returns `true` if the given package version is allowed, even if it's marked as yanked by
|
||||
/// the relevant index.
|
||||
pub(crate) fn allowed(&self, package_name: &PackageName, version: &Version) -> bool {
|
||||
self.0
|
||||
.get(package_name)
|
||||
.is_some_and(|allowed_yanks| allowed_yanks.contains(version))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromIterator<&'a Requirement> for AllowedYanks {
|
||||
fn from_iter<T: IntoIterator<Item = &'a Requirement>>(iter: T) -> Self {
|
||||
pub(crate) fn from_manifest(manifest: &Manifest, markers: &MarkerEnvironment) -> Self {
|
||||
let mut allowed_yanks = FxHashMap::<PackageName, FxHashSet<Version>>::default();
|
||||
for requirement in iter {
|
||||
for requirement in manifest
|
||||
.requirements
|
||||
.iter()
|
||||
.chain(manifest.constraints.iter())
|
||||
.chain(manifest.overrides.iter())
|
||||
.chain(manifest.preferences.iter())
|
||||
.filter(|requirement| requirement.evaluate_markers(markers, &[]))
|
||||
.chain(manifest.editables.iter().flat_map(|(editable, metadata)| {
|
||||
metadata
|
||||
.requires_dist
|
||||
.iter()
|
||||
.filter(|requirement| requirement.evaluate_markers(markers, &editable.extras))
|
||||
}))
|
||||
{
|
||||
let Some(pep508_rs::VersionOrUrl::VersionSpecifier(specifiers)) =
|
||||
&requirement.version_or_url
|
||||
else {
|
||||
|
|
@ -43,4 +48,12 @@ impl<'a> FromIterator<&'a Requirement> for AllowedYanks {
|
|||
}
|
||||
Self(allowed_yanks)
|
||||
}
|
||||
|
||||
/// Returns `true` if the given package version is allowed, even if it's marked as yanked by
|
||||
/// the relevant index.
|
||||
pub(crate) fn allowed(&self, package_name: &PackageName, version: &Version) -> bool {
|
||||
self.0
|
||||
.get(package_name)
|
||||
.is_some_and(|allowed_yanks| allowed_yanks.contains(version))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue