Commit graph

693 commits

Author SHA1 Message Date
Ibraheem Ahmed
bb73edb03b
Respect local versions for all user requirements (#5232)
## Summary

This fixes a few bugs introduced by
https://github.com/astral-sh/uv/pull/5104. I previously thought we could
track conflicting locals the same way we track conflicting URLs in
forks, but it turns out that ends up being very tricky. URL forks work
because we prioritize directly URL requirements. We can't prioritize
locals in the same way without conflicting with the URL prioritization
(this may be possible but it's not trivial), so we run into issues where
a correct resolution depends on the order in which dependencies are
traversed.

Instead, we track local versions across all forks in `Locals`. When
applying a local version, we apply all locals with markers that
intersect with the current fork. This way we end up applying some local
versions without creating a fork. For example, given:
```
// pyproject.toml
dependencies = [
    "torch==2.0.0+cu118 ; platform_machine == 'x86_64'",
]

// requirements.in
torch==2.0.0
.
```

We choose `2.0.0+cu118` in all cases. However, if a disjoint fork is
created based on local versions, the resolver will choose the most
compatible local when it narrows to a specific fork. Thus we correctly
respect local versions when forking:
```
// pyproject.toml
dependencies = [
    "torch==2.0.0+cu118 ; platform_machine == 'x86_64'",
    "torch==2.0.0+cpu ; platform_machine != 'x86_64'"
]

// requirements.in
torch==2.0.0
.
``` 

We should also be able to use a similar strategy for
https://github.com/astral-sh/uv/pull/5150.

## Test Plan

This fixes https://github.com/astral-sh/uv/issues/5220 locally for me,
as well as a few other bugs that were not reported yet.
2024-07-19 16:56:09 -05:00
Charlie Marsh
ed9b820815
Remove trailing period from user-facing messages (#5218)
## Summary

Per #5209, we only show periods in messages when the message itself
spans more than a single sentence.
2024-07-19 10:43:49 -04:00
Charlie Marsh
fb1a529106
Process completed Python installs and uninstalls as a stream (#5203)
## Summary

This ensures that we process Python installs and uninstalls as soon as
they complete, rather than waiting for them all to complete, then
processing them sequentially. In practice, it shouldn't be much of a
difference (since the processing is code is fairly light), but it
strikes me as more correct.
2024-07-19 12:50:38 +00:00
konsti
93ba676f2e
Log origin of version selection (#5186)
Log whether a version was picked because it was the next version or
because it was a preference (installed, lockfile or sibling fork)
2024-07-19 08:15:45 +00:00
konsti
5bcdaedf8b
Merge extras in lockfile (#5181)
As user, you specify a list of extras. Internally, we decompose this
into one virtual package per extra. We currently leak this abstraction
by writing one entry per extra to the lockfile:

```toml
[[distribution]]
name = "foo"
version = "4.39.0.dev0"
source = { editable = "." }
dependencies = [
    { name = "pandas" },
    { name = "pandas", extra = "excel" },
    { name = "pandas", extra = "hdf5" },
    { name = "pandas", extra = "html", marker = "os_name != 'posix'" },
    { name = "pandas", extra = "output-formatting", marker = "os_name == 'posix'" },
    { name = "pandas", extra = "plot", marker = "os_name == 'posix'" },
]
```

Instead, we should merge the extras into a list of extras, creating a
more concise lockfile:

```toml
[[distribution]]
name = "foo"
version = "4.39.0.dev0"
source = { editable = "." }
dependencies = [
    { name = "pandas", extra = ["excel", "hdf5"] },
    { name = "pandas", extra = ["html"], marker = "os_name != 'posix'" },
    { name = "pandas", extra = ["output-formatting", "plot"], marker = "os_name == 'posix'" },
]
```

The base package is now implicitly included, as it is in PEP 508.

Fixes #4888
2024-07-18 14:07:49 -04:00
Ibraheem Ahmed
bbd65fc626
Set exact version specifiers when resolving from lockfile (#5193)
## Summary

Should resolve https://github.com/astral-sh/uv/issues/5192.

## Test Plan

@konstin can you confirm this fixes your issue?
2024-07-18 19:02:08 +02:00
konsti
fbb00f701c
Warn about unconstrained direct deps in lowest resolution (#5142)
Warn when there is a direct dependency without a lower bound and
`--resolution lowest` is set.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-07-18 03:44:53 +00:00
Charlie Marsh
6a49dba30c
Enforce hashes in lockfile install (#5170)
## Summary

Hashes will be validated if present, but aren't required (since, e.g.,
some registries will omit them, as will Git dependencies and such).

Closes https://github.com/astral-sh/uv/issues/5168.
2024-07-17 23:10:37 +00:00
Charlie Marsh
218ae2c13e
Key hash policy on version, rather than package (#5169)
## Summary

First part of: https://github.com/astral-sh/uv/issues/5168.
2024-07-17 19:01:49 -04:00
Charlie Marsh
ba4e2e3d2a
Use the strongest hash in the lockfile (#5167)
## Summary

We only need to store one hash -- it should be the "strongest" hash. In
practice, most registries (like PyPI) only serve one, and we only
compute a SHA256 hash for direct URLs.

Part of: https://github.com/astral-sh/uv/issues/4924

## Test Plan

I verified that changing:

```diff
diff --git a/crates/distribution-types/src/hash.rs b/crates/distribution-types/src/hash.rs
index 553a74f55..d36c62286 100644
--- a/crates/distribution-types/src/hash.rs
+++ b/crates/distribution-types/src/hash.rs
@@ -31,7 +31,7 @@ impl<'a> HashPolicy<'a> {
     pub fn algorithms(&self) -> Vec<HashAlgorithm> {
         match self {
             Self::None => vec![],
-            Self::Generate => vec![HashAlgorithm::Sha256],
+            Self::Generate => vec![HashAlgorithm::Sha256, HashAlgorithm::Sha512],
             Self::Validate(hashes) => {
                 let mut algorithms = hashes.iter().map(HashDigest::algorithm).collect::<Vec<_>>();
                 algorithms.sort();
```

Then running `uv lock` with a URL gave me:

```toml
[[distribution]]
name = "iniconfig"
version = "2.0.0"
source = { url = "62565a6e1c/iniconfig-2.0.0-py3-none-any.whl" }
wheels = [
    { url = "62565a6e1c/iniconfig-2.0.0-py3-none-any.whl", hash = "sha512:44cc53a6c8dd7cf4d6d52bded308bcc4b4f85fff2ed081f60f7d4beaa86a7cde6d099e3976331232d4cbd472ad5d1781064725b0999c7cd3a2a4d42df687ee81" },
]
```
2024-07-17 20:38:33 +00:00
Charlie Marsh
e271d1fdde
Make registry hashes optional in the lockfile (#5166)
## Summary

If a registry doesn't include hashes, then we won't include them in the
lockfile either.

Part of: https://github.com/astral-sh/uv/issues/4924.

Closes: https://github.com/astral-sh/uv/issues/5120.
2024-07-17 16:29:49 -04:00
konsti
a6dfd3953a
Handle universal vs. fork markers with ResolverMarkers (#5099)
* Use a dedicated `ResolverMarkers` check in the fork state. This is
better than the `MarkerTree::And(Vec::new())` check.
* Report the timing correct naming universal resolution instead of two
spaces around an empty string when there are no markers.
* On resolution error, show the split that we're in. I'm not sure how to
word this, since we're doing a universal resolution until we fork, so
the trace may contain information from requirements that are not part of
this fork.
2024-07-17 18:59:33 +02:00
Ahmed Ilyas
eb35c05b89
Indicate that uv lock --upgrade has updated the lock file (#5110)
## Summary

Resolves #4346, I've gone with the suggested `cargo` approach here.

## Test Plan

`cargo test`

```console
❯ ../target/debug/uv lock --upgrade
warning: `uv lock` is experimental and may change without warning.
Resolved 11 packages in 41ms
Updating flask v2.3.3 -> v3.0.3
note: pass `--verbose` to see 9 unchanged dependencies
❯ ../target/debug/uv lock --upgrade -vv
    0.002478s DEBUG uv uv 0.2.24
warning: `uv lock` is experimental and may change without warning.
....
Resolved 11 packages in 50ms
    0.103703s DEBUG uv::commands::project::lock Unchanged blinker v1.8.2
    0.103719s DEBUG uv::commands::project::lock Unchanged click v8.1.7
    0.103731s DEBUG uv::commands::project::lock Unchanged colorama v0.4.6
    0.103742s DEBUG uv::commands::project::lock Unchanged flask v3.0.3
    0.103754s DEBUG uv::commands::project::lock Unchanged importlib-metadata v8.0.0
    0.103767s DEBUG uv::commands::project::lock Unchanged itsdangerous v2.2.0
    0.103778s DEBUG uv::commands::project::lock Unchanged jinja2 v3.1.4
    0.103788s DEBUG uv::commands::project::lock Unchanged markupsafe v2.1.5
    0.103798s DEBUG uv::commands::project::lock Unchanged werkzeug v3.0.3
    0.103809s DEBUG uv::commands::project::lock Unchanged zipp v3.19.2
```
2024-07-17 01:14:20 +00:00
Ibraheem Ahmed
d583847f8b
Allow conflicting locals when forking (#5104)
## Summary

Currently, the `Locals` type relies on there being a single local
version for a given package. With marker expressions this may not be
true, a similar problem to https://github.com/astral-sh/uv/pull/4435.
This changes the `Locals` type to `ForkLocals`, which tracks locals for
a given fork. Local versions are now tracked on `PubGrubRequirement`
before forking.

Resolves https://github.com/astral-sh/uv/issues/4580.
2024-07-16 16:57:30 +00:00
Andrew Gallant
048ae8f7f3 uv-resolver: add TRACE dump of resolver output
Specifically, this shows the resolution produced by the
resolver *before* constructing a resolution graph.

Unlike most trace messages, this is a multi-line message
that needs to do some small amount of work to build
itself. So we do an explicit gating on the log level here
instead of just relying on the `trace!` macro itself.
2024-07-16 09:51:54 -07:00
Charlie Marsh
9a44bc1d35
Filter out invalid wheels based on requires-python (#5084)
## Summary

The example in the linked issue doesn't quite work, but I think it has
to do with the existing filtering logic. Will follow-up separately.

Closes https://github.com/astral-sh/uv/issues/5012.
2024-07-15 21:01:38 -04:00
Andrew Gallant
563507edba uv-resolver: add support for incomplete markers
In some cases, it's possible for the marker expressions on conflicting
dependency specification to be disjoint but *incomplete*. That is, if
one unions the disjoint markers, the result is not the complete set of
marker environments possible. There may be some "gap" of marker
environments not covered by the markers.

This is a problem in practice because, before this commit, we only
created forks in the resolver for specific marker expressions. So if a
dependency happened to fall in a "gap," our resolver would never see it.

This commit fixes this by adding a new split covering the negation of
the union of all marker expressions in a set of forks for a specific
package.

Originally, I had planned on only creating this split when it was known
that the gap actually existed. That is, when the negation of the marker
expressions did *not* correspond to the empty set. After a lot of
thought, unfortunately, this (I believe) effectively boils down to 3SAT,
which is NP-complete.

Instead, what we do here is *always* create an extra split unless we can
definitively tell that it is empty. We look for a few cases, but
otherwise throw our hands up and potentially do wasted work.

This also updates the lock scenario tests to reflect the actual bug fix
here.
2024-07-15 10:09:01 -07:00
konsti
e34ab96e80
Remove special casing from no solution error (#5067)
The only pubgrub error that can occur is a `NoSolutionError`, and the
only place it can occur is `unit_propagation`, all other variants if
`PubGrubError` are unreachable. By changing the return type on pubgrub's
side (https://github.com/astral-sh/pubgrub/pull/28), we can remove the
pattern matching and the `unreachable!()` asserts on `PubGrubError`.

Our pubgrub error wrapper used to have a two phased initialization,
first mostly stubs in `solve[_tracked]()` and then adding the actual
context in `resolve()`. When constructing the error in `solve` we
already have all this context, so we can unify this to a regular
constructor and remove the special casing in `resolve()` and `hints()`.
2024-07-15 17:43:35 +02:00
konsti
f3430c3a2a
Improve error message when package has no installation candidates (#5010)
Currently, with
```toml
[project]
name = "transformers"
version = "4.39.0.dev0"
requires-python = ">=3.10"
dependencies = [
  "torch==1.10.0"
]
```
i get
```
$ uv sync --preview
Resolved 3 packages in 7ms
error: found distribution torch==1.10.0 @ registry+https://pypi.org/simple with neither wheels nor source distribution
```
This error message is wrong, there are wheels, they are just not
compatible. I initially got this error message during `uv lock` (in a
build), so i also added that this is about installation, not about
locking.

We should reject this version immediately because with the current
requires python, it can never be installed, but even then we need to
change the error message because you can be on the correct python
version, but an unsupported platform.
2024-07-15 00:00:40 +00:00
Charlie Marsh
a571150949
Normalize out complementary == or != markers (#5050)
## Summary

Closes https://github.com/astral-sh/uv/issues/5044.
2024-07-14 23:53:58 +00:00
Ibraheem Ahmed
ba217f1059
Use lockfile to prefill resolver index (#4495)
## Summary

Use the lockfile to prefill the `InMemoryIndex` used by the resolver.
This enables us to resolve completely from the lockfile without making
any network requests/builds if the requirements are unchanged. It also
means that if new requirements are added we can still avoid most I/O
during resolution, partially addressing
https://github.com/astral-sh/uv/issues/3925.

The main limitation of this PR is that resolution from the lockfile can
fail if new versions are requested that are not present in the lockfile,
in which case we have to perform a fresh resolution. Fixing this would
likely require lazy version/metadata requests by `VersionMap` (this is
different from the lazy parsing we do, the list of versions in a
`VersionMap` is currently immutable).

Resolves https://github.com/astral-sh/uv/issues/3892.

## Test Plan

Added a `deterministic!` macro that ensures that a resolve from the
lockfile and a clean resolve result in the same lockfile output for all
our current tests.
2024-07-12 18:49:28 -04:00
Ibraheem Ahmed
a1f71a36e7
Fix substring marker expression disjointness checks (#4998)
## Summary

Noticed a bug here, `'a' in env` and `env not in 'a'` are not disjoint
given `env == 'ab'`.
2024-07-12 15:21:21 +00:00
Ibraheem Ahmed
d833910a5d
Avoid reparsing wheel URLs (#4947)
## Summary

We currently store wheel URLs in an unparsed state because we don't have
a stable parsed representation to use with rykv. Unfortunately this
means we end up reparsing unnecessarily in a lot of places, especially
when constructing a `Lock`. This PR adds a `UrlString` type that lets us
avoid reparsing without losing the validity of the `Url`.

## Test Plan

Shaves off another ~10 ms from
https://github.com/astral-sh/uv/issues/4860.

```
➜  transformers hyperfine "../../uv/target/profiling/uv lock" "../../uv/target/profiling/baseline lock" --warmup 3
Benchmark 1: ../../uv/target/profiling/uv lock
  Time (mean ± σ):     120.9 ms ±   2.5 ms    [User: 126.0 ms, System: 80.6 ms]
  Range (min … max):   116.8 ms … 125.7 ms    23 runs
 
Benchmark 2: ../../uv/target/profiling/baseline lock
  Time (mean ± σ):     129.9 ms ±   4.2 ms    [User: 127.1 ms, System: 86.1 ms]
  Range (min … max):   123.4 ms … 141.2 ms    23 runs

Summary
  ../../uv/target/profiling/uv lock ran
    1.07 ± 0.04 times faster than ../../uv/target/profiling/baseline lock
```
2024-07-10 05:16:30 -04:00
Charlie Marsh
23eb42deed
Allow constraints to be provided in --upgrade-package (#4952)
## Summary

Allows, e.g., `--upgrade-package flask<3.0.0`.

Closes https://github.com/astral-sh/uv/issues/1964.
2024-07-09 20:09:13 -07:00
Ibraheem Ahmed
8c9bd70c71
Avoid serializing if lockfile does not change (#4945)
## Summary

Avoid serializing and writing the lockfile if a cheap comparison shows
that the contents have not changed.

## Test Plan

Shaves ~10ms off of https://github.com/astral-sh/uv/issues/4860 for me.

```
➜  transformers hyperfine "../../uv/target/profiling/uv lock" "../../uv/target/profiling/baseline lock" --warmup 3
Benchmark 1: ../../uv/target/profiling/uv lock
  Time (mean ± σ):     130.5 ms ±   2.5 ms    [User: 130.3 ms, System: 85.0 ms]
  Range (min … max):   126.8 ms … 136.9 ms    23 runs
 
Benchmark 2: ../../uv/target/profiling/baseline lock
  Time (mean ± σ):     140.5 ms ±   5.0 ms    [User: 142.8 ms, System: 85.5 ms]
  Range (min … max):   133.2 ms … 153.3 ms    21 runs
 
Summary
  ../../uv/target/profiling/uv lock ran
    1.08 ± 0.04 times faster than ../../uv/target/profiling/baseline lock
```
2024-07-09 17:08:27 -04:00
konsti
53db63f6dd
Apply extra to overrides and constraints (#4829)
This is an attempt to solve https://github.com/astral-sh/uv/issues/ by
applying the extra marker of the requirement to overrides and
constraints.

Say in `a` we have a requirements
```
b==1; python_version < "3.10"
c==1; extra == "feature"
```

and overrides
```
b==2; python_version < "3.10"
b==3; python_version >= "3.10"
c==2; python_version < "3.10"
c==3; python_version >= "3.10"
```

Our current strategy is to discard the markers in the original
requirements. This means that on 3.12 for `a` we install `b==3`, but it
also means that we add `c` to `a` without `a[feature]`, causing #4826.
With this PR, the new requirement become,

```
b==2; python_version < "3.10"
b==3; python_version >= "3.10"
c==2; python_version < "3.10" and extra == "feature"
c==3; python_version >= "3.10" and extra == "feature"
```

allowing to override markers while preserving optional dependencies as
such.

Fixes #4826
2024-07-09 20:37:24 +02:00
Charlie Marsh
72dd34b225
Filter out markers based on Python requirement (#4912)
## Summary

In marker normalization, we now remove any markers that are redundant
with the `requires-python` specifier (i.e., always true for the given
Python requirement).

For example, given `iniconfig ; python_version >= '3.7'`, we can remove
the `python_version >= '3.7'` marker when resolving with
`--python-version 3.8`.

Closes #4852.
2024-07-09 09:15:58 -07:00
Charlie Marsh
a046d23f79
Avoid AND-ing multi-term specifiers in marker normalization (#4911)
## Summary

Given `python_version != '3.8' and python_version < '3.10'`, the first
term was expanded to `python_version < '3.8'` and `python_version >
'3.8'`. We then AND'd all three terms together. We don't seem to have a
way to differentiate between the terms to AND and the terms to OR in the
normalization code (it all gets flattened together), so instead this PR
expands the expressions at the leaf level and then flattens them at the
level above when appropriate.

Closes https://github.com/astral-sh/uv/issues/4910.
2024-07-09 16:04:26 +00:00
Ibraheem Ahmed
ed4234d52e
Filter and flatten markers (#4639)
## Summary

More marker simplification:
- Filters out redundant subtrees based on outer expressions, e.g. `a and (a or
b)` simplifies to `a`.
- Flattens nested trees internally, e.g. `(a and b) and c`

Resolves https://github.com/astral-sh/uv/issues/4536.
2024-07-08 18:59:21 +00:00
Ibraheem Ahmed
dc7ad3abdb
Implement uv tree (#4708)
## Summary

Implements the `uv tree`, which displays dependencies from the lockfile
as a tree. Resolves https://github.com/astral-sh/uv/issues/4699.
2024-07-08 18:07:48 +00:00
Andrew Gallant
857d2e8f1e uv-resolver: partially revert Requires-Python version narrowing
The PR #4707 introduced the notion of "version narrowing," where a
Requires-Python constraint was _possibly_ narrowed whenever the
universal resolver created a fork. The version narrowing would occur
when the fork was a result of a marker expression on `python_version`
that is *stricter* than the configured `Requires-Python` (via, say,
`pyproject.toml`).

The crucial conceptual change made by #4707 is therefore that
`Requires-Python` is no longer an invariant configuration of resolution,
but rather a mutable constraint that can vary from fork to fork. This in
turn can result in some cases, such as in #4885, where different
versions of dependencies are selected. We aren't sure whether we can fix
those or not, with version narrowing, so for now, we do this revert to
restore the previous behavior and we'll try to address the version
narrowing some other time.

This also adds the case from #4885 as a regression test, ensuring that
we don't break that in the future. I confirmed that with version
narrowing, this test outputs duplicate distributions. Without narrowing,
there are no duplicates.

Ref #4707, Fixes #4885
2024-07-08 09:56:59 -07:00
Charlie Marsh
ac3a085084
Respect requires-python when prefetching (#4900)
## Summary

This is fallout from https://github.com/astral-sh/uv/pull/4705. We need
to respect `requires-python` in the prefetch code to avoid building
unsupported distributions.

Closes https://github.com/astral-sh/uv/issues/4898.
2024-07-08 16:32:09 +00:00
Charlie Marsh
71c6a9fad3
Sort dependencies before wheels and source distributions (#4897)
Closes https://github.com/astral-sh/uv/issues/4889.
2024-07-08 14:25:05 +00:00
konsti
57cfe1e229
Small forking log improvements (#4894)
I found the current messages insufficient when tracking down a bug.
2024-07-08 13:56:57 +00:00
konsti
d787e69f7c
Rename Workspace.root to Workspace.install_path (#4859)
Renaming in preparation of #4833, which adds a `Workspace.lock_path`. No
functional changes.
2024-07-07 18:35:41 +00:00
Charlie Marsh
b588054dfb
Always use release-only comparisons for requires-python (#4794)
## Summary

There are a few ideas at play here:

1. pip always strips versions to the release when evaluating against a
`Requires-Python`, so we now do the same. That means, e.g., using
`3.13.0b0` will be accepted by a project with `Requires-Python: >=
3.13`, which does _not_ adhere to PEP 440 semantics but is somewhat
intuitive.
2. Because we know we'll only be evaluating against release-only
versions, we can use different semantics in PubGrub that let us collapse
ranges. For example, `python_version >= '3.10' or python_version <
'3.10'` can be collapsed to the truthy marker.

Closes https://github.com/astral-sh/uv/issues/4714.
Closes https://github.com/astral-sh/uv/issues/4272.
Closes https://github.com/astral-sh/uv/issues/4719.
2024-07-04 20:06:52 +00:00
konsti
11cb0059c1
Remove incompatible wheels from uv.lock (#4799)
Remove wheels from the lockfile that don't match the required python
version. For example, we remove
`charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl` when we have
`requires-python = ">=3.12"`.

Our snapshots barely show changes since we avoid the large binaries for
which matters. Here are 3 real world `uv.lock` before/after comparisons
to show the large difference:
*
[warehouse](https://gist.github.com/konstin/9a1ed6a32b410e250fcf4c6ea8c536a5)
(5677 -> 4214)
*
[transformers](https://gist.github.com/konstin/5636281b5226f64aa44ce3244d5230cd)
(6484 -> 5816)
*
[github-wikidata-bot](https://gist.github.com/konstin/ebbd7b9474523aaa61d9a8945bc02071)
(793 -> 454)

We only remove wheels we are certain don't match the python version and
still keep those with unknown tags. We could remove even more wheels by
also considering other markers, e.g. removing linux wheels for a
windows-only dep, but we would trade complex, easy-to-get-wrong logic
for diminishing returns.
2024-07-04 14:03:54 -04:00
konsti
d178d97a40
Document the RequiresPython fields (#4798) 2024-07-04 08:27:02 -04:00
Zanie Blue
dd7da6af5f
Change "toolchain" to "python" (#4735)
Whew this is a lot.

The user-facing changes are:

- `uv toolchain` to `uv python` e.g. `uv python find`, `uv python
install`, ...
- `UV_TOOLCHAIN_DIR` to` UV_PYTHON_INSTALL_DIR`
- `<UV_STATE_DIR>/toolchains` to `<UV_STATE_DIR>/python` (with
[automatic
migration](https://github.com/astral-sh/uv/pull/4735/files#r1663029330))
- User-facing messages no longer refer to toolchains, instead using
"Python", "Python versions" or "Python installations"

The internal changes are:

- `uv-toolchain` crate to `uv-python`
- `Toolchain` no longer referenced in type names
- Dropped unused `SystemPython` type (previously replaced)
- Clarified the type names for "managed Python installations"
- (more little things)
2024-07-03 07:44:29 -05:00
Ibraheem Ahmed
a380e8e4df
Add conversion from lockfile Distribution to Metadata (#4706)
## Summary

Splitting this out from https://github.com/astral-sh/uv/pull/4495
because it's also useful to reuse the `uv pip tree` code for `uv tree`.
2024-07-02 18:03:20 +00:00
Charlie Marsh
d9f389a58d
Narrow requires-python requirement in resolver forks (#4707)
## Summary

Given:

```text
numpy >=1.26 ; python_version >= '3.9'
numpy <1.26 ; python_version < '3.9'
```

When resolving for Python 3.8, we need to narrow the `requires-python`
requirement in the top branch of the fork, because `numpy >=1.26` all
require Python 3.9 or later -- but we know (in that branch) that we only
need to _solve_ for Python 3.9 or later.

Closes https://github.com/astral-sh/uv/issues/4669.
2024-07-02 12:23:38 +00:00
Charlie Marsh
89b3324ae1
Move Requires-Python incompatibilities out of version map (#4705)
## Summary

This is required to solve https://github.com/astral-sh/uv/issues/4669,
because the `Requires-Python` version can now vary across a resolution.
For example, within certain forks, we might have a more narrow range,
which would allow us to use distributions that would not be allowed for
the global resolution.

This should be fine because `requires-python` is part of the package
metadata, so it should be consistent between files within a package
version. As such, there shouldn't be any risk that we incorrectly
prioritize distributions by omitting this information.

(To be more specific, the risk is something like: we prioritize some
wheel over a source distribution within a package-version, so we don't
track the source distribution at all. Then, later, when we choose a
candidate, we see that the wheel doesn't meet the `Requires-Python`
requirement, even though the source distribution _would've_ met it. If
files within a distribution could have varied support, this would be a
real risk.)
2024-07-02 08:15:39 -04:00
Charlie Marsh
f3d1e52e65
Use requires-python semantics for --universal (#4701)
## Summary

This doesn't actually change any behaviors, but it does make it a bit
easier to solve #4669, because we don't have to support "version
narrowing" for the non-`RequiresPython` variants in here. Right now, the
semantics are kind of muddied, because the `target` variant is
_sometimes_ interpreted as an exact version and sometimes as a lower
bound.
2024-07-01 15:16:40 -04:00
konsti
0ee4a2cc6e
Remove SolveState to ForkState (#4683)
It's hard to talk about solve state and resolver state, so i'm renaming
them to fork state and resolver state, indicating the hierarchy between
more directly.
2024-07-01 12:33:50 -04:00
Charlie Marsh
977a5c8835
Use a single mutable preferences for forks (#4690)
## Summary

Avoids a quadratic loop.

See: https://github.com/astral-sh/uv/pull/4662.
2024-07-01 12:47:28 +00:00
Charlie Marsh
2d57309b0f
Set fork solution as preference when resolving (#4662)
## Summary

This should both make it faster to solve forks (since we have a guess
for a valid resolution, and will bias towards packages we've already
fetched) and improve consistency between forks.

Closes https://github.com/astral-sh/uv/issues/4617.
2024-07-01 08:25:40 -04:00
konsti
049833e037
Log when we start solving a fork (#4684)
Adds a debug log message with the markers.
2024-07-01 08:46:54 +00:00
Charlie Marsh
ac87fd4006
Disable Clippy's too-many-arguments rule (#4663)
## Summary

We allow this constantly, I think it's just too pedantic for us.
2024-06-30 19:30:38 +00:00
Charlie Marsh
8d9b4a5e1c
Sort indexes during graph edge removal (#4649)
## Summary

`remove_edge` will invalidate the last index in the graph, so we need to
ensure that each index we look at is "earlier" than the last.

Co-authored-by: bluss <bluss@users.noreply.github.com>
2024-06-29 13:31:54 -04:00
Charlie Marsh
ea6185e082
Merge markers when applying constraints (#4648)
## Summary

When a constraint is applied to a requirement with a marker, the marker
needs to be propagated to the constraint.

If both the constraint and the requirement have a marker, they need to
be merged together (via `and`).

Closes https://github.com/astral-sh/uv/issues/4575.
2024-06-29 16:51:04 +00:00