A user reported a homebrew Python that would raise an exception in the
interpreter probing script because `platform.mac_ver()` returned `('',
('', '', ''), '')` on his installation due to
https://github.com/Homebrew/homebrew-core/issues/206778
This is easy enough to catch and show a proper error message instead of
the Python backtrace.
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:
- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->
## Summary
This adds `NO_BINARY` and `NO_BINARY_PACKAGE` environment variables to
the uv CLI, allowing the user to specify packages to build from source
using environment variables. Its not a complete fix for #4291 as it does
not handle the `pip` subcommand.
## Test Plan
This was tested by running `uv sync` with various `UV_NO_BINARY` and
`UV_NO_BINARY_PACKAGE` environment variables set and checking that the
correct set of packages were compiled rather than taken from pre-built
wheels.
---------
Co-authored-by: Zanie Blue <contact@zanie.dev>
## Summary
Now that `version` is an optional field, we shouldn't error if an
unambiguous package is lacking a version. We can still enforce the same
guarantees via `source`, since we always set version and source
together, if the package is unambiguous. I also retained the same error
for non-local packages that lack a version like this.
Closes https://github.com/astral-sh/uv/issues/11384.
The underlying cause here, I believe, was that we weren't accounting
for the case where an edge could be visited *without* any extras
enabled. Because of that, we got into situations where we thought
there was only one path to an edge when there were actually more
paths. This in turn lead to us erroneously doing simplification where
it actually isn't justified. And in turn lead to duplicate versions
of the same package being installed in the same environment.
The fix for this ends up being really simple: in the case where we
don't add any conflict items for a package during graph traversal,
we materialize an empty set of conflicts to mark the case of no
extras being enabled when visiting the child edges. This is enough
to propagate the knowledge of multiple paths to the same edge and
causes us to avoid doing improper simplifications.
This does fix the problem in the snapshot, but it does also I think
lead to other cases where simplifications are no longer possible
(hence the changes to the airflow snapshot). But this seems
expected, since we are doing strictly less simplification than we
were before. It's unclear if all of those cases were actual bugs
or not though.
The snapshot is too big to meaningfully read, but the problem is
in the dependencies of `torchmetrics`:
[[package]]
name = "torchmetrics"
version = "1.6.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "lightning-utilities" },
{ name = "numpy" },
{ name = "packaging" },
{ name = "torch", version = "2.2.1", source = { registry = "https://pypi.org/simple" } },
{ name = "torch", version = "2.5.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-chgnet' or extra != 'extra-4-test-m3gnet'" },
]
The conflict markers here are overlapping, which means
both can be included in the same environment.
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:
- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->
## Summary
I've just fixed some broken anchors after browing ux doc site.
## Test Plan
- `index.md`: based on `mkdocs serve` log
- `readme.md`: manual check
## Aside
Do you manually keep `readme.md` and `index.md` partially sync? I've
tried
checking pre-commit and other scripts but found no way to port my edits
from one
to the other.
<!-- How was it tested? -->
---------
Co-authored-by: Zanie Blue <contact@zanie.dev>
Previously, we patched pkg-config .pc files to have the absolute path to
the directory where we unpack a python-build-standalone release. As
discussed in #11028, we can use ${pcfiledir} in a .pc file to indicate
paths relative to the location of the file itself.
This change was implemented in astral-sh/python-build-standalone#507, so
for newer python-build-standalone releases, we don't need to do any
patching. Optimize this case by only modifying the .pc file if an actual
change is needed (which might be helpful down the line with hard links
or something). For older releases, change uv's patch to match what
python-build-standalone now does.
## Motivation
No-op `uv lock` in apache airflow
(891c67f210ab7c877d1f00ea6ea3d3cdbb0e96ef) is slow, which makes `uv run`
slow, too.
Reference project:
```
$ hyperfine "uv run python -c \"print('hi')\""
Benchmark 1: uv run python -c "print('hi')"
Time (mean ± σ): 16.3 ms ± 1.5 ms [User: 9.8 ms, System: 6.4 ms]
Range (min … max): 13.0 ms … 20.0 ms 186 runs
```
Apache airflow before:
```
$ hyperfine "uv run python -c \"print('hi')\""
Benchmark 1: uv run python -c "print('hi')"
Time (mean ± σ): 161.0 ms ± 5.2 ms [User: 135.3 ms, System: 24.1 ms]
Range (min … max): 155.0 ms … 176.3 ms 18 runs
```
## Optimization
`FlatRequiresDist::from_requirements` is taking 50% of main thread
runtime.
Before:

After both commits:

Apache airflow after the first commit:
```
$ hyperfine "uv-profiling run python -c \"print('hi')\""
Benchmark 1: uv-profiling run python -c "print('hi')"
Time (mean ± σ): 122.3 ms ± 5.4 ms [User: 96.1 ms, System: 24.7 ms]
Range (min … max): 114.0 ms … 133.2 ms 23 runs
```
Apache airflow after the second commit:
```
$ hyperfine "uv-profiling run python -c \"print('hi')\""
Benchmark 1: uv-profiling run python -c "print('hi')"
Time (mean ± σ): 108.5 ms ± 3.4 ms [User: 83.2 ms, System: 24.2 ms]
Range (min … max): 103.6 ms … 119.9 ms 28 runs
```
## Summary
These are used for coordination across processes. If you run uv under,
e.g., the root user, then under a different user, I don't think we
should prevent you from acquiring the lock.
Closes https://github.com/astral-sh/uv/issues/11324.
Includes https://pypy.org/posts/2025/02/pypy-v7318-release.html
These are labeled as betas in the post but not anywhere obvious to me?
I'm not sure we need to portray this to users.
Co-authored-by: zanieb <2586601+zanieb@users.noreply.github.com>
## Summary
No behavior changes... This just separates the formatting from the
collection of the results, and also fixes a bug whereby we didn't say
"No changes detected" in some cases.
Given an input in the shape:
```
foo[bar]==1.0.0; sys_platform == 'linux'
foo==1.0.0; sys_platform != 'linux'
```
We would write either
```
foo==1.0.0; sys_platform == 'linux'
```
or
```
foo==1.0.0
```
depending on the iteration order, as the first one is from the marker
proxy package and the second one from the package without marker.
The fix correctly merges graph entries when there are two nodes with
different extras and different markers.
I tried to write a packse test but it failed due to a different
iteration order showing the correct case directly instead of the failing
one we'd need.
Only `strip_extras` is affected, since `combine_extras` uses
`version_marker`.
## Summary
I followed the docs to install flash-attn with uv and got the following
issue
```uv sync
Resolved 27 packages in 12ms
× Failed to build `flash-attn==2.7.4.post1`
├─▶ The build backend returned an error
╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1)
[stderr]
Traceback (most recent call last):
File "<string>", line 8, in <module>
ModuleNotFoundError: No module named 'setuptools'
hint: This usually indicates a problem with the package or the build environment.
```
installing setuptools before running uv sync as done with torch helps
fix it.
## Test Plan
I tested locally before it failed to install, after it worked