mirror of https://github.com/astral-sh/uv
Resolver internals docs touchups (#5850)
This commit is contained in:
parent
2cd63f06dc
commit
68f186c409
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue