mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Avoid enforcing extra-only constraints (#4570)
## Summary In the dependency refactor (https://github.com/astral-sh/uv/pull/4430), the logic for requirements and constraints was combined. Specifically, we were applying constraints _before_ filtering on markers and extras, and then applying that same filtering to the constraints. As a result, constraints that should only be activated when an extra is enabled were being enabled unconditionally. Closes https://github.com/astral-sh/uv/issues/4569.
This commit is contained in:
parent
a8c28c4612
commit
bbbe1f3968
3 changed files with 77 additions and 12 deletions
|
@ -1302,15 +1302,6 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
) -> impl Iterator<Item = &'a Requirement> {
|
) -> impl Iterator<Item = &'a Requirement> {
|
||||||
self.overrides
|
self.overrides
|
||||||
.apply(dependencies)
|
.apply(dependencies)
|
||||||
.flat_map(|requirement| {
|
|
||||||
iter::once(requirement).chain(
|
|
||||||
// If the requirement was constrained, add those constraints.
|
|
||||||
self.constraints
|
|
||||||
.get(&requirement.name)
|
|
||||||
.into_iter()
|
|
||||||
.flatten(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.filter(move |requirement| {
|
.filter(move |requirement| {
|
||||||
// If the requirement would not be selected with any Python version
|
// If the requirement would not be selected with any Python version
|
||||||
// supported by the root, skip it.
|
// supported by the root, skip it.
|
||||||
|
@ -1353,8 +1344,50 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
|
.flat_map(move |requirement| {
|
||||||
|
iter::once(requirement).chain(
|
||||||
|
self.constraints
|
||||||
|
.get(&requirement.name)
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.filter(move |constraint| {
|
||||||
|
if !satisfies_requires_python(self.requires_python.as_ref(), constraint) {
|
||||||
|
trace!(
|
||||||
|
"skipping {constraint} because of Requires-Python {requires_python}",
|
||||||
|
requires_python = self.requires_python.as_ref().unwrap()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !possible_to_satisfy_markers(markers, constraint) {
|
||||||
|
trace!("skipping {constraint} because of context resolver markers {markers}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the constraint isn't relevant for the current platform, skip it.
|
||||||
|
match extra {
|
||||||
|
Some(source_extra) => {
|
||||||
|
if !constraint.evaluate_markers(
|
||||||
|
self.markers.as_ref(),
|
||||||
|
std::slice::from_ref(source_extra),
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if !constraint.evaluate_markers(self.markers.as_ref(), &[]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch the metadata for a stream of packages and versions.
|
/// Fetch the metadata for a stream of packages and versions.
|
||||||
|
|
|
@ -9731,3 +9731,38 @@ fn no_binary_only_binary() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `gunicorn` only depends on `eventlet` via an extra, so the resolution should succeed despite
|
||||||
|
/// the nonsensical extra.
|
||||||
|
#[test]
|
||||||
|
fn ignore_invalid_constraint() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let requirements_in = context.temp_dir.child("requirements.in");
|
||||||
|
requirements_in.write_str("gunicorn>=20")?;
|
||||||
|
|
||||||
|
let constraints_txt = context.temp_dir.child("constraints.txt");
|
||||||
|
constraints_txt.write_str("eventlet==9999.0.1.2.3.4.5")?;
|
||||||
|
|
||||||
|
uv_snapshot!(context
|
||||||
|
.pip_compile()
|
||||||
|
.arg("requirements.in")
|
||||||
|
.arg("-c")
|
||||||
|
.arg("constraints.txt"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
# This file was autogenerated by uv via the following command:
|
||||||
|
# uv pip compile --cache-dir [CACHE_DIR] requirements.in -c constraints.txt
|
||||||
|
gunicorn==21.2.0
|
||||||
|
# via -r requirements.in
|
||||||
|
packaging==24.0
|
||||||
|
# via gunicorn
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 2 packages in [TIME]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
3
req.txt
3
req.txt
|
@ -1,3 +0,0 @@
|
||||||
--index-url file:///Users/crmarsh/workspace/packse/index/simple-html/
|
|
||||||
|
|
||||||
example-a-961b4c22
|
|
Loading…
Add table
Add a link
Reference in a new issue