-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Improve display of available package ranges #6118
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
Conversation
| ----- stderr ----- | ||
| × No solution found when resolving dependencies: | ||
| ╰─▶ Because only package-a<=1.2.3 is available and you require package-a>1.2.3, we can conclude that the requirements are unsatisfiable. | ||
| ╰─▶ Because only package-a==1.2.3+foo is available and you require package-a>1.2.3, we can conclude that the requirements are unsatisfiable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we know there is exactly one version available, so we show that instead of a range.
| ╰─▶ 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,<=3.0.0 | ||
| package-a>2.0.0,<=3.0.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the idea from #6071, there is no 2.0.0 so we shouldn't use >= here.
143c9d2 to
3f1c777
Compare
3f1c777 to
1cb945d
Compare
| (Some(first), Some(last)) => { | ||
| let range = Range::<Version>::from_range_bounds(( | ||
| Bound::Included(first.clone()), | ||
| Bound::Included(last.clone()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting... This should have holes in it, right? But my guess is it doesn't help / doesn't matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It basically doesn't matter in this case, we're just using it to check if the other range is completely out of bounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I should write a note for that, maybe there are some weird cases where the holes do matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote it this way to avoid doing something like for version in available_versions { range.contains(version) } to see if the range contained all or none of the versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think this is cool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a note, we probably wont simplify some things that we could.
| _ => (*upper).clone(), | ||
| }; | ||
|
|
||
| new_range = new_range.union(&Range::from_range_bounds((lower, upper))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this is quadratic, and we should instead be collecting all the new ranges and then unioning them all at once at the end? But I don't see a way to do that in the Range API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish. I think you can't just push segments yourself because it voids some guarantees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping you could pass an iterator to union or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a note. We could follow-up in PubGrub. cc @konstin
charliermarsh
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense.
| // `foo>999`, and the the available versions are all `<10` it's useless to show. | ||
| if segment_range.is_disjoint(&available_range) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the range is a singleton, and it's not in available versions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Is that impossible?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like this?
❯ uv add 'httpx==9999'
╰─▶ Because there is no version of httpx==9999 and example depends on httpx==9999, we can conclude that example's requirements
are unsatisfiable.
And because your workspace requires example, we can conclude that your workspace's requirements are unsatisfiable.
I think that's always handled before we get here. Otherwise, this operation is performed on the complement so I don't think it's possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah like that. Ok I figured it was somehow handled upstream.
1cb945d to
7cd52c5
Compare
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [astral-sh/uv](https://github.com/astral-sh/uv) | patch | `0.2.36` -> `0.2.37` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>astral-sh/uv (astral-sh/uv)</summary> ### [`v0.2.37`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0237) [Compare Source](astral-sh/uv@0.2.36...0.2.37) ##### Performance - Avoid cloning requirement for unchanged markers ([#​6116](astral-sh/uv#6116)) ##### Bug fixes - Fix loading of cached metadata for Git distributions with subdirectories ([#​6094](astral-sh/uv#6094)) ##### Error messages - Add env var to `--link-mode=copy` warning ([#​6103](astral-sh/uv#6103)) - Avoid displaying "failed to download" on build failures for local source distributions ([#​6075](astral-sh/uv#6075)) - Improve display of available package ranges ([#​6118](astral-sh/uv#6118)) - Use "your requirements" consistently in resolver error messages ([#​6113](astral-sh/uv#6113)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40NDAuNyIsInVwZGF0ZWRJblZlciI6IjM3LjQ0MC43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
Includes the changes from #6071 but takes them way further.
When we have the set of available versions for a package, we can do a much better job displaying an error.
For example:
The resolver has demonstrated that the requested range cannot be used because there are only versions in ranges outside the requested range. However, the display of the range of available versions is pretty bad! We say there are versions of httpx available in ranges that definitely have no versions available.
With this pull request, the error becomes:
We achieve this by:
httpx>=9999httpx<=999with<=1.0.0b0.Note that when we perform (2), we may include an additional bound that is not relevant, e.g., we include the lower bound of(edit: I did this, it wasn't hard)>=0.6.7. This is a bit extraneous, but I don't think it's confusing. We can consider some advanced logic to avoid that later.We also improve error messages when there is only one version available by showing that version instead of a range.