## Summary
Closes https://github.com/astral-sh/uv/issues/10493.
## Test Plan
Run `cargo test --profile fast-build --no-fail-fast -p uv
username_password_sources` from a terminal.
## Summary
If you have a dependency with a marker, and you add a constraint, it
causes us to _always_ fork, because we represent the constraint as a
second dependency with the marker repeated (and, therefore, we have two
requirements of the same name, both with markers). I don't think we
should fork here -- and in the end it's leading to this undesirable
resolution: #10481.
I tried to change constraints such that we just _reuse_ and augment the
initial requirement, but that has a fairly negative effect on error
messages: #10489. So this fix seems a bit better to me.
Closes https://github.com/astral-sh/uv/issues/10481.
## Summary
Fixes a bug when there are only comments in the dependencies section.
Basically, after one removes all dependencies, if there are remaining
comments then the value unwrapped here
c198e2233e/crates/uv-workspace/src/pyproject_mut.rs (L1309)
is never properly initialized.
It's initialized to `None`, here
c198e2233e/crates/uv-workspace/src/pyproject_mut.rs (L1256),
but doesn't get set to `Some(...)` until the first dependency here
c198e2233e/crates/uv-workspace/src/pyproject_mut.rs (L1276)
and since we remove them all... there are none.
## Test Plan
Manually induced bug with
```
[project]
name = "t1"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"duct>=0.6.4",
"minilog>=2.3.1",
# comment
]
```
Then running
```
$ RUST_LOG=trace RUST_BACKTRACE=full uv remove duct minilog
DEBUG uv 0.5.8
DEBUG Found project root: `/home/bnorick/dev/workspace/t1`
DEBUG No workspace root found, using project root
thread 'main' panicked at crates/uv-workspace/src/pyproject_mut.rs:1294:73:
called `Option::unwrap()` on a `None` value
stack backtrace:
0: 0x5638d7bed6ba - <unknown>
1: 0x5638d783760b - <unknown>
2: 0x5638d7bae232 - <unknown>
3: 0x5638d7bf0f07 - <unknown>
4: 0x5638d7bf215c - <unknown>
5: 0x5638d7bf1972 - <unknown>
6: 0x5638d7bf1909 - <unknown>
7: 0x5638d7bf18f4 - <unknown>
8: 0x5638d75087d2 - <unknown>
9: 0x5638d750896b - <unknown>
10: 0x5638d7508d68 - <unknown>
11: 0x5638d8dcf1bb - <unknown>
12: 0x5638d76be271 - <unknown>
13: 0x5638d75ef1f9 - <unknown>
14: 0x5638d75fc3cd - <unknown>
15: 0x5638d772d9de - <unknown>
16: 0x5638d8476812 - <unknown>
17: 0x5638d83e1894 - <unknown>
18: 0x5638d84722d3 - <unknown>
19: 0x5638d83e1372 - <unknown>
20: 0x7f851cfc7d90 - <unknown>
21: 0x7f851cfc7e40 - __libc_start_main
22: 0x5638d758e992 - <unknown>
23: 0x0 - <unknown>
```
N.B. After fixing #10430, `ArcStr` became the fastest implementation
(and the gains were significantly reduced, down to 1-2%). See:
https://github.com/astral-sh/uv/pull/10453#issuecomment-2583344414.
## Summary
I tried out a variety of small string crates, but `Arc<str>`
outperformed them, giving a ~10% speed-up:
```console
❯ hyperfine "../arcstr lock" "../flexstr lock" "uv lock" "../arc lock" "../compact_str lock" --prepare "rm -f uv.lock" --min-runs 50 --warmup 20
Benchmark 1: ../arcstr lock
Time (mean ± σ): 304.6 ms ± 2.3 ms [User: 302.9 ms, System: 117.8 ms]
Range (min … max): 299.0 ms … 311.3 ms 50 runs
Benchmark 2: ../flexstr lock
Time (mean ± σ): 319.2 ms ± 1.7 ms [User: 317.7 ms, System: 118.2 ms]
Range (min … max): 316.8 ms … 323.3 ms 50 runs
Benchmark 3: uv lock
Time (mean ± σ): 330.6 ms ± 1.5 ms [User: 328.1 ms, System: 139.3 ms]
Range (min … max): 326.6 ms … 334.2 ms 50 runs
Benchmark 4: ../arc lock
Time (mean ± σ): 303.0 ms ± 1.2 ms [User: 301.6 ms, System: 118.4 ms]
Range (min … max): 300.3 ms … 305.3 ms 50 runs
Benchmark 5: ../compact_str lock
Time (mean ± σ): 320.4 ms ± 2.0 ms [User: 318.7 ms, System: 120.8 ms]
Range (min … max): 317.3 ms … 326.7 ms 50 runs
Summary
../arc lock ran
1.01 ± 0.01 times faster than ../arcstr lock
1.05 ± 0.01 times faster than ../flexstr lock
1.06 ± 0.01 times faster than ../compact_str lock
1.09 ± 0.01 times faster than uv lock
```
## Summary
We can read from the slice directly. I don't think this will affect
performance today, because `from_str` will then allocate, but it
_should_ be a speedup once #10475 merges, since we can then avoid
allocating a `String` and go straight from `str` to `ArcStr`.
#8061 incorrectly claims to change the delimiter for `UV_FIND_LINKS`
from spaces to commas. In reality, it prevents `UV_FIND_LINKS` from
being split. This commit fixes that.
## Summary
This appears to be a consistent 1% performance improvement and should
also reduce memory quite a bit. We've also decided to use these for
markers, so it's nice to use the same optimization here.
```
❯ hyperfine "./uv pip compile --universal scripts/requirements/airflow.in" "./arcstr pip compile --universal scripts/requirements/airflow.in" --min-runs 50 --warmup 20
Benchmark 1: ./uv pip compile --universal scripts/requirements/airflow.in
Time (mean ± σ): 136.3 ms ± 4.0 ms [User: 139.1 ms, System: 241.9 ms]
Range (min … max): 131.5 ms … 149.5 ms 50 runs
Benchmark 2: ./arcstr pip compile --universal scripts/requirements/airflow.in
Time (mean ± σ): 134.9 ms ± 3.2 ms [User: 137.6 ms, System: 239.0 ms]
Range (min … max): 130.1 ms … 151.8 ms 50 runs
Summary
./arcstr pip compile --universal scripts/requirements/airflow.in ran
1.01 ± 0.04 times faster than ./uv pip compile --universal scripts/requirements/airflow.in
```
It turns out that we use `UniversalMarker::pep508` quite a bit. To the
point that it makes sense to pre-compute it when constructing a
`UniversalMarker`.
This still isn't necessarily the fastest thing we can do, but this
results in a major speed-up and `without_extras` no longer shows up for
me in a profile.
Motivating benchmarks. First, from #10430:
```
$ hyperfine 'rm -f uv.lock && uv lock' 'rm -f uv.lock && uv-ag-optimize-without-extras lock'
Benchmark 1: rm -f uv.lock && uv lock
Time (mean ± σ): 408.3 ms ± 276.6 ms [User: 333.6 ms, System: 111.1 ms]
Range (min … max): 316.9 ms … 1195.3 ms 10 runs
Warning: The first benchmarking run for this command was significantly slower than the rest (1.195 s). This could be caused by (filesystem) caches that were not filled until after the first run. You should consider using the '--warmup' option to fill those caches before the actual benchmark. Alternatively, use the '--prepare' option to clear the caches before each timing run.
Benchmark 2: rm -f uv.lock && uv-ag-optimize-without-extras lock
Time (mean ± σ): 209.4 ms ± 2.2 ms [User: 209.8 ms, System: 103.8 ms]
Range (min … max): 206.1 ms … 213.4 ms 14 runs
Summary
rm -f uv.lock && uv-ag-optimize-without-extras lock ran
1.95 ± 1.32 times faster than rm -f uv.lock && uv lock
```
And now from #10438:
```
$ hyperfine 'uv pip compile requirements.in -c constraints.txt --universal --no-progress --python-version 3.8 --offline > /dev/null' 'uv-ag-optimize-without-extras pip compile requirements.in -c constraints.txt --universal --no-progress --python-version 3.8 --offline > /dev/null'
Benchmark 1: uv pip compile requirements.in -c constraints.txt --universal --no-progress --python-version 3.8 --offline > /dev/null
Time (mean ± σ): 12.718 s ± 0.052 s [User: 12.818 s, System: 0.140 s]
Range (min … max): 12.650 s … 12.815 s 10 runs
Benchmark 2: uv-ag-optimize-without-extras pip compile requirements.in -c constraints.txt --universal --no-progress --python-version 3.8 --offline > /dev/null
Time (mean ± σ): 419.5 ms ± 6.7 ms [User: 434.7 ms, System: 100.6 ms]
Range (min … max): 412.7 ms … 434.3 ms 10 runs
Summary
uv-ag-optimize-without-extras pip compile requirements.in -c constraints.txt --universal --no-progress --python-version 3.8 --offline > /dev/null ran
30.32 ± 0.50 times faster than uv pip compile requirements.in -c constraints.txt --universal --no-progress --python-version 3.8 --offline > /dev/null
```
Fixes#10430, Fixes#10438
## Summary
We shouldn't consider incompatible distributions (e.g., those that don't
match the required Python version) when determining the implied markers.
For some reason this was banned when originally added (I did not see
discussion about it). I think it's fine to allow. With `uv run`, there's
a bit of nuance because we also allow the script to be read from stdin.
## Summary
If a user provides a constraint like `flask==3.0.0`, that gets expanded
to `[3.0.0, 3.0.0+[max])`. So it's not a _singleton_, but it should be
treated as such for the purposes of prioritization, since in practice it
will almost always map to a single version.
This should be essentially the exact same behaviour, but backon is a
total API redesign, so things had to be expressed slightly differently.
Overall I think the code is more readable, which is nice.
Fixes#10001
## Summary
The issue here is that we add `urllib3{python_full_version >= '3.8'}` as
a dependency, then `requests{python_full_version >= '3.8'}`, which adds
`urllib3`, but at that point, we haven't expanded
`urllib3{python_full_version >= '3.8'}`, so we "lose" the singleton
constraint. The solution is to ensure that we visit proxies eagerly, so
that we accumulate constraints as early as possible.
Closes
https://github.com/astral-sh/uv/issues/10425#issuecomment-2580324578.
## Summary
Since there are occasional inquiries about how to configure UV for
build-system specific features, I want to raise awareness that users
should refer to the documentation of the build system they are using for
relevant settings.
## Test Plan
Run docs service in local.
9821d58d35

---------
Signed-off-by: FishAlchemist <48265002+FishAlchemist@users.noreply.github.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
## Summary
You can now run `uv tree --script main.py` to show the dependency tree
for a given script. If a lockfile doesn't exist, it will create one.
Closes https://github.com/astral-sh/uv/issues/7328.
## Summary
`uv add --script main.py anyio` will now update the lockfile, _if_ it
already exists. (If no such lockfile exists, the behavior is unchanged.)
## Summary
This PR adds `ls` alias to `uv {tool, python, pip} list` for
convenience.
Not sure if folks previously discussed this or have any opinion on
having aliases – but I have a muscle memory for `ls` for listing things
in commands I'm using (like `docker images ls`, `zellij ls`, `helm ls`
etc.) and thought having `ls` alias for `list` command would be useful.
## Test Plan
I simply compiled `uv` and manually checked `./target/release/uv {tool,
python, pip} ls`.
The latest release flaked failing to fetch the buildx image, which is
reportedly due to rate limits. Last I checked, DockerHub enforces much
stricter limits on unauthenticated requests. I added a bot account and a
corresponding read-only token.
## Summary
You can now run `uv lock --script main.py` to lock a given script
(though as of this PR, the script itself isn't used anywhere).
Closes https://github.com/astral-sh/uv/issues/6318.