Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/reference/internals/resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,38 @@ numpy==2.0.0; python_version >= "3.9" and python_version < "3.10"
numpy==2.1.0; python_version >= "3.10"
```

## URL dependencies

In uv, a dependency can either be a registry dependency, a package with a version specifier or the
plain package name, or a URL dependency, everything with a `{name} @ {url}` or a `git`,` url`,
`path`, or `workspace` source, or put differently, all Git, remote file, local file or local path
dependencies.
Comment thread
konstin marked this conversation as resolved.
Outdated

When a URL is declared for a package, uv pins the package to this URL, and the version this URL
implies. If there are two conflicting URLs for a package, the resolver errors, as a URL can only be
declared as something akin to an exact `==` pin, and not as list of URLs. A list of URLs is
supported through [flat indexes](../../concepts/indexes.md#flat-indexes) instead.

uv requires that URLs are either declared directly (in the project, in a workspace member, in a
constraint, or in an override, any location that is discovered directly), or by other URL
Comment thread
konstin marked this conversation as resolved.
Outdated
dependencies. uv discovers all URL dependencies and their transitive URL dependencies ahead of the
resolution and pins all packages to the URLs and the versions they imply.

uv does not allow URLs in index packages. This has two reasons: One is a security and predictability
aspect, that forbids registry distributions to point to non-registry distributions and helps
auditing which URls can be accessed. For example, when only using one index URL and no URL
Comment thread
konstin marked this conversation as resolved.
Outdated
dependencies, uv will not install any package from outside the index.

The other is that URLs can add additional versions to the resolution, which either breaks an
assumption of the incremental resolver or would require to always fetch the metadata for all
versions. Say the root package depends on foo, bar, and baz, all registry dependencies. foo depends
on `bar >= 2`, but bar only has version 1 on the index. With the incremental approach, this is an
error, foo cannot be fulfilled, there is a resolver error. If URLs on index packages were allowed,
Comment thread
konstin marked this conversation as resolved.
Outdated
it could be that there is a version of baz declares a dependency on baz-core and that has a version
that declares `bar @ https://example.com/bar-2-py3-none-any.whl` adding a version of bar that makes
requirements resolve. If a dependency can add new versions, discarding any version in the resolver
would require looking at all possible versions of all direct and transitive dependencies.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words: this is a limitation of uv's resolver implementation. In order to keep resolution time (and memory usage I assume) reasonably low, it assumes that the version universe is fixed during resolution, and no new versions can be discovered during the process.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could theoretically make it possible by fetching everything ahead of time and checking, but having to check every version reachable ruins performance. iirc no package manager supports this, it's not really possible to write a performant tool if you can't be incremental, just from the cost of looking at all packages.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's hard to explain it with an example here to avoid having to explain the concept of resolution in the SAT sense and how you can't derive that a package-version in incompatible from a range of its dependency being exhaustively incompatible and how that's required to make both fast conclusions and to conclude failure for incompatible dependencies.


## Prioritization

Prioritization is important for both performance and for better resolutions.
Expand Down
Loading