Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect sentinels in prioritization #10443

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions crates/uv-resolver/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ impl NoSolutionError {
match derivation_tree {
DerivationTree::External(External::NotRoot(_, _)) => Some(derivation_tree),
DerivationTree::External(External::NoVersions(package, versions)) => {
if SentinelRange::from(&versions).is_sentinel() {
if SentinelRange::from(&versions).is_complement() {
return None;
}

Expand Down Expand Up @@ -977,13 +977,30 @@ impl<'range> From<&'range Range<Version>> for SentinelRange<'range> {
}

impl SentinelRange<'_> {
/// Returns `true` if the range appears to be, e.g., `>1.0.0, <1.0.0+[max]`.
/// Returns `true` if the range appears to be, e.g., `>=1.0.0, <1.0.0+[max]`.
pub fn is_sentinel(&self) -> bool {
self.0.iter().all(|(lower, upper)| {
let (Bound::Included(lower), Bound::Excluded(upper)) = (lower, upper) else {
return false;
};
if !lower.local().is_empty() {
return false;
}
if upper.local() != LocalVersionSlice::Max {
return false;
}
*lower == upper.clone().without_local()
})
}

/// Returns `true` if the range appears to be, e.g., `>1.0.0, <1.0.0+[max]` (i.e., a sentinel
/// range with the non-local version removed).
pub fn is_complement(&self) -> bool {
self.0.iter().all(|(lower, upper)| {
let (Bound::Excluded(lower), Bound::Excluded(upper)) = (lower, upper) else {
return false;
};
if lower.local() == LocalVersionSlice::Max {
if !lower.local().is_empty() {
return false;
}
if upper.local() != LocalVersionSlice::Max {
Expand Down
20 changes: 9 additions & 11 deletions crates/uv-resolver/src/pubgrub/priority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use uv_pep440::Version;
use crate::fork_urls::ForkUrls;
use crate::pubgrub::package::PubGrubPackage;
use crate::pubgrub::PubGrubPackageInner;
use crate::SentinelRange;

/// A prioritization map to guide the PubGrub resolution process.
///
Expand Down Expand Up @@ -57,8 +58,9 @@ impl PubGrubPriorities {
// Compute the priority.
let priority = if urls.get(name).is_some() {
PubGrubPriority::DirectUrl(Reverse(index))
} else if version.as_singleton().is_some() {
// TODO(charlie): Take local version ranges into account (e.g., `[2.0, 2.0+[max])`).
} else if version.as_singleton().is_some()
|| SentinelRange::from(version).is_sentinel()
{
PubGrubPriority::Singleton(Reverse(index))
} else {
// Keep the conflict-causing packages to avoid loops where we seesaw between
Expand All @@ -81,8 +83,9 @@ impl PubGrubPriorities {
// Compute the priority.
let priority = if urls.get(name).is_some() {
PubGrubPriority::DirectUrl(Reverse(next))
} else if version.as_singleton().is_some() {
// TODO(charlie): Take local version ranges into account (e.g., `[2.0, 2.0+[max])`).
} else if version.as_singleton().is_some()
|| SentinelRange::from(version).is_sentinel()
{
PubGrubPriority::Singleton(Reverse(next))
} else {
PubGrubPriority::Unspecified(Reverse(next))
Expand Down Expand Up @@ -140,10 +143,7 @@ impl PubGrubPriorities {
};
match self.package_priority.entry(name.clone()) {
std::collections::hash_map::Entry::Occupied(mut entry) => {
if matches!(
entry.get(),
PubGrubPriority::ConflictEarly(_) | PubGrubPriority::Singleton(_)
) {
if matches!(entry.get(), PubGrubPriority::ConflictEarly(_)) {
// Already in the right category
return false;
};
Expand Down Expand Up @@ -178,9 +178,7 @@ impl PubGrubPriorities {
// The ConflictEarly` match avoids infinite loops.
if matches!(
entry.get(),
PubGrubPriority::ConflictLate(_)
| PubGrubPriority::ConflictEarly(_)
| PubGrubPriority::Singleton(_)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@konstin -- Heads up, I removed this... Otherwise, the wrong_backtracking_basic test failed. I think it succeeded by accident before? Since all the conflicts are in singletons.

PubGrubPriority::ConflictLate(_) | PubGrubPriority::ConflictEarly(_)
) {
// Already in the right category
return false;
Expand Down
2 changes: 0 additions & 2 deletions crates/uv-resolver/src/version_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,6 @@ impl VersionMap {
range: &Ranges<Version>,
) -> impl DoubleEndedIterator<Item = (&Version, VersionMapDistHandle)> {
// Performance optimization: If we only have a single version, return that version directly.
//
// TODO(charlie): Now that we use local version sentinels, does this ever trigger?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does... Proxy packages use Ranges::singleton, which hits this path.

if let Some(version) = range.as_singleton() {
either::Either::Left(match self.inner {
VersionMapInner::Eager(ref eager) => {
Expand Down
8 changes: 4 additions & 4 deletions crates/uv/tests/it/pip_install_scenarios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,17 +531,17 @@ fn excluded_only_compatible_version() {

----- stderr -----
× No solution found when resolving dependencies:
╰─▶ Because only the following versions of package-a are available:
╰─▶ Because package-a==1.0.0 depends on package-b==1.0.0 and only the following versions of package-a are available:
package-a==1.0.0
package-a==2.0.0
package-a==3.0.0
and package-a==1.0.0 depends on package-b==1.0.0, we can conclude that package-a<2.0.0 depends on package-b==1.0.0.
we can conclude that package-a<2.0.0 depends on package-b==1.0.0.
And because package-a==3.0.0 depends on package-b==3.0.0, we can conclude that all of:
package-a<2.0.0
package-a>2.0.0
depend on one of:
package-b==1.0.0
package-b==3.0.0
package-b<=1.0.0
package-b>=3.0.0

And because you require one of:
package-a<2.0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3001,20 +3001,18 @@ wheels = [

[[package]]
name = "protobuf"
version = "3.20.3"
version = "4.25.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/55/5b/e3d951e34f8356e5feecacd12a8e3b258a1da6d9a03ad1770f28925f29bc/protobuf-3.20.3.tar.gz", hash = "sha256:2e3427429c9cffebf259491be0af70189607f365c2f41c7c3764af6f337105f2", size = 216768 }
sdist = { url = "https://files.pythonhosted.org/packages/e8/ab/cb61a4b87b2e7e6c312dce33602bd5884797fd054e0e53205f1c27cf0f66/protobuf-4.25.4.tar.gz", hash = "sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d", size = 380283 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/28/55/b80e8567ec327c060fa39b242392e25690c8899c489ecd7bb65b46b7bb55/protobuf-3.20.3-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:f4bd856d702e5b0d96a00ec6b307b0f51c1982c2bf9c0052cf9019e9a544ba99", size = 918427 },
{ url = "https://files.pythonhosted.org/packages/31/be/80a9c6f16dfa4d41be3edbe655349778ae30882407fa8275eb46b4d34854/protobuf-3.20.3-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9aae4406ea63d825636cc11ffb34ad3379335803216ee3a856787bcf5ccc751e", size = 1051042 },
{ url = "https://files.pythonhosted.org/packages/db/96/948d3fcc1fa816e7ae1d27af59b9d8c5c5e582f3994fd14394f31da95b99/protobuf-3.20.3-cp310-cp310-win32.whl", hash = "sha256:28545383d61f55b57cf4df63eebd9827754fd2dc25f80c5253f9184235db242c", size = 780167 },
{ url = "https://files.pythonhosted.org/packages/6f/5e/fc6feb366b0a9f28e0a2de3b062667c521cd9517d4ff55077b8f351ba2f3/protobuf-3.20.3-cp310-cp310-win_amd64.whl", hash = "sha256:67a3598f0a2dcbc58d02dd1928544e7d88f764b47d4a286202913f0b2801c2e7", size = 904029 },
{ url = "https://files.pythonhosted.org/packages/00/e7/d23c439c55c90ae2e52184363162f7079ca3e7d86205b411d4e9dc266f81/protobuf-3.20.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:398a9e0c3eaceb34ec1aee71894ca3299605fa8e761544934378bbc6c97de23b", size = 982826 },
{ url = "https://files.pythonhosted.org/packages/99/25/5825472ecd911f4ac2ac4e9ab039a48b6d03874e2add92fb633e080bf3eb/protobuf-3.20.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf01b5720be110540be4286e791db73f84a2b721072a3711efff6c324cdf074b", size = 918423 },
{ url = "https://files.pythonhosted.org/packages/c7/df/ec3ecb8c940b36121c7b77c10acebf3d1c736498aa2f1fe3b6231ee44e76/protobuf-3.20.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:daa564862dd0d39c00f8086f88700fdbe8bc717e993a21e90711acfed02f2402", size = 1019250 },
{ url = "https://files.pythonhosted.org/packages/36/8b/433071fed0058322090a55021bdc8da76d16c7bc9823f5795797803dd6d0/protobuf-3.20.3-cp39-cp39-win32.whl", hash = "sha256:819559cafa1a373b7096a482b504ae8a857c89593cf3a25af743ac9ecbd23480", size = 780270 },
{ url = "https://files.pythonhosted.org/packages/11/a5/e52b731415ad6ef3d841e9e6e337a690249e800cc7c06f0749afab26348c/protobuf-3.20.3-cp39-cp39-win_amd64.whl", hash = "sha256:03038ac1cfbc41aa21f6afcbcd357281d7521b4157926f30ebecc8d4ea59dcb7", size = 904215 },
{ url = "https://files.pythonhosted.org/packages/8d/14/619e24a4c70df2901e1f4dbc50a6291eb63a759172558df326347dce1f0d/protobuf-3.20.3-py2.py3-none-any.whl", hash = "sha256:a7ca6d488aa8ff7f329d4c545b2dbad8ac31464f1d8b1c87ad1346717731e4db", size = 162128 },
{ url = "https://files.pythonhosted.org/packages/c8/43/27b48d9040763b78177d3083e16c70dba6e3c3ee2af64b659f6332c2b06e/protobuf-4.25.4-cp310-abi3-win32.whl", hash = "sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4", size = 392409 },
{ url = "https://files.pythonhosted.org/packages/0c/d4/589d673ada9c4c62d5f155218d7ff7ac796efb9c6af95b0bd29d438ae16e/protobuf-4.25.4-cp310-abi3-win_amd64.whl", hash = "sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d", size = 413398 },
{ url = "https://files.pythonhosted.org/packages/34/ca/bf85ffe3dd16f1f2aaa6c006da8118800209af3da160ae4d4f47500eabd9/protobuf-4.25.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b", size = 394160 },
{ url = "https://files.pythonhosted.org/packages/68/1d/e8961af9a8e534d66672318d6b70ea8e3391a6b13e16a29b039e4a99c214/protobuf-4.25.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835", size = 293700 },
{ url = "https://files.pythonhosted.org/packages/ca/6c/cc7ab2fb3a4a7f07f211d8a7bbb76bba633eb09b148296dbd4281e217f95/protobuf-4.25.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040", size = 294612 },
{ url = "https://files.pythonhosted.org/packages/a4/b5/f7e2460dec8347d67e6108bef6ad3291c76e38c898a1087e2c836c02951e/protobuf-4.25.4-cp39-cp39-win32.whl", hash = "sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca", size = 392490 },
{ url = "https://files.pythonhosted.org/packages/c7/0b/15bd1a224e5e5744a0dcccf11bcd5dc1405877be38e477b1359d7c2c3737/protobuf-4.25.4-cp39-cp39-win_amd64.whl", hash = "sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f", size = 413357 },
{ url = "https://files.pythonhosted.org/packages/b5/95/0ba7f66934a0a798006f06fc3d74816da2b7a2bcfd9b98c53d26f684c89e/protobuf-4.25.4-py3-none-any.whl", hash = "sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978", size = 156464 },
]

[[package]]
Expand Down Expand Up @@ -4700,18 +4698,17 @@ wheels = [

[[package]]
name = "tf2onnx"
version = "1.16.1"
version = "1.8.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "flatbuffers" },
{ name = "numpy" },
{ name = "onnx" },
{ name = "protobuf" },
{ name = "requests" },
{ name = "six" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/3f/48/826db3d02645d84e7ee5d5ce8407f771057d40fe224d9c3e89536674ccef/tf2onnx-1.16.1-py3-none-any.whl", hash = "sha256:90fb5f62575896d47884d27dc313cfebff36b8783e1094335ad00824ce923a8a", size = 455820 },
{ url = "https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl", hash = "sha256:1ebabb96c914da76e23222b6107a8b248a024bf259d77f027e6690099512d457", size = 345298 },
]

[[package]]
Expand Down
Loading