Commit Graph

747 Commits

Author SHA1 Message Date
konsti 431ddc1d74
Change backtracking when packages conflict too much (#9843)
Background reading: https://github.com/astral-sh/uv/issues/8157
Companion PR: https://github.com/astral-sh/pubgrub/pull/36
Requires for test coverage: https://github.com/astral-sh/packse/pull/230

When two packages A and B conflict, we have the option to choose a lower
version of A, or a lower version of B. Currently, we determine this by
the order we saw a package (assuming equal specificity of the
requirement): If we saw A before B, we pin A until all versions of B are
exhausted. This can lead to undesirable outcomes, from cases where it's
just slow (sentry) to others cases without lower bounds where be
backtrack to a very old version of B. This old version may fail to build
(terminating the resolution), or it's a version so old that it doesn't
depend on A (or the shared conflicting package) anymore - but also is
too old for the user's application (fastapi). #8157 collects such cases,
and the `wrong-backtracking` packse scenario contains a minimized
example.

We try to solve this by tracking which packages are "A"s, culprits, and
"B"s, affected, and manually interfering with project selection and
backtracking. Whenever a version we just chose is rejected, we give the
current package a counter for being affected, and the package it
conflicted with a counter for being a culprit. If a package accumulates
more counts than a threshold, we reprioritize: Undecided after the
culprits, after the affected, after packages that only have a single
version (URLs, `==<version>`). We then ask pubgrub to backtrack just
before the culprit. Due to the changed priorities, we now select package
B, the affected, instead of package A, the culprit.

To do this efficiently, we ask pubgrub for the incompatibility that
caused backtracking, or just the last version to be discarded (due to
its dependencies). For backtracking, we use the last incompatibility
from unit propagation as a heuristic. When a version is discarded
because one of its dependencies conflicts with the partial solution, the
incompatibility tells us the package in the partial solution that
conflicted.

We only backtrack once per package, on the first time it passes the
threshold. This prevents backtracking loops in which we make the same
decisions over and over again. But we also changed the priority, so that
we shouldn't take the same path even after the one time we backtrack (it
would defeat the purpose of this change).

There are some parameters that can be tweaked: Currently, the threshold
is set to 5, which feels not too eager with so me of the conflicts that
we want to tolerate but also changes strategies quickly. The relative
order of the new priorities can also be changed, as for each (A, B) pair
the priority of B is afterwards lower than that for A. Currently,
culprits capture conflict for the whole package, but we could limit that
to a specific version. We could discard conflict counters after
backtracking instead of keeping them eternally as we do now. Note that
we're always taking about pairs (A, B), but in practice we track
individual packages, not pairs.

A case that we wouldn't capture is when B is only introduced to the
dependency graph after A, but I think that would require cyclical
dependency for A and B to conflict? There may also be cases where
looking at the last incompatibility is insufficient.

Another example that we can't repair with prioritization is
urllib3/boto3/botocore: We actually have to check all the newer versions
of boto3 and botocore to identify the version that allows with the older
urllib3, no shortcuts allowed.

```
urllib3<1.25.4
boto3
```

All examples I tested were cases with two packages where we only had to
switch the order, so I've abstracted them into a single packse case.

This PR changes the resolution for certain paths, and there is the risk
for regressions.

Fixes #8157

---

All tested examples improved.

Input fastapi:
```text
starlette<=0.36.0
fastapi<=0.115.2
```

```
# BEFORE
$ uv pip --no-progress compile -p 3.11 --exclude-newer 2024-10-01 --no-annotate debug/fastapi.txt
annotated-types==0.7.0
anyio==4.6.0
fastapi==0.1.17
idna==3.10
pydantic==2.9.2
pydantic-core==2.23.4
sniffio==1.3.1
starlette==0.36.0
typing-extensions==4.12.2

# AFTER
$ cargo run --profile fast-build --no-default-features pip compile -p 3.11 --no-progress --exclude-newer 2024-10-01 --no-annotate debug/fastapi.txt 
annotated-types==0.7.0
anyio==4.6.0
fastapi==0.109.1
idna==3.10
pydantic==2.9.2
pydantic-core==2.23.4
sniffio==1.3.1
starlette==0.35.1
typing-extensions==4.12.2
```


Input xarray:
```text
xarray[accel]
```

```
# BEFORE
$ uv pip --no-progress compile -p 3.11 --exclude-newer 2024-10-01 --no-annotate debug/xarray-accel.txt
bottleneck==1.4.0
flox==0.9.13
llvmlite==0.36.0
numba==0.53.1
numbagg==0.8.2
numpy==2.1.1
numpy-groupies==0.11.2
opt-einsum==3.4.0
packaging==24.1
pandas==2.2.3
python-dateutil==2.9.0.post0
pytz==2024.2
scipy==1.14.1
setuptools==75.1.0
six==1.16.0
toolz==0.12.1
tzdata==2024.2
xarray==2024.9.0

# AFTER
$ cargo run --profile fast-build --no-default-features pip compile -p 3.11 --no-progress --exclude-newer 2024-10-01 --no-annotate debug/xarray-accel.txt
bottleneck==1.4.0
flox==0.9.13
llvmlite==0.43.0
numba==0.60.0
numbagg==0.8.2
numpy==2.0.2
numpy-groupies==0.11.2
opt-einsum==3.4.0
packaging==24.1
pandas==2.2.3
python-dateutil==2.9.0.post0
pytz==2024.2
scipy==1.14.1
six==1.16.0
toolz==0.12.1
tzdata==2024.2
xarray==2024.9.0
```


Input sentry: The resolution is identical, but arrived at much faster:
main tries 69 versions (sentry-kafka-schemas: 63), PR tries 12 versions
(sentry-kafka-schemas: 6; 5 times conflicting, then once the right
version).

```text
python-rapidjson<=1.20,>=1.4
sentry-kafka-schemas<=0.1.113,>=0.1.50
```

```
# BEFORE
$ uv pip --no-progress compile -p 3.11 --exclude-newer 2024-10-01 --no-annotate debug/sentry.txt
fastjsonschema==2.20.0
msgpack==1.1.0
python-rapidjson==1.8
pyyaml==6.0.2
sentry-kafka-schemas==0.1.111
typing-extensions==4.12.2

# AFTER
$ cargo run --profile fast-build --no-default-features pip compile -p 3.11 --no-progress --exclude-newer 2024-10-01 --no-annotate debug/sentry.txt
fastjsonschema==2.20.0
msgpack==1.1.0
python-rapidjson==1.8
pyyaml==6.0.2
sentry-kafka-schemas==0.1.111
typing-extensions==4.12.2
```


Input apache-beam
```text
# Run on Python 3.10
dill<0.3.9,>=0.2.2
apache-beam<=2.49.0
```

```
# BEFORE
$ uv pip --no-progress compile -p 3.10 --exclude-newer 2024-10-01 --no-annotate debug/apache-beam.txt
  × Failed to download and build `apache-beam==2.0.0`
  ╰─▶ Build backend failed to determine requirements with `build_wheel()` (exit status: 1)

# AFTER
$ cargo run --profile fast-build --no-default-features pip compile -p 3.10 --no-progress --exclude-newer 2024-10-01 --no-annotate debug/apache-beam.txt
apache-beam==2.49.0
certifi==2024.8.30
charset-normalizer==3.3.2
cloudpickle==2.2.1
crcmod==1.7
dill==0.3.1.1
dnspython==2.6.1
docopt==0.6.2
fastavro==1.9.7
fasteners==0.19
grpcio==1.66.2
hdfs==2.7.3
httplib2==0.22.0
idna==3.10
numpy==1.24.4
objsize==0.6.1
orjson==3.10.7
proto-plus==1.24.0
protobuf==4.23.4
pyarrow==11.0.0
pydot==1.4.2
pymongo==4.10.0
pyparsing==3.1.4
python-dateutil==2.9.0.post0
pytz==2024.2
regex==2024.9.11
requests==2.32.3
six==1.16.0
typing-extensions==4.12.2
urllib3==2.2.3
zstandard==0.23.0
```
2024-12-16 11:39:50 +01:00
Zanie Blue c2e2c39449
Show terms in derivation tree debug output (#9862) 2024-12-13 22:53:33 -06:00
Charlie Marsh f0a2d6f076
Allow multiple disjoint URLs in overrides (#9893)
## Summary

Closes https://github.com/astral-sh/uv/issues/9803.
2024-12-14 02:12:44 +00:00
Zanie Blue 4bce1a32ec
Fix bug in terms when collapsing unavailable versions in resolver errors (#9877)
Closes https://github.com/astral-sh/uv/issues/9861
Closes https://github.com/pubgrub-rs/pubgrub/issues/297
2024-12-13 15:06:39 -06:00
Charlie Marsh b2459e6326
Introduce a `--fork-strategy` preference mode (#9868)
## Summary

This PR makes the behavior in https://github.com/astral-sh/uv/pull/9827
the default: we try to select the latest supported package version for
each supported Python version, but we still optimize for choosing fewer
versions when stratifying by platform.

However, you can opt out with `--fork-strategy fewest`.

Closes https://github.com/astral-sh/uv/issues/7190.
2024-12-13 16:05:07 -05:00
Charlie Marsh 0ee21146f4
Fork version selection based on `requires-python` requirements (#9827)
## Summary

This PR addresses a significant limitation in the resolver whereby we
avoid choosing the latest versions of packages when the user supports a
wider range.

For example, with NumPy, the latest versions only support Python 3.10
and later. If you lock a project with `requires-python = ">=3.8"`, we
pick the last NumPy version that supported Python 3.8, and use that for
_all_ Python versions. So you get `1.24.4` for all versions, rather than
`2.2.0`. And we'll never upgrade you unless you bump your
`requires-python`. (Even worse, those versions don't have wheels for
Python 3.12, etc., so you end up building from source.)

(As-is, this is intentional. We optimize for minimizing the number of
selected versions, and the current logic does that well!)

Instead, we know recognize when a version has an elevated
`requires-python` specifier and fork. This is a new fork point, since we
need to fork once we have the package metadata, as opposed to when we
see the dependencies.

In this iteration, I've made this behavior the default. I'm sort of
undecided on whether I want to push on that... Previously, I'd suggested
making it opt-in via a setting
(https://github.com/astral-sh/uv/pull/8686).

Closes https://github.com/astral-sh/uv/issues/8492.
2024-12-13 15:33:46 -05:00
Charlie Marsh f80ddf10b6
Avoid trailing slash when deserializing from lockfile (#9848)
## Summary

Very tricky problem whereby `workspace_root.join(path)` returns the
workspace root with a trailing slash if `path` is empty... This caused
us to accidentally _include_ excluded members during workspace
discovery, since (e.g.) `packages/seeds` doesn't match
`packages/seeds/`.

Closes
https://github.com/astral-sh/uv/issues/9832#issuecomment-2539121761.
2024-12-12 18:49:05 +00:00
Charlie Marsh 8110dedde7
Simplify requires-python check in resolver (#9824)
## Summary

I believe this is identical.
2024-12-11 15:38:25 -05:00
Zanie Blue ae25c2f4db
Upgrade minimum Rust version to 1.83 (#9815)
This reverts commit 6cc7a560f7 to reapply
#9511 since we've disabled ppc64le-musl per #9793
2024-12-11 10:06:19 -06:00
konsti 509dc83fd3
Resolver module improvements (#9773)
Further small refactorings for the resolver.
2024-12-11 14:46:36 +00:00
Andrew Gallant c809462e4b
uv-resolver: deduplicate resolution markers (#9780)
Since we don't (currently) include conflict markers with our
`resolution-markers` in the lock file, it's possible that we end up
with duplicate markers. This happens when the resolver creates more
than one fork with the same PEP 508 markers but different conflict
markers, _and_ where those PEP 508 markers don't simplify to "always
true" after accounting for `requires-python`.

This change should be a strict improvement on the status quo. We aren't
removing any information. It is possible that we should be writing
conflict markers here (like we do for dependency edges), but I haven't
been able to come up with a case or think through a scenario where they
are necessary.

Fixes #9296
2024-12-10 14:58:39 -05:00
konsti 389a26ef9e
Omit empty resolution markers in lockfile (#9738) 2024-12-10 17:18:10 +00:00
konsti b751648bfe
Refactor unavailable metadata to shrink the resolver (#9769)
The resolver methods are already too large and complex, especially
`choose_version*`, so i wanted to shrink and simplify them a bit before
adding new methods to them.

I've split `MetadataResponse` into three variants: success, non-fatal
error (reported through pubgrub), fatal error (reported as error trace).
The resulting non-fatal `MetadataUnavailable` type is equivalent to the
`IncompletePackage` type, so they are now merged. (`UnavailableVersion`
is a bit different since, besides the extra `IncompatibleDist` variant,
it have no error source attached). This shows that the missing metadata
variant was unused, which I removed.

Tagging as error messages for the logging format changes.
2024-12-10 16:46:53 +00:00
Andrew Gallant edf875e306
add conflict markers to the lock file (#9370)
This PR adds a notion of "conflict markers" to the lock file as an
attempt to address #9289. The idea is to encode a new kind of boolean
expression indicating how to choose dependencies based on which extras
are activated.

As an example of what conflict markers look like, consider one of the
cases
brought up in #9289, where `anyio` had unconditional dependencies on
two different versions of `idna`. Now, those are gated by markers, like
this:

```toml
        [[package]]
        name = "anyio"
        version = "4.3.0"
        source = { registry = "https://pypi.org/simple" }
        dependencies = [
            { name = "idna", version = "3.5", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-7-project-foo'" },
            { name = "idna", version = "3.6", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-7-project-bar' or extra != 'extra-7-project-foo'" },
            { name = "sniffio" },
        ]
```

The odd extra values like `extra-7-project-foo` are an encoding of not
just the conflicting extra (`foo`) but also the package it's declared
for (`project`). We need both bits of information because different
packages may have the same extra name, even if they are completely
unrelated. The `extra-` part is a prefix to distinguish it from groups
(which, in this case, would be encoded as `group-7-project-foo` if `foo`
were a dependency group). And the `7` part indicates the length of the
package name which makes it possible to parse out the package and extra
name from this encoding. (We don't actually utilize that property, but
it seems like good sense to do it in case we do need to extra
information from these markers.)

While this preserves PEP 508 compatibility at a surface level, it does
require utilizing this encoding scheme in order
to evaluate them when they're present (which only occurs when
conflicting extras/groups are declared).

My sense is that the most complex part of this change is not just adding
conflict markers, but their simplification. I tried to address this in
the code comments and commit messages.

Reviewers should look at this commit-by-commit.

Fixes #9289, Fixes #9546, Fixes #9640, Fixes #9622, Fixes #9498, Fixes
#9701, Fixes #9734
2024-12-10 10:57:22 -05:00
Charlie Marsh 6fb0d797ed
Improve self-dependency hint to make shadowing clear (#9716) 2024-12-10 08:50:14 -06:00
Charlie Marsh 4c334e67a3
Show 'depends on itself' for proxy packages (#9717) 2024-12-10 08:48:26 -06:00
Charlie Marsh 25045cb3e8
Avoid 403 error hint for PyTorch URLs (#9750)
## Summary

Closes https://github.com/astral-sh/uv/issues/9746.
2024-12-09 22:30:24 +00:00
Charlie Marsh 3992295e9a
Avoid enforcing non-conflicts in `uv export` (#9751)
## Summary

These are already enforced a level above.
2024-12-09 16:56:16 -05:00
Charlie Marsh 00a4adfc46
Respect self-constraints on recursive extras (#9714)
## Summary

Sort of ridiculous, but today this passes, when it should fail:

```toml
[project]
name = "foo"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13.0"
dependencies = []

[project.optional-dependencies]
async = [
    "foo[async]==0.2.0",
]
```
2024-12-08 04:53:42 +00:00
Charlie Marsh 1b4bd8d3b7
Enforce correctness of self-dependencies (#9705)
## Summary

As far as I can tell, this was added in
https://github.com/astral-sh/uv/pull/319, but it seems _incorrect_ to
ignore these.

Closes https://github.com/astral-sh/uv/issues/9693.
2024-12-08 04:17:23 +00:00
Charlie Marsh 7df16af764
Use copy-on-write when normalizing paths (#9710) 2024-12-07 15:52:41 -05:00
Charlie Marsh 696b64f168
Fix projects's typo in resolver error messages (#9708) 2024-12-07 19:03:16 +00:00
Charlie Marsh 3aaa9594be
Add test coverage for build tag prioritization (#9680)
## Summary

See: https://github.com/astral-sh/uv/pull/3781 and
https://github.com/astral-sh/uv/pull/9677.
2024-12-06 09:32:19 -05:00
konsti 400839c527
Remove derivation chain special casing (#9678)
Instead of modifying the error to replace a dummy derivation chain from
construction with the real one, build the error with the real derivation
chain directly.
2024-12-06 13:05:03 +00:00
konsti a286e95f44
Use `thiserror` in `InstalledDist` (#9676)
Wanted to try something that didn't work, ended up removing that todo.
2024-12-06 13:43:14 +01:00
Charlie Marsh 9c8a741efe
Respect build tag priority in `uv.lock` (#9677)
## Summary

Akin to https://github.com/astral-sh/uv/pull/3781.

Closes https://github.com/astral-sh/uv/issues/9673.
2024-12-06 07:40:49 -05:00
konsti 890fb10fa1
Unify dist error handling (#9659)
This came up when trying to improve the build error reporting.
Introduces `DistErrorKind` to avoid error variants for each case that
are only different in one line of the message.
2024-12-05 20:54:14 -05:00
konsti 77df01f4bf
Include more sources to avoid lowest bound warning (#9644)
In https://github.com/astral-sh/uv/issues/8155#issuecomment-2508969900,
resolution lowest was complaining about missing lower bounds for a
pacakge, even though the package had a URL, too:

```
uv pip install dist/pymatgen-2024.10.3.tar.gz pymatgen[ci,optional] --resolution=lowest
```

The error was raised from `pymatgen[ci,optional]`, because we were
looking at it before looking at the "URL"
`dist/pymatgen-2024.10.3.tar.gz`.

I've also added constraints and overrides to the bounds lookup, since
they are missing from the dependency graph.

Fixes #8155 (again)
2024-12-05 09:09:38 +00:00
konsti c314c68bff
Ignore dynamic version in source dist (#9549)
When encountering `dynamic = ["version"]` in the pyproject.toml of a
source dist, we can ignore that and treat it as a statically known
metadata distribution, since the filename tells us the version and that
version must not change on build.

This fixed locking PyGObject 3.50.0 from `pygobject-3.50.0.tar.gz`
(minimized):

```toml
[project]
name = "PyGObject"
description = "Python bindings for GObject Introspection"
requires-python = ">=3.9, <4.0"
dependencies = [
    "pycairo>=1.16"
]
dynamic = ["version"]
```

Afterwards, `uv add --no-sync toga` passes on Ubuntu 24.04 without the
pygobject build deps, when previously it needed `{ name = "pygobject",
version = "3.50.0", requires-dist = [], requires-python = ">=3.9" }`.

I've added a check that source distribution versions are respected after
build.

Fixes #9548
2024-12-04 11:40:31 +00:00
Charlie Marsh 1ecdc1a31e
Model groups as a property of requirements (#9545)
## Summary

Today, our dependency group implementation is a little awkward... For
each package `P`, we check if `P` contains dependencies for each enabled
group, then add a dependency on `P` with the group enabled. There are a
few issues here:

1. It's sort of backwards... We add a dependency from the base package
`P` to `P` with the group enabled. Then `P` with the group enabled adds
a dependency on the base package.
2. We can't, e.g., enable different groups for different packages. (We
don't have a way for users to specify this on the CLI, but there's no
reason that it should be _impossible_ in the resolver.)
3. It's inconsistent with how extras work, which leads to confusing
differences in the resolver.

Instead, our internal requirement type can now include dependency
groups, which makes dependency groups look much, much more like extras
in the resolver.
2024-12-04 00:55:51 +00:00
Zanie Blue 6cc7a560f7
Revert "Upgrade to Rust 1.83 (#9511)" (#9617)
This reverts commit cf20673197 (#9511) due
to failure on powerpc64le in https://github.com/astral-sh/uv/pull/9612
2024-12-03 19:21:05 +00:00
Charlie Marsh ae6f66effc
Normalize paths when lowering Git dependencies (#9595)
## Summary

Discovered while working on https://github.com/astral-sh/uv/issues/9516.
In the linked repo, the root uses a `../dependency` path for the
workspace member, which we weren't normalizing.
2024-12-03 05:41:26 +00:00
Andrew Gallant 81569c47bf uv-resolver: conditionally include the base package dependency
This _partially_ unwinds the optimization in #9540 by adding back the
base package dependency as a sibling to the extra package dependency
in some cases. Specifically, this occurs when _any_ of the extras are
declared as conflicting.

This is believed to be necessary (until another method is found) to
handle the forking logic based on conflicts. Namely, the forking logic
depends on the base and extra packages being sibling dependencies. If
only the extra is present, then it won't be included in the fork that
excludes all conflicting extras. And that means the base package won't
either, even though it should be included in that fork in some cases. If
the base package dependency is deferred, then it will never be reached.

This also adds another test and updates the snapshots that would have
caught the regression in #9540 if the conflict tests had been enabled.
2024-12-02 15:39:39 -05:00
Charlie Marsh 71df509d09
Avoid adding non-extra package with extra dependencies (#9540)
## Summary

Previously, when we encountered `foo[bar]`, we'd add a dependency on
`PubGrubPackage::Package` for `foo`, and then `PubGrubPackage::Extra`
for `foo[bar]`.

Later, when we ask for the dependencies of the `PubGrubPackage::Extra`,
we add `PubGrubPackage::Package` for `foo`, and
`PubGrubPackage::Package` for `foo[bar]`. This is an intentional
strategy because it ensures that PubGrub "knows" that these have to be
solved to the same version as early as possible.

It turns out that the first part here ("add a dependency on
`PubGrubPackage::Package` for `foo`") is suboptimal, because it means
PubGrub might try to solve _just_ `foo` without realizing that it also
has to accommodate all the constraints from the extra.

Instead, we now add _just_ `PubGrubPackage::Extra` for `foo[bar]`, and
defer adding the base package. It looks like this leads to a far more
efficient solve for Airflow.
2024-12-01 08:42:27 -05:00
Charlie Marsh 8126a5ed32
Make `MarkerTree` `Copy` (#9542)
## Summary

It's just a `usize`. It seems simpler and perhaps even more performant
(?) to make it `Copy`.
2024-11-30 14:07:07 -05:00
Charlie Marsh 6bebf79ac3
Remove uses of `Option<MarkerTreeContents>` in `PubGrubPackage` (#9541)
## Summary

Just use `MarkerTree::TRUE` instead of `None`.
2024-11-30 10:36:18 -05:00
Charlie Marsh 22fd9f7ff1
Pass extra when evaluating lockfile markers (#9539)
## Summary

When we serialize and deserialize the lockfile, we remove the conflict
markers. So in the linked case, the edges for the `tqdm` entries are
like:

```
complexified_marker: UniversalMarker {
    pep508_marker: python_full_version >= '3.9.0',
    conflict_marker: true,
},
```

However... when we evaluate in-memory, the conflict markers are still
there...

```
complexified_marker: UniversalMarker {
    pep508_marker: true,
    conflict_marker: extra == 't1' and extra != 't2',
},
```

So if `uv run` creates the lockfile, we evaluate this as `false`.

We should make this consistent, and I expect @BurntSushi is aware. But
for now, it's reasonable / correct to pass the extra when evaluating at
this specific point, since we know the dependency was enabled by the
marker.

Closes
https://github.com/astral-sh/uv/issues/9533#issuecomment-2508908591.
2024-11-30 14:22:18 +00:00
Charlie Marsh 53fe301b1d
Avoid using IDs across PubGrub states (#9538)
## Summary

This isn't safe, because the prefetcher is global but the IDs could come
from different PubGrub states (i.e., different forks).
2024-11-30 13:59:21 +00:00
Charlie Marsh 2aca623691
Remove unused specifier field from `PubGrub` structs (#9536) 2024-11-30 03:59:34 +00:00
Charlie Marsh 69811837e5
Support recursive extras with marker in `pip compile -r pyproject.toml` (#9535)
## Summary

Closes https://github.com/astral-sh/uv/issues/9530.
2024-11-30 03:40:22 +00:00
Charlie Marsh 950855877a
Use constraints in trace rather than irrelevant requires-python (#9529) 2024-11-29 19:25:43 +00:00
Charlie Marsh cf20673197
Upgrade to Rust 1.83 (#9511)
## Summary

A lot of good new lints, and most importantly, error stabilizations. I
tried to find a few usages of the new stabilizations, but I'm sure there
are more.

IIUC, this _does_ require bumping our MSRV.
2024-11-29 12:04:22 -05:00
Charlie Marsh 590294a0ac
Propagate markers for recursive extras in resolver (#9509)
## Summary

Closes
https://github.com/astral-sh/uv/issues/9499#issuecomment-2506491209.
2024-11-28 12:40:00 -05:00
konsti b80bd87b99
Don't emit unpinned warning for proxy packages (#9497)
Whenever we see an unpinned proxy package, we know that its base package
is also unpinned and emitted a warning.

Part 1 of 2 for #8155
2024-11-28 12:39:38 +00:00
Charlie Marsh 8a27d4d340
Allow file: URLs to include package names (#9493)
## Summary

Closes https://github.com/astral-sh/uv/issues/9489.
2024-11-27 22:27:07 -05:00
Charlie Marsh f1ccbcb065
Consistently enforce requested-vs.-built metadata when retrieving wheels (#9484)
## Summary

We were missing a bunch of edge cases, e.g., the wheel exists in the
cache already.

Closes https://github.com/astral-sh/uv/issues/9480.
2024-11-27 16:51:01 -05:00
Charlie Marsh ee84620e90
Use consistent formatting for build system errors (#9340)
## Summary

These look pretty different from the help / hint messages we show on
resolver failure. I've added color, backticks, and a "hint:" prefix.

Before:

![Screenshot 2024-11-21 at 5 45
40 PM](https://github.com/user-attachments/assets/71ee2551-8fc6-4715-a9d7-68055cd34547)

After:

![Screenshot 2024-11-21 at 6 05
31 PM](https://github.com/user-attachments/assets/24e7fb46-49aa-4b6f-a442-115a71a3414b)
2024-11-27 14:22:53 +00:00
Charlie Marsh 916d5d7778
Migrate to PubGrub's arena for package names (#9448)
## Summary

There's more we can do here, i.e., to leverage the IDs more widely, but
this is a start.
2024-11-26 15:05:39 -05:00
Charlie Marsh 8aeaf98f59
Rename from `Lowered` to `Canonical` (#9447)
By request:
https://github.com/astral-sh/uv/pull/9341#pullrequestreview-2460979421.
2024-11-26 13:34:43 -05:00
Charlie Marsh d18753527f
Remove `python_version` from lowered marker representation (#9343)
## Summary

We never construct these -- they should be impossible, since we always
translate to `python_full_version`. This PR encodes that impossibility
in the types.
2024-11-26 14:39:36 +00:00