-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
relax error checking around unconditional enabling of conflicting extras #10875
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This removes the error that was causing folks problems. This does result in some snapshot updates that are arguably wrong, or at least sub-optimal. However, it's actually intended. Because the approach we're going to take is going to permit the creation of uninstallable lock files as a side effect. In the future, we will modify this test to check that, while `uv lock` succeeds, `uv sync` will always fail.
With the previous commit loosening a restriction in the resolver, it reveals a bug: a `uv sync` won't install a `package[extra]` dependency. This occurs because `extra` isn't treated as activated during install, and thus `package[extra]`'s conflict marker isn't satisfied. In other words, the way we dealt with conflict markers previously assumed that conflicting extras could _only_ be activated via `--extra foo`. And while that used to be true, after the previous commit, it no longer is. We'll fix this bug in the next commit. I added this test in a separate commit to make the problem and resulting fix clearer.
This will make `package[extra]` work even when `extra` is declared as a conflicting extra. Note that this isn't relevant for dependency groups since AFAIK those can actually only be enabled on the CLI. There is no `package:group` dependency syntax.
This collects ALL activated extras while traversing the lock file to produce a `Resolution` for installation. If any two extras are activated that are conflicting, then an error is produced. We add a couple of tests to demonstrate the behavior. One case is desirable (where we conditionally depend on `package[extra]`) and the other case is undesirable (where we create an uninstallable lock file). Fixes #9942, Fixes #10590
This is the test we tweaked a few commits back when we first removed the error checking in the resolver. We now add in some `uv sync` commands, including one that should fail.
333527b
to
243178a
Compare
charliermarsh
approved these changes
Jan 22, 2025
tmeijn
pushed a commit
to tmeijn/dotfiles
that referenced
this pull request
Jan 26, 2025
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [astral-sh/uv](https://github.com/astral-sh/uv) | patch | `0.5.22` -> `0.5.24` | 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.5.24`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0524) [Compare Source](astral-sh/uv@0.5.23...0.5.24) ##### Enhancements - Improve determinism of resolution by always setting package priorities ([#​10853](astral-sh/uv#10853)) - Upgrade to `cargo-dist` 0.28.0; improves several installer behaviors ([#​10884](astral-sh/uv#10884)) ##### Performance - Remove dependencies clone in resolver ([#​10880](astral-sh/uv#10880)) - Use Hashbrown's raw entry API to reduce hashes and clone in resolver priority determination ([#​10881](astral-sh/uv#10881)) ##### Bug fixes - Allow fallback to Python download on non-critical discovery errors ([#​10908](astral-sh/uv#10908)) ##### Preview features - Register managed Python version with the Windows Registry (PEP 514) ([#​10634](astral-sh/uv#10634)) ##### Documentation - Improve documentation for some environment variables ([#​10887](astral-sh/uv#10887)) - Add git subdirectory example ([#​10894](astral-sh/uv#10894)) ### [`v0.5.23`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0523) [Compare Source](astral-sh/uv@0.5.22...0.5.23) ##### Enhancements - Add `--refresh` to `uv venv` ([#​10834](astral-sh/uv#10834)) - Add `--no-default-groups` command-line flag ([#​10618](astral-sh/uv#10618)) ##### Bug fixes - Sort extras and groups when comparing lockfile requirements ([#​10856](astral-sh/uv#10856)) - Include `commit_id` and `requested_revision` in `direct_url.json` ([#​10862](astral-sh/uv#10862)) - Invalidate lockfile when static versions change ([#​10858](astral-sh/uv#10858)) - Make GitHub fast path errors non-fatal ([#​10859](astral-sh/uv#10859)) - Remove warnings for `--frozen` and `--locked` in `uv run --script` ([#​10840](astral-sh/uv#10840)) - Resolve `find-links` paths relative to the configuration file ([#​10827](astral-sh/uv#10827)) - Respect visitation order for proxy packages ([#​10833](astral-sh/uv#10833)) - Treat version mismatch errors as non-fatal in fast paths ([#​10860](astral-sh/uv#10860)) - Mark `--locked` and `--upgrade` are conflicting ([#​10836](astral-sh/uv#10836)) - Relax error checking around unconditional enabling of conflicting extras ([#​10875](astral-sh/uv#10875)) ##### Documentation - Reduce ambiguity in conflicting extras example ([#​10877](astral-sh/uv#10877)) - Update pre-commit documentation ([#​10756](astral-sh/uv#10756)) ##### Error messages - Error when workspace contains conflicting Python requirements ([#​10841](astral-sh/uv#10841)) - Improve uvx error message when uv is missing ([#​9745](astral-sh/uv#9745)) </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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xMjIuMCIsInVwZGF0ZWRJblZlciI6IjM5LjEyNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
BurntSushi
added a commit
that referenced
this pull request
Jan 29, 2025
In #10875, I relaxed the error checking during resolution to permit dependencies like `foo[x1]`, where `x1` was defined to be conflicting. In exchange, the error was, roughly speaking, moved to installation time. This was achieved by looking at the full set of enabled extras and checking whether any conflicts occurred. If so, an error was reported. This ends up being more expressive and permits more valid configurations. However, in so doing, there was a bug in how the accumulated extras were being passed to conflict marker evaluation. Namely, we weren't accounting for the fact that if `foo[x1]` was enabled, then that fact should be carried through to all conflict marker evaluations. This is because some of those will use things like `extra != 'x1'` to indicate that it should only be included if an extra *isn't* enabled. In #10985, this manifested with PyTorch where `torch==2.4.1` and `torch==2.4.1+cpu` were being installed simultaneously. Namely, the choice to install `torch==2.4.1` was not taking into account that the `cpu` extra has been enabled. If it did, then it's conflict marker would evaluate to `false`. Since it didn't, and since `torch==2.4.1+cpu` was also being included, we ended up installing both versions. The approach I took in this PR was to add a second breadth first traversal (which comes first) over the dependency tree to accumulate all of the activated extras. Then, only in the second traversal do we actually build up the resolution graph. Unfortunately, I have no automatic regression test to include here. The regression test we _ought_ to include involves `torch`. And while we are generally find to use those in tests that only generate a lock file, the regression test here actually requires running installation. And downloading and installing `torch` in tests is bad juju. So adding a regression test for this is blocked on better infrastructure for PyTorch tests. With that said, I did manually verify that the test case in #10985 no longer installs multiple versions of `torch`. Fixes #10985
BurntSushi
added a commit
that referenced
this pull request
Jan 29, 2025
In #10875, I relaxed the error checking during resolution to permit dependencies like `foo[x1]`, where `x1` was defined to be conflicting. In exchange, the error was, roughly speaking, moved to installation time. This was achieved by looking at the full set of enabled extras and checking whether any conflicts occurred. If so, an error was reported. This ends up being more expressive and permits more valid configurations. However, in so doing, there was a bug in how the accumulated extras were being passed to conflict marker evaluation. Namely, we weren't accounting for the fact that if `foo[x1]` was enabled, then that fact should be carried through to all conflict marker evaluations. This is because some of those will use things like `extra != 'x1'` to indicate that it should only be included if an extra *isn't* enabled. In #10985, this manifested with PyTorch where `torch==2.4.1` and `torch==2.4.1+cpu` were being installed simultaneously. Namely, the choice to install `torch==2.4.1` was not taking into account that the `cpu` extra has been enabled. If it did, then it's conflict marker would evaluate to `false`. Since it didn't, and since `torch==2.4.1+cpu` was also being included, we ended up installing both versions. The approach I took in this PR was to add a second breadth first traversal (which comes first) over the dependency tree to accumulate all of the activated extras. Then, only in the second traversal do we actually build up the resolution graph. Unfortunately, I have no automatic regression test to include here. The regression test we _ought_ to include involves `torch`. And while we are generally find to use those in tests that only generate a lock file, the regression test here actually requires running installation. And downloading and installing `torch` in tests is bad juju. So adding a regression test for this is blocked on better infrastructure for PyTorch tests. With that said, I did manually verify that the test case in #10985 no longer installs multiple versions of `torch`. Fixes #10985
BurntSushi
added a commit
that referenced
this pull request
Jan 29, 2025
In #10875, I relaxed the error checking during resolution to permit dependencies like `foo[x1]`, where `x1` was defined to be conflicting. In exchange, the error was, roughly speaking, moved to installation time. This was achieved by looking at the full set of enabled extras and checking whether any conflicts occurred. If so, an error was reported. This ends up being more expressive and permits more valid configurations. However, in so doing, there was a bug in how the accumulated extras were being passed to conflict marker evaluation. Namely, we weren't accounting for the fact that if `foo[x1]` was enabled, then that fact should be carried through to all conflict marker evaluations. This is because some of those will use things like `extra != 'x1'` to indicate that it should only be included if an extra *isn't* enabled. In #10985, this manifested with PyTorch where `torch==2.4.1` and `torch==2.4.1+cpu` were being installed simultaneously. Namely, the choice to install `torch==2.4.1` was not taking into account that the `cpu` extra has been enabled. If it did, then it's conflict marker would evaluate to `false`. Since it didn't, and since `torch==2.4.1+cpu` was also being included, we ended up installing both versions. The approach I took in this PR was to add a second breadth first traversal (which comes first) over the dependency tree to accumulate all of the activated extras. Then, only in the second traversal do we actually build up the resolution graph. Unfortunately, I have no automatic regression test to include here. The regression test we _ought_ to include involves `torch`. And while we are generally find to use those in tests that only generate a lock file, the regression test here actually requires running installation. And downloading and installing `torch` in tests is bad juju. So adding a regression test for this is blocked on better infrastructure for PyTorch tests. With that said, I did manually verify that the test case in #10985 no longer installs multiple versions of `torch`. Fixes #10985
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
When I first added conflicting extras, I made
package[foo]
a harderror during resolution whenever
foo
was declared as a conflictingextra. This was a conservative approach meant to prevent cases where
conflicts occurred non-locally throughout the dependency tree.
However, as #9942 and #10590 seem to suggest, this ends up making
some use cases impossible. For example, it prevents the ability
to encapsulate the conflicting extras of a package from a parent
dependent. This overall makes conflicting extras much less flexible.
So in this PR, we remove that error checking. But doing so ends up
making it possible to install multiple versions of the same package
into the same environment. So we "recapture" the error check at
installation time instead of resolution time. This affords us more
flexibility, but it now means that we can generate lock files that will
always fail to install.
This is best reviewed commit-by-commit.
Fixes #9942, Fixes #10590