Resolver internals docs touchups (#5850)

This commit is contained in:
konsti 2024-08-07 10:32:31 +02:00 committed by GitHub
parent 2cd63f06dc
commit 68f186c409
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 27 deletions

View File

@ -1,4 +1,5 @@
.venv .venv
CHANGELOG.md CHANGELOG.md
PREVIEW-CHANGELOG.md PREVIEW-CHANGELOG.md
docs/reference/*.md docs/reference/cli.md
docs/reference/settings.md

View File

@ -8,10 +8,10 @@
## Resolver ## Resolver
As defined in a textbook, resolution, or finding a set of version to install from a given set of As defined in a textbook, resolution, or finding a set of version to install from a given set of
requirements, is equivalent to the [SAT requirements, is equivalent to the
problem](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem) and thereby NP-complete: in [SAT problem](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem) and thereby NP-complete:
the worst case you have to try all possible combinations of all versions of all packages and there in the worst case you have to try all possible combinations of all versions of all packages and
are no general, fast algorithms. In practice, this is misleading for a number of reasons: there are no general, fast algorithms. In practice, this is misleading for a number of reasons:
- The slowest part of resolution in uv is loading package and version metadata, even if it's cached. - The slowest part of resolution in uv is loading package and version metadata, even if it's cached.
- There are many possible solutions, but some are preferable than others. For example we generally - There are many possible solutions, but some are preferable than others. For example we generally
@ -30,34 +30,33 @@ uv uses [pubgrub-rs](https://github.com/pubgrub-rs/pubgrub), the Rust implementa
[PubGrub](https://nex3.medium.com/pubgrub-2fb6470504f), an incremental version solver. PubGrub in uv [PubGrub](https://nex3.medium.com/pubgrub-2fb6470504f), an incremental version solver. PubGrub in uv
works in the following steps: works in the following steps:
- Start with a partial solution that declares which packages versions have been selected and - Start with a partial solution that declares which packages versions have been selected and which
which are undecided. Initially, this may be all undecided. are undecided. Initially, only a virtual root package is decided.
- The highest priority package is selected from the undecided packages. Package with URLs (including - The highest priority package is selected from the undecided packages. Package with URLs (including
file, git, etc.) have the highest priority, then those with more exact specifiers (such as `==`), file, git, etc.) have the highest priority, then those with more exact specifiers (such as `==`),
then those with less strict specifiers. Inside each category, packages are ordered by when they then those with less strict specifiers. Inside each category, packages are ordered by when they
were first seen (i.e. order in a file), making the resolution deterministic. were first seen (i.e. order in a file), making the resolution deterministic.
- A version is picked for the selected package. The version must works with all specifiers from the - A version is picked for the selected package. The version must works with all specifiers from the
requirements in the partial solution and must not be previously marked as incompatible. The requirements in the partial solution and must not be previously marked as incompatible. The
resolver prefers versions from a lockfile (`uv.lock` or `-o requirements.txt`) and that are resolver prefers versions from a lockfile (`uv.lock` or `-o requirements.txt`) and those installed
installed in the current environment. Versions are checked from highest to lowest (unless using an in the current environment. Versions are checked from highest to lowest (unless using an
alternative [resolution strategy](../concepts/resolution.md#resolution-strategy)). alternative [resolution strategy](../concepts/resolution.md#resolution-strategy)).
- All requirements of the selected package version are added to the undecided packages. uv - All requirements of the selected package version are added to the undecided packages. uv
prefetches their metadata in the background to improve performance. prefetches their metadata in the background to improve performance.
- The process is either repeated with the next package unless a conflict is detected, in which the - The process is either repeated with the next package unless a conflict is detected, in which the
resolver will backtrack. For example, if the partial solution contains, among other packages, `a resolver will backtrack. For example, the partial solution contains, among other packages, `a 2`
2` then `b 2` with the requirements `a 2 -> c 1` and `b 2 -> c 2`. No compatible version of `c` then `b 2` with the requirements `a 2 -> c 1` and `b 2 -> c 2`. No compatible version of `c` can
can be found. PubGrub can determine this was caused by `a 2` and `b 2` and add the incompatibility be found. PubGrub can determine this was caused by `a 2` and `b 2` and add the incompatibility
`{a 2, b 2}`, meaning that when either is picked, the other cannot be selected. The partial solution is `{a 2, b 2}`, meaning that when either is picked, the other cannot be selected. The partial
restored to `a 2` with the tracked incompatibility and the resolver attempts to pick a new version solution is restored to `a 2` with the tracked incompatibility and the resolver attempts to pick a
for `b`. new version for `b`.
Eventually, the resolver either picks compatible versions for all packages (a successful resolution) Eventually, the resolver either picks compatible versions for all packages (a successful resolution)
or there is an incompatibility including the "root" package which defines the versions requested by or there is an incompatibility including the virtual "root" package which defines the versions
the user. An incompatibility with the root package indicates that whatever versions of the root requested by the user. An incompatibility with the root package indicates that whatever versions of
dependencies and their transitive dependencies are picked, there will always be a conflict. From the the root dependencies and their transitive dependencies are picked, there will always be a conflict.
incompatibilities tracked in PubGrub, an error message is constructed to enumerate the involved From the incompatibilities tracked in PubGrub, an error message is constructed to enumerate the
packages. involved packages.
!!! tip !!! tip
@ -67,8 +66,8 @@ packages.
## Forking ## Forking
Python resolvers historically didn't support backtracking, and even with backtracking, resolution Python resolvers historically didn't support backtracking, and even with backtracking, resolution
was usually limited to single environment, which one specific architecture, operating system, was usually limited to single environment, which one specific architecture, operating system, Python
Python version, and Python implementation. Some packages use contradictory requirements for different version, and Python implementation. Some packages use contradictory requirements for different
environments, for example: environments, for example:
```text ```text
@ -120,8 +119,8 @@ included Python versions, uv requires that all dependencies have the same minimu
Package versions that declare a higher minimum Python version, e.g., `requires-python = ">=3.10"`, Package versions that declare a higher minimum Python version, e.g., `requires-python = ">=3.10"`,
are rejected, because a resolution with that version can't be installed on Python 3.9. For are rejected, because a resolution with that version can't be installed on Python 3.9. For
simplicity and forward compatibility, only lower bounds in `requires-python` are respected. For simplicity and forward compatibility, only lower bounds in `requires-python` are respected. For
example, if a package declares `requires-python = ">=3.8,<4"`, the `<4` marker is not propagated example, if a package declares `requires-python = ">=3.8,<4"`, the `<4` marker is not propagated to
to the entire resolution. the entire resolution.
## Wheel tags ## Wheel tags