Consider installed packages during resolution#2596
Conversation
4bd3f16 to
dbe5cf9
Compare
charliermarsh
left a comment
There was a problem hiding this comment.
I think this generally looks good!
This is driving me a little crazy and is becoming a larger problem in #2596 where I need to move more types (like `Upgrade` and `Reinstall`) into this crate. Anything that's shared across our core resolver, install, and build crates needs to be defined in this crate to avoid cyclic dependencies. We've outgrown it being a single file with some shared traits. There are no behavioral changes here.
48e4bf0 to
18f36d6
Compare
| .ok_or(ResolveError::Unregistered)?; | ||
| self.visited.insert(package_name.clone()); | ||
|
|
||
| let empty_version_map = VersionMap::default(); |
There was a problem hiding this comment.
We need to initialize this for lifetimes since version_map is a reference.
There was a problem hiding this comment.
Alternatively we could have CandidateSelector.select take an Option<&VersionMap> but I opted for an empty iterable to avoid nesting in select instead. I'd consider revisiting this in the future as well.
There was a problem hiding this comment.
I think you can do let empty_version_map; here and then empty_version_map = VersionMap::default() in each branch if you want.
There was a problem hiding this comment.
Actually idk if that makes sense we're trying to return &VersionMap::default() in the match which is the problem?
e53df4c to
d9cf413
Compare
<!-- Thank you for contributing to uv! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> - Displays missing packages as single-line warnings. - Adds support for `Editable project location` and `Required-by` fields in `pip show`. Part of #2526. # Conflicts: # crates/uv-dispatch/src/lib.rs # crates/uv-resolver/src/resolver/mod.rs # crates/uv-resolver/tests/resolver.rs # crates/uv-traits/src/lib.rs # crates/uv/src/commands/pip_compile.rs # Conflicts: # crates/uv/src/commands/pip_sync.rs
5bca934 to
e2fbf2e
Compare
charliermarsh
left a comment
There was a problem hiding this comment.
This generally looks great to me.
| .ok_or(ResolveError::Unregistered)?; | ||
| self.visited.insert(package_name.clone()); | ||
|
|
||
| let empty_version_map = VersionMap::default(); |
There was a problem hiding this comment.
I think you can do let empty_version_map; here and then empty_version_map = VersionMap::default() in each branch if you want.
| && self | ||
| .installed_packages | ||
| .get_packages(package_name) | ||
| .is_empty() |
There was a problem hiding this comment.
I believe so but want to confirm: do you have any tests in which a package is already installed, but doesn't exist on the registry? I.e., exercising true for self.unavailable_packages.get(package_name).is_some() and false for the latter condition.
| { | ||
| debug_assert!( | ||
| false, | ||
| "Dependencies were requested for a package that is not available" |
There was a problem hiding this comment.
How do we even get here btw?
There was a problem hiding this comment.
Maybe a dumb question since there's a debug_assert! here anyway.
There was a problem hiding this comment.
Ah if a version map cannot be retrieved for a package we track the package in unavailable_packages but that's no longer the sole way to have a candidate for a package so this is kind of a lazy way of allowing installed packages dependencies to be retrieved even if they were not available in the index.
# Conflicts: # crates/distribution-types/src/lib.rs # crates/uv-dev/src/install_many.rs # crates/uv-resolver/src/finder.rs # crates/uv-resolver/src/lib.rs # crates/uv-resolver/src/manifest.rs # crates/uv-resolver/tests/resolver.rs # crates/uv/src/commands/pip_compile.rs # crates/uv/src/commands/pip_install.rs # crates/uv/src/commands/pip_sync.rs # crates/uv/src/commands/reporters.rs # crates/uv/tests/pip_sync.rs
5188ca6 to
3815e3e
Compare
9217532 to
59b58dc
Compare
|
I've addressed all the feedback from the review. |
…tion in the resolver (#2779) Addresses panic introduced in #2596 and reported in #2763 (comment) When there are multiple versions of a package available, we remove the existing packages before installing the resolved version to "fix" the environment. We must remove all of the package versions and reinstall because removing _any_ of the package versions could break the others. Since reinstalls require a pull from the remote, this broke a contract between the resolver and the planner which must always agree on which packages should come from the remote. This further demonstrates that we should be constructing the install plan with more concrete knowledge from the resolver (i.e. `ResolvedDist` instead of `Requirement`) to avoid having to manually ensure logic matches. ## Test plan Fails on `main` with panic succeeds on branch ``` uv venv --seed source .venv/bin/activate pip install anyio==3.7.0 --ignore-installed pip install anyio==4.0.0 --ignore-installed cargo run -- pip install anyio black -v ```
Previously, we did not consider installed distributions as candidates while performing resolution. Here, we update the resolver to use installed distributions that satisfy requirements instead of pulling new distributions from the registry.
The implementation details are as follows:
SitePackagesto theCandidateSelectorExclusionstype which tracks installed packages to ignore during selectionResolvedDistwrapper withInstalled(InstalledDist)andInstallable(Dist)variantsThe user-facing behavior is thoroughly covered in the tests, but briefly:
Closes #1661
Addresses:
uv pip install -e {package}#1476Test plan
charlesnicholson/uv-pep420-bugpasses[ ] Unit test for wheel not available in registry but already installed locally (#2282)(seems complicated and not worthwhile)pip compiledoes not consider installed packages