mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-03 13:14:41 +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.
|
||||
let self_bound = requires_python_marker(&self.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(())
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[test]
|
||||
fn universal_unnecessary_python() -> Result<()> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue