mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-13 09:12:32 +00:00
Prioritize forks based on upper bounds (#5643)
## Summary Given a fork like: ``` pylint < 3 ; sys_platform == 'darwin' pylint > 2 ; sys_platform != 'darwin' ``` Solving the top branch will typically yield a solution that also satisfies the bottom branch, due to maximum version selection (while the inverse isn't true). To quote an example from the docs: ```rust // If there's no difference, prioritize forks with upper bounds. We'd prefer to solve // `numpy <= 2` before solving `numpy >= 1`, since the resolution produced by the former // might work for the latter, but the inverse is unlikely to be true due to maximum // version selection. (Selecting `numpy==2.0.0` would satisfy both forks, but selecting // the latest `numpy` would not.) ``` Closes https://github.com/astral-sh/uv/issues/4926 for now.
This commit is contained in:
parent
89947681d1
commit
c2a6cb391b
2 changed files with 85 additions and 1 deletions
|
|
@ -2844,7 +2844,34 @@ impl Ord for Fork {
|
||||||
// work for the latter, but the inverse is unlikely to be true.
|
// work for the latter, but the inverse is unlikely to be true.
|
||||||
let self_bound = requires_python_marker(&self.markers).unwrap_or_default();
|
let self_bound = requires_python_marker(&self.markers).unwrap_or_default();
|
||||||
let other_bound = requires_python_marker(&other.markers).unwrap_or_default();
|
let other_bound = requires_python_marker(&other.markers).unwrap_or_default();
|
||||||
other_bound.cmp(&self_bound)
|
|
||||||
|
other_bound.cmp(&self_bound).then_with(|| {
|
||||||
|
// If there's no difference, prioritize forks with upper bounds. We'd prefer to solve
|
||||||
|
// `numpy <= 2` before solving `numpy >= 1`, since the resolution produced by the former
|
||||||
|
// might work for the latter, but the inverse is unlikely to be true due to maximum
|
||||||
|
// version selection. (Selecting `numpy==2.0.0` would satisfy both forks, but selecting
|
||||||
|
// the latest `numpy` would not.)
|
||||||
|
let self_upper_bounds = self
|
||||||
|
.dependencies
|
||||||
|
.iter()
|
||||||
|
.filter(|dep| {
|
||||||
|
dep.version
|
||||||
|
.bounding_range()
|
||||||
|
.is_some_and(|(_, upper)| !matches!(upper, Bound::Unbounded))
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
let other_upper_bounds = other
|
||||||
|
.dependencies
|
||||||
|
.iter()
|
||||||
|
.filter(|dep| {
|
||||||
|
dep.version
|
||||||
|
.bounding_range()
|
||||||
|
.is_some_and(|(_, upper)| !matches!(upper, Bound::Unbounded))
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
|
||||||
|
self_upper_bounds.cmp(&other_upper_bounds)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7949,6 +7949,63 @@ fn universal_no_repeated_unconditional_distributions() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Solve for upper bounds before solving for lower bounds. A solution that satisfies `pylint < 3`
|
||||||
|
/// can also work for `pylint > 2`, but the inverse isn't true (due to maximum version selection).
|
||||||
|
#[test]
|
||||||
|
fn universal_prefer_upper_bounds() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
let requirements_in = context.temp_dir.child("requirements.in");
|
||||||
|
requirements_in.write_str(indoc::indoc! {r"
|
||||||
|
pylint < 3 ; sys_platform == 'darwin'
|
||||||
|
pylint > 2 ; sys_platform != 'darwin'
|
||||||
|
"})?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), windows_filters=false, context.pip_compile()
|
||||||
|
.arg("requirements.in")
|
||||||
|
.arg("-p")
|
||||||
|
.arg("3.8")
|
||||||
|
.arg("--universal"), @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 -p 3.8 --universal
|
||||||
|
astroid==2.15.8 ; (python_version < '3.11' and sys_platform == 'darwin') or (python_version < '3.11' and sys_platform != 'darwin') or (python_version >= '3.11' and sys_platform == 'darwin') or (python_version >= '3.11' and sys_platform != 'darwin')
|
||||||
|
# via pylint
|
||||||
|
colorama==0.4.6 ; sys_platform == 'win32'
|
||||||
|
# via pylint
|
||||||
|
dill==0.3.8
|
||||||
|
# via pylint
|
||||||
|
isort==5.13.2 ; (python_version < '3.11' and sys_platform == 'darwin') or (python_version < '3.11' and sys_platform != 'darwin') or (python_version >= '3.11' and sys_platform == 'darwin') or (python_version >= '3.11' and sys_platform != 'darwin')
|
||||||
|
# via pylint
|
||||||
|
lazy-object-proxy==1.10.0 ; (python_version < '3.11' and sys_platform == 'darwin') or (python_version < '3.11' and sys_platform != 'darwin') or (python_version >= '3.11' and sys_platform == 'darwin') or (python_version >= '3.11' and sys_platform != 'darwin')
|
||||||
|
# via astroid
|
||||||
|
mccabe==0.7.0 ; (python_version < '3.11' and sys_platform == 'darwin') or (python_version < '3.11' and sys_platform != 'darwin') or (python_version >= '3.11' and sys_platform == 'darwin') or (python_version >= '3.11' and sys_platform != 'darwin')
|
||||||
|
# via pylint
|
||||||
|
platformdirs==4.2.0 ; (python_version < '3.11' and sys_platform == 'darwin') or (python_version < '3.11' and sys_platform != 'darwin') or (python_version >= '3.11' and sys_platform == 'darwin') or (python_version >= '3.11' and sys_platform != 'darwin')
|
||||||
|
# via pylint
|
||||||
|
pylint==2.17.7
|
||||||
|
# via -r requirements.in
|
||||||
|
tomli==2.0.1 ; python_version < '3.11'
|
||||||
|
# via pylint
|
||||||
|
tomlkit==0.12.4 ; (python_version < '3.11' and sys_platform == 'darwin') or (python_version < '3.11' and sys_platform != 'darwin') or (python_version >= '3.11' and sys_platform == 'darwin') or (python_version >= '3.11' and sys_platform != 'darwin')
|
||||||
|
# via pylint
|
||||||
|
typing-extensions==4.10.0 ; python_version < '3.11'
|
||||||
|
# via
|
||||||
|
# astroid
|
||||||
|
# pylint
|
||||||
|
wrapt==1.16.0 ; (python_version < '3.11' and sys_platform == 'darwin') or (python_version < '3.11' and sys_platform != 'darwin') or (python_version >= '3.11' and sys_platform == 'darwin') or (python_version >= '3.11' and sys_platform != 'darwin')
|
||||||
|
# via astroid
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: The requested Python version 3.8 is not available; 3.12.[X] will be used to build dependencies instead.
|
||||||
|
Resolved 12 packages in [TIME]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove `python_version` markers that are always true.
|
/// Remove `python_version` markers that are always true.
|
||||||
#[test]
|
#[test]
|
||||||
fn universal_unnecessary_python() -> Result<()> {
|
fn universal_unnecessary_python() -> Result<()> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue