## Summary
<!-- What's the purpose of the change? What does it do, and why? -->
Fixes#18021
Store dependencies excluded by uv tool install in the tool receipt and
provide these same dependencies to the requirements resolver when the
tool is upgraded.
## Test Plan
<!-- How was it tested? -->
Running the repro commands provided in issue #18021, we can see the
excluded dependency does not get reinstalled when the tool is upgraded:
```sh
$ cat /tmp/excludes.txt
markdown-it-py
$ ~/Dev/uv/target/debug/uv install --excludes /tmp/excludes.txt 2048-cli==1.0.2
Resolved 7 packages in 150ms
Installed 7 packages in 56ms
+ 2048-cli==1.0.2
+ click==8.3.1
+ maturin==1.12.0
+ numpy==2.4.2
+ pygments==2.19.2
+ rich==13.9.4
+ rich-menu==0.3.0
Installed 1 executable: 2048-cli
$ cat ~/.local/share/uv/tools/2048-cli/uv-receipt.toml
[tool]
requirements = [{ name = "2048-cli" }]
excludes = ["markdown-it-py"]
entrypoints = [
{ name = "2048-cli", install-path = "/home/brad/.local/bin/2048-cli", from = "2048-cli" },
]
$ ~/Dev/uv/target/debug/uv tool upgrade 2048-cli
Updated 2048-cli v1.0.2 -> v1.0.3
- 2048-cli==1.0.2
+ 2048-cli==1.0.3
Installed 1 executable: 2048-cli
```
---------
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
## Summary
This provides the scaffolding (CLI and initial `uv-audit` crate) for a
`uv audit` subcommand.
Closes#9189.
Tracking:
- [x] Core CLI scaffolding (this PR)
- [x] #18185
- [x] Audit core (probably a new `uv-audit` crate): #18124
- [ ] Bulk dependency audits with OSV
- [ ] Result presentation
- [ ] #18193
Things that also need to be done with the MVP:
- [ ] We should not audit workspace members by default (by definition,
they don't exist on indices and therefore don't have meaningful results
from vulnerability services).
- [ ] I need to ensure groups/etc. are being filtered by correctly,
right now we audit every single package in the lockfile unconditionally.
## Test Plan
Unit and integration tests commensurate with the new functionality.
---------
Signed-off-by: William Woodruff <william@astral.sh>
## Summary
If the user provides credentials for an index URL during tool install,
we strip the credentials. However, we now store the authentication
policy as `always` to ensure that if the user attempts to upgrade, and
we can't query the index, we correctly fail.
This won't cover credentials provided via keyring, but it will cover
embedded credentials and environment variables.
Closes https://github.com/astral-sh/uv/issues/18120.
## Summary
[`pip-compile`] (jazzband) has the following semantics when invoked with
both `--upgrade` and `--upgrade-package={pkg}{constraint}`: upgrade all
packages WHILE abiding by the constraints provided.
Currently, `uv` ignores the additional constraints, merging `--upgrade`
and `--upgrade-package` simply as `--upgrade`, which is obviously a
divergence in behavior. This leads to specific package constraints being
ignored, even when explicitly provided. When I went to look at patching
this, I noticed an open TODO around the same behavior in the
`--no-upgrade` case.
As a solution, separate the `UpgradeStrategy` from the constraints
provided, allowing for a more graceful merge.
[`pip-compile`]: https://github.com/jazzband/pip-tools
I've created an issue to track this here:
https://github.com/astral-sh/uv/issues/18225
## Test Plan
I've added a few integration tests to cover this case (including
updating the negative test that existed), and updated the relevant
snapshots.
---------
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
uv 0.10 can use direct builds for uv_build with `<0.10`, there were no
breaking changes.
This PR also revamps the direct build detection to be more sensitive and
improves the errors messages.
---------
Co-authored-by: Aria Desires <aria.desires@gmail.com>
Avoid churn in this file when IDEs remove the trailing whitespace while
the snapshot contains. This single space looks like a typo in the pyenv
placeholder package.
Alternative to https://github.com/astral-sh/uv/pull/18182.
By default, retry-policies compute the actual retry duration as
`min_retry_interval * (base ** n_past_retries) * rng.uniform(0.0, 1.0)`,
so the first sleep duration would be between 0s and 1s. This change
bumps this to a real 1s minimum.
## Summary
If no revision is specified, we should assume the input used the default
branch (rather than returning early and ignoring the existing SHA).
Closes https://github.com/astral-sh/uv/issues/18224.
Resolves https://github.com/astral-sh/uv/issues/18202
This diff adds a `UV_INIT_BARE` environment variable that makes `--bare`
the default behavior for `uv init`. The command-line flag takes
precedence over the environment variable, following the same pattern
used by `UV_FROZEN`, `UV_LOCKED`, and other boolean environment
variables.
<!--
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
If a package uses meson-python as backend, it's declared as:
```
[build-system]
build-backend = 'mesonpy'
requires = ['meson-python']
```
Currently, if meson-python is missing, one gets the following hint:
```
Traceback (most recent call last):
File "<string>", line 8, in <module>
import mesonpy as backend
ModuleNotFoundError: No module named 'mesonpy'
hint: This error likely indicates that `sagemath` depends on `mesonpy`, but doesn't declare it as a build
dependency. If `sagemath` is a first-party package, consider adding `mesonpy` to its `build-system.requires`.
Otherwise, either add it to your `pyproject.toml` under:
[tool.uv.extra-build-dependencies]
sagemath = ["mesonpy"]
or `uv pip install mesonpy` into the environment and re-run with `--no-build-isolation`.
```
which is not quite correct as the build backend/module is called
"mesonpy" but the python package one has to install is "meson-python".
This hint is improved in this PR.
<!-- What's the purpose of the change? What does it do, and why? -->
## Test Plan
I didn't yet had a chance to setup a local dev env for testing this.
<!-- How was it tested? -->
Resolves#18014 (also related to
https://github.com/astral-sh/uv/issues/18010)
When `--exclude-newer` is active and all versions of a required package
were uploaded after the cutoff, resolution fails with no indication that
the setting is the cause. This diff adds a resolver hint that surfaces
the relationship.
The diff also includes debug-level logging of the exclude-newer
configuration at resolver start (happy to get this in separately, if
needed), and trace-level logging each time an individual file is
excluded by the timestamp cutoff. These help diagnose resolution
behavior without requiring the hint to fire.
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [resvg](https://redirect.github.com/linebender/resvg) | dependencies |
minor | `0.46.0` → `0.47.0` |
---
### Release Notes
<details>
<summary>linebender/resvg (resvg)</summary>
###
[`v0.47.0`](https://redirect.github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0470-2026-02-05)
[Compare
Source](https://redirect.github.com/linebender/resvg/compare/v0.46.0...v0.47.0)
This release has an MSRV of 1.87.0 for `usvg` and `resvg` and the C API.
##### Added
- Focal radius (`fr`) supported for Radial Gradients.
([#​1014](https://redirect.github.com/linebender/resvg/issues/1014)
by [@​wmedrano](https://redirect.github.com/wmedrano))
- Support for variable fonts based on font-variation-settings CSS
property.
([#​997](https://redirect.github.com/linebender/resvg/issues/997)
by [@​oetiker](https://redirect.github.com/oetiker))
##### Changed
- `tiny-skia` has a major version bump from 0.11 to 0.12.
</details>
---
### Configuration
📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM, only on
Monday ( * 0-3 * * 1 ) (UTC), Automerge - At any time (no schedule
defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/astral-sh/uv).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNi41IiwidXBkYXRlZEluVmVyIjoiNDMuMjYuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiYnVpbGQ6c2tpcC1kb2NrZXIiLCJidWlsZDpza2lwLXJlbGVhc2UiLCJpbnRlcm5hbCJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Copy of https://github.com/astral-sh/uv/pull/17753 which GitHub
auto-closed.
This adds test infrastructure for cross-device links and file systems
with reflink support. In short, we create a few extra file systems on
the CI runners then provide their paths to the test suite using
environment variables to ensure we have coverage. If the variables are
not set, the tests are skipped.
---------
Co-authored-by: Claude <noreply@anthropic.com>
This PR contains the following updates:
| Package | Type | Update | Change | Pending |
|---|---|---|---|---|
| [jiff](https://redirect.github.com/BurntSushi/jiff) |
workspace.dependencies | patch | `0.2.19` → `0.2.20` | `0.2.21` |
---
### Release Notes
<details>
<summary>BurntSushi/jiff (jiff)</summary>
###
[`v0.2.20`](https://redirect.github.com/BurntSushi/jiff/blob/HEAD/CHANGELOG.md#0220-2026-02-11)
[Compare
Source](https://redirect.github.com/BurntSushi/jiff/compare/0.2.19...0.2.20)
\===================
This release contains a major internal refactor that moves off of using
ranged
integers internally. There are also some small bug fixes and added
support for
finding the system time zone on emscripten targets.
Enhancements:
- [#​11](https://redirect.github.com/BurntSushi/jiff/issues/11):
Stop using ranged integers internally.
- [#​490](https://redirect.github.com/BurntSushi/jiff/issues/490):
Add support for retrieving the system time zone on emscripten targets.
- [#​500](https://redirect.github.com/BurntSushi/jiff/issues/500):
Update comparison with the `time` crate in the Jiff documentation.
- [#​502](https://redirect.github.com/BurntSushi/jiff/issues/502):
Enable some non-default features for the Rust Playground deployment.
Bug fixes:
- [#​485](https://redirect.github.com/BurntSushi/jiff/issues/485):
Fix bug with padding for negative integers in `strftime`.
- [#​486](https://redirect.github.com/BurntSushi/jiff/issues/486):
Make `%^c` result in uppercase strings where appropriate.
</details>
---
### Configuration
📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM, only on
Monday ( * 0-3 * * 1 ) (UTC), Automerge - At any time (no schedule
defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/astral-sh/uv).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNi41IiwidXBkYXRlZEluVmVyIjoiNDMuMjYuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiYnVpbGQ6c2tpcC1yZWxlYXNlIiwiaW50ZXJuYWwiXX0=-->
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
In https://github.com/astral-sh/uv/issues/18026, we received a report
that resolution took >90m and the root cause appears to be that repeated
conflicts with a single extra causes an exponential explosion.
I used Codex to find an optimization to avoid this.
> When processing N pairwise conflict sets that share a common extra
(e.g., {pinned, a}, {pinned, b}, {pinned, c}, ...), the resolver creates
forks by iterating over each conflict set and splitting every existing
fork into N+1 sub-forks. Without the optimization, this is
multiplicative — each conflict set multiplies the fork count, producing
O(2^N) forks even though most are redundant.
>
> The key observation is: if a prior conflict set already excluded an
extra from a fork, then a later conflict set involving that same extra
is already satisfied in that fork — there's nothing left to separate.
For example, after processing {pinned, a}, one fork has pinned excluded.
When we then process {pinned, b}, that fork already can't have pinned
active, so the constraint "at most one of pinned or b" is trivially
true. We call this fork dominated by the earlier split — no further
forking is needed.
>
> The one subtlety: even if a conflict set is satisfied in a fork, we
might still need to fork if the remaining non-excluded item appears in
another conflict set that's still live (i.e., has two or more
non-excluded items). That's the refined check — we only skip forking
when the item is truly dominated across all conflict sets, not just the
current one.
I then did some rough benchmarking
```
┌────┬────────┬───────┬─────────┐
│ N │ Before │ After │ Speedup │
├────┼────────┼───────┼─────────┤
│ 5 │ 29ms │ 27ms │ ~1× │
├────┼────────┼───────┼─────────┤
│ 8 │ 58ms │ 27ms │ 2× │
├────┼────────┼───────┼─────────┤
│ 10 │ 185ms │ 26ms │ 7× │
├────┼────────┼───────┼─────────┤
│ 15 │ 20.0s │ 46ms │ 435× │
├────┼────────┼───────┼─────────┤
│ 20 │ >60s │ 28ms │ >2,000× │
└────┴────────┴───────┴─────────┘
```
In preparation for #17753 though this technically could affect macOS too
if you have a HFS+ drive which supports hardlinks but not reflinks.
I manually tested this on a Linux with cross-filesystem links and varied
levels of hardlink and reflink support. #17753 will include
infrastructure for testing in CI.
This came out of an experience on whether claude code can find missing
updates in from changes in PRs:
#18096 — Propagate project-level conflicts to package extras (zanieb)
**Stale docstring on `filter_by_group`**: In
`crates/uv-resolver/src/resolver/environment.rs`, the docstring still
says "Include rules have no effect in `included_by_group`". After this
PR, include rules DO affect `included_by_group` when a project-level
exclusion exists for a package — an explicit inclusion for a specific
extra overrides the exclusion.
#18081 — Filter `pylock.toml` wheels by tags and `requires-python`
(konstin)
**Inverted docstring on `is_wheel_unreachable`**: At
`crates/uv-resolver/src/lock/mod.rs:6088`, the docstring says "Returns
`false` if the wheel is definitely unreachable" but the function
actually returns `true` when unreachable. The `true`/`false` are
swapped.
#18075 — make missing files warning debug (dead10ck)
**Analogous `warn!` not changed in flat_index.rs**:
`crates/uv-client/src/flat_index.rs:215` has a similar `warn!("Skipping
file in {}: {err}", &url)` that exhibits the same noisy pattern.
Arguable whether flat indexes warrant the same change since they're
user-configured and less likely to trigger mass warnings.
uv_build is faster and has less network use than uv_build, and it's a
better practice to use it than setuptools, so we should do it in our own
tests.
Migrates only the easy tests, we do test setuptools features and quirks
in some places, those aren't touched. One commit per migrated
integration test file, for easier review.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Closes https://github.com/astral-sh/uv/issues/18070
Fixes an issue where `--no-emit-workspace --all-packages` would
incorrectly emit `-e .` (the workspace root) when the workspace
contained only a single member at the root.
When a workspace contains a single member at the root, that member is
not included in the lockfile's `members` set (it's empty). The
`--all-packages` flag uses `InstallTarget::Workspace`, which returned
`None` for `project_name()`. This meant `include_package()` had no way
to identify the root project as a workspace member — neither the
`project_name` check nor the `members.contains()` check could match it,
so it passed through the `--no-emit-workspace` filter.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Closes#18015
Project-level conflict items (e.g., `{ package = "pkg-a" }`) were not
properly excluding the package's extras and groups from the conflicting
fork. When a project-level conflict excludes a package, all of that
package's extras should also be excluded (since they transitively depend
on the base package). The alternative seems to be that the user needs to
enumerate all of the extra conflicts explicitly in addition to the
package conflict, which seems excessive.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Consolidates our file copying and linking logic in `uv-fs` instead of
having a duplicate implementation in `uv-install-wheel`. This required
introducing some new abstractions in `uv-fs` to support the features
wheel installation needs.
I think this is a blocker to improving our reflink handling in
https://github.com/astral-sh/uv/pull/17753 and also generally desirable
since the copy fallback logic is complicated.
## Summary
This corrects a comment in the documentation to match the work done in
#16523, and to match the documentation for `--format`, which states:
```
/// Supports `requirements.txt`, `pylock.toml` (PEP 751) and CycloneDX v1.5 JSON output formats.
```
## Test Plan
N/A
---------
Co-authored-by: konstin <konstin@mailbox.org>
I noticed this because pyx rejected a wheel that uv did not skip. This
warns, e.g., when the version component is not normalized, but still
attempts the upload on stable. Under preview we skip the wheel, as we do
for other invalid wheel filenames.
## Summary
Fixes#18002.
`UV_NO_DEFAULT_GROUPS=1 uv sync` currently fails with:
```
error: invalid value '1' for '--no-default-groups'
[possible values: true, false]
```
This is because `--no-default-groups` uses clap's default bool parser,
which only accepts `true`/`false`. Meanwhile, `--no-dev` (and
`UV_NO_DEV`) already uses `BoolishValueParser`, which accepts `1`,
`yes`, `on`, `true` (and their negatives).
## Fix
Add `value_parser = clap::builder::BoolishValueParser::new()` to all
four `--no-default-groups` argument definitions (`SyncArgs`, `RunArgs`,
`ExportArgs`, `TreeArgs`), matching the existing pattern used by
`--no-dev`.
## Test Plan
`UV_NO_DEFAULT_GROUPS=1 uv sync` should now succeed instead of erroring.
Co-authored-by: Ocean <ocean@Mac-mini-von-Ocean.local>
make missing files warning debug
Currently, there are a lot of spurious warning messages about missing
files for some packages. This
results in output like this, with dozens or more of the same message:
```
❯ : uv tool install audible-cli --upgrade
WARN Skipping file for beautifulsoup4: beautifulsoup4-4.6.1-py2.7.egg
WARN Skipping file for beautifulsoup4: beautifulsoup4-4.6.1-py3.5.egg
WARN Skipping file for pyasn1: pyasn1-0.0.11a-py2.3.egg
WARN Skipping file for pyasn1: pyasn1-0.0.11a-py2.4.egg
WARN Skipping file for pyasn1: pyasn1-0.0.11a-py2.5.egg
WARN Skipping file for pyasn1: pyasn1-0.0.11a-py2.6.egg
WARN Skipping file for pyasn1: pyasn1-0.0.11a-py2.7.egg
WARN Skipping file for pyasn1: pyasn1-0.0.12a-py2.3.egg
WARN Skipping file for pyasn1: pyasn1-0.0.12a-py2.4.egg
WARN Skipping file for pyasn1: pyasn1-0.0.12a-py2.5.egg
WARN Skipping file for pyasn1: pyasn1-0.0.12a-py2.6.egg
WARN Skipping file for pyasn1: pyasn1-0.0.12a-py2.7.egg
WARN Skipping file for pyasn1: pyasn1-0.0.13-py2.3.egg
WARN Skipping file for pyasn1: pyasn1-0.0.13-py2.4.egg
WARN Skipping file for pyasn1: pyasn1-0.0.13-py2.5.egg
WARN Skipping file for pyasn1: pyasn1-0.0.13-py2.6.egg
WARN Skipping file for pyasn1: pyasn1-0.0.13-py2.7.egg
```
This change makes them debug messages instead to avoid all these
unhelpful messages.
## Summary
Our redaction handling is already well covered here, but this switches
two tests to use snapshots to make them slightly clearer/more resilient
(e.g. in case we accidentally debug a token not as a string but as
bytes, in which case the previous naive string match would
false-negative here).
## Test Plan
But doctor, I am the unit tests.
Signed-off-by: William Woodruff <william@astral.sh>