-
Notifications
You must be signed in to change notification settings - Fork 8
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
Add forking scenarios that are unstable with preferences #203
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
In the first scenario, `preferences-dependent-forking`, we show how the resolution can be different the second time because we don't fork anymore because the preferences from the lockfile make us skip the fork point. This scenario is inspired by the same happening in the `transformer` repo, where a single universal resolution leads to a more desirable lock without duplicate versions. Consider a fresh run without preferences: * We start with cleaver 2 * We fork * We reject cleaver 2 * We find a cleaver 1 solution in fork 1 with foo 2 with bar 1 * We find a cleaver 1 solution in fork 2 with foo 1 with bar 2 * We write cleaver 1, foo 1, foo 2, bar 1 and bar 2 to the lockfile In a subsequent run, we read the preference cleaver 1 from the lockfile (the preferences for foo and bar don't matter): * We start with cleaver 1 * We're in universal mode, we resolve foo 1 and bar 1 * We write cleaver 1 and bar 1 to the lockfile We call a resolution that's different between first and second run unstable. Design sketch: ```text root -> cleaver, foo, bar # Cause a fork, then forget that version. cleaver 2 -> unrelated-dep==1; fork==1 cleaver 2 -> unrelated-dep==2; fork==2 cleaver 2 -> reject-cleaver-2 # Allow diverging versions when forking, but force foo 1, bar 1 in universal mode without forking. cleaver 1 -> foo==1; fork==1 cleaver 1 -> bar==1; fork==2 ``` Let's try this out: ```toml [project] name = "dummy" version = "0.1.0" requires-python = ">=3.12" dependencies = [ "preferences-dependent-forking-5c5f76e6" ] [tool.uv] index-url = "http://127.0.0.1:3141/" ``` Cleanup and first, fresh run without preferences, on linux: ```console $ rm -f uv.lock $ uv venv -q $ cargo run -q -- sync --preview Resolved 6 packages in 647ms Built dummy @ file:///home/konsti/projects/uv/debug/dummy Built preferences-dependent-forking-5c5f76e6==0.0.0 Prepared 2 packages in 457ms Installed 5 packages in 1ms + dummy==0.1.0 (from file:///home/konsti/projects/uv/debug/dummy) + preferences-dependent-forking-5c5f76e6==0.0.0 + preferences-dependent-forking-bar-5c5f76e6==1.0.0 + preferences-dependent-forking-cleaver-5c5f76e6==1.0.0 + preferences-dependent-forking-foo-5c5f76e6==2.0.0 ``` Second run, using the preferences from the lockfile: ```console $ cargo run -q -- sync --preview Resolved 5 packages in 113ms Uninstalled 1 package in 0.57ms Installed 1 package in 1ms - preferences-dependent-forking-foo-5c5f76e6==2.0.0 + preferences-dependent-forking-foo-5c5f76e6==1.0.0 ``` The logs confirm that in the first run with fork, while in the second we don't. In the second scenario `preferences-dependent-forking-conflicting`, we add `foo 1 -> bar==2` so that the resolving cleaver 1 fails without forking: ```toml [project] name = "dummy" version = "0.1.0" requires-python = ">=3.12" dependencies = [ "preferences-dependent-forking-conflicting-5f0792c1" ] [tool.uv] index-url = "http://127.0.0.1:3141/" ``` Cleanup and first, fresh run, on linux: ```console $ rm -f uv.lock $ uv venv -q $ cargo run -q -- sync --preview Resolved 7 packages in 166ms Built dummy @ file:///home/konsti/projects/uv/debug/dummy Prepared 1 package in 489ms Installed 5 packages in 1ms + dummy==0.1.0 (from file:///home/konsti/projects/uv/debug/dummy) + preferences-dependent-forking-conflicting-5f0792c1==0.0.0 + preferences-dependent-forking-conflicting-bar-5f0792c1==2.0.0 + preferences-dependent-forking-conflicting-cleaver-5f0792c1==1.0.0 + preferences-dependent-forking-conflicting-foo-5f0792c1==2.0.0 ``` In the second run, we're using the preferences from the lockfile. We reject preference cleaver 1 in universal mode, then move to cleaver 2, fork, and fail in one of the forks by the cleaver 2 rejecting package: ```console $ cargo run -q -- sync --preview × No solution found when resolving dependencies for split (sys_platform != 'linux'): ╰─▶ Because preferences-dependent-forking-conflicting-foo-5f0792c1==1.0.0 depends on preferences-dependent-forking-conflicting-bar-5f0792c1==2 and preferences-dependent-forking-conflicting-cleaver-5f0792c1==1.0.0 depends on preferences-dependent-forking-conflicting-foo-5f0792c1{sys_platform == 'linux'}==1, we can conclude that preferences-dependent-forking-conflicting-cleaver-5f0792c1==1.0.0 depends on preferences-dependent-forking-conflicting-bar-5f0792c1==2. And because preferences-dependent-forking-conflicting-cleaver-5f0792c1==1.0.0 depends on preferences-dependent-forking-conflicting-bar-5f0792c1{sys_platform != 'linux'}==1 and only the following versions of preferences-dependent-forking-conflicting-cleaver-5f0792c1 are available: preferences-dependent-forking-conflicting-cleaver-5f0792c1==1.0.0 preferences-dependent-forking-conflicting-cleaver-5f0792c1==2.0.0 we can conclude that preferences-dependent-forking-conflicting-cleaver-5f0792c1<2.0.0 cannot be used. (1) Because preferences-dependent-forking-conflicting-reject-cleaver-2-5f0792c1==1.0.0 depends on preferences-dependent-forking-conflicting-unrelated-dep-5f0792c1==3 and only preferences-dependent-forking-conflicting-reject-cleaver-2-5f0792c1==1.0.0 is available, we can conclude that all versions of preferences-dependent-forking-conflicting-reject-cleaver-2-5f0792c1 and preferences-dependent-forking-conflicting-unrelated-dep-5f0792c1{sys_platform != 'linux'}==2.0.0 are incompatible. And because preferences-dependent-forking-conflicting-cleaver-5f0792c1==2.0.0 depends on preferences-dependent-forking-conflicting-unrelated-dep-5f0792c1{sys_platform != 'linux'}==2 and preferences-dependent-forking-conflicting-reject-cleaver-2-5f0792c1, we can conclude that preferences-dependent-forking-conflicting-cleaver-5f0792c1==2.0.0 cannot be used. And because we know from (1) that preferences-dependent-forking-conflicting-cleaver-5f0792c1<2.0.0 cannot be used, we can conclude that all versions of preferences-dependent-forking-conflicting-cleaver-5f0792c1 cannot be used. And because preferences-dependent-forking-conflicting-5f0792c1==0.0.0 depends on preferences-dependent-forking-conflicting-cleaver-5f0792c1, we can conclude that preferences-dependent-forking-conflicting-5f0792c1==0.0.0 cannot be used. And because only preferences-dependent-forking-conflicting-5f0792c1==0.0.0 is available and dummy==0.1.0 depends on preferences-dependent-forking-conflicting-5f0792c1, we can conclude that dummy==0.1.0 cannot be used. And because only dummy==0.1.0 is available and you require dummy, we can conclude that the requirements are unsatisfiable. ``` The logs confirm that we fork in both runs. I don't know whether this scenario should be tagged `satisfiable` yet or not.
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.
In the first scenario,
preferences-dependent-forking
, we show how the resolution can be different the second time because we don't fork anymore because the preferences from the lockfile make us skip the fork point. This scenario is inspired by the same happening in thetransformer
repo, where a single universal resolution leads to a more desirable lock without duplicate versions.Consider a fresh run without preferences:
In a subsequent run, we read the preference cleaver 1 from the lockfile (the preferences for foo and bar don't matter):
We call a resolution that's different between first and second run unstable.
Design sketch:
Let's try this out:
Cleanup and first, fresh run without preferences, on linux:
Second run, using the preferences from the lockfile:
The logs confirm that in the first run with fork, while in the second we don't.
In the second scenario
preferences-dependent-forking-conflicting
, we addfoo 1 -> bar==2
so that the resolving cleaver 1 fails without forking:Cleanup and first, fresh run, on linux:
In the second run, we're using the preferences from the lockfile. We reject preference cleaver 1 in universal mode, then move to cleaver 2, fork, and fail in one of the forks by the cleaver 2 rejecting package:
The logs confirm that we fork in both runs.
I don't know whether this scenario should be tagged
satisfiable
yet or not.