Compare commits

..

21 commits
0.7.19 ... main

Author SHA1 Message Date
Zanie Blue
7e48292fac
Fix handling of pre-releases in preferences (#14498)
Some checks are pending
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
Closes https://github.com/astral-sh/uv/issues/14485

I tested this using the reproduction in the issue. It'd be nice to add
test coverage though.
2025-07-07 20:10:35 -05:00
github-actions[bot]
e31f556205
Sync latest Python releases (#14452)
Automated update for Python releases.

Co-authored-by: zanieb <2586601+zanieb@users.noreply.github.com>
2025-07-08 00:53:38 +00:00
Zanie Blue
dedced3265
Remove cache-dependency-glob examples for setup-uv (#14493)
Some checks are pending
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
See https://github.com/astral-sh/uv/pull/13163#discussion_r2063244551
2025-07-07 15:06:23 -05:00
theirix
5c6d76ca8b
Update documentation for GHA to use v6 (#14490)
## Summary

`astral-sh/setup-uv@v6` is the latest version of GitHub actions.

## Test Plan

Documentation update
2025-07-07 14:04:45 -05:00
Nils Koch
1d20530f2d
trim content of INSTALLER file (#14488)
<!--
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

We are using UV as a library and `installer()` returned `"pip\n"`. The
packages got installed by the pip package manager and not by UV. pip
seems to add a new line to the `INSTALLER` file and UV does not.

<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

<!-- How was it tested? -->
2025-07-07 18:16:50 +02:00
renovate[bot]
ddb1577a93
Update Rust crate reqwest to v0.12.22 (#14475)
Some checks are pending
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [reqwest](https://redirect.github.com/seanmonstar/reqwest) |
workspace.dependencies | patch | `=0.12.15` -> `=0.12.22` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Release Notes

<details>
<summary>seanmonstar/reqwest (reqwest)</summary>

###
[`v0.12.22`](https://redirect.github.com/seanmonstar/reqwest/blob/HEAD/CHANGELOG.md#v01222)

[Compare
Source](https://redirect.github.com/seanmonstar/reqwest/compare/v0.12.21...v0.12.22)

- Fix socks proxies when resolving IPv6 destinations.

###
[`v0.12.21`](https://redirect.github.com/seanmonstar/reqwest/blob/HEAD/CHANGELOG.md#v01221)

[Compare
Source](https://redirect.github.com/seanmonstar/reqwest/compare/v0.12.20...v0.12.21)

- Fix socks proxy to use `socks4a://` instead of `socks4h://`.
- Fix `Error::is_timeout()` to check for hyper and IO timeouts too.
- Fix request `Error` to again include URLs when possible.
- Fix socks connect error to include more context.
- (wasm) implement `Default` for `Body`.

###
[`v0.12.20`](https://redirect.github.com/seanmonstar/reqwest/blob/HEAD/CHANGELOG.md#v01220)

[Compare
Source](https://redirect.github.com/seanmonstar/reqwest/compare/v0.12.19...v0.12.20)

- Add `ClientBuilder::tcp_user_timeout(Duration)` option to set
`TCP_USER_TIMEOUT`.
- Fix proxy headers only using the first matched proxy.
- (wasm) Fix re-adding `Error::is_status()`.

###
[`v0.12.19`](https://redirect.github.com/seanmonstar/reqwest/blob/HEAD/CHANGELOG.md#v01219)

[Compare
Source](https://redirect.github.com/seanmonstar/reqwest/compare/v0.12.18...v0.12.19)

- Fix redirect that changes the method to GET should remove payload
headers.
- Fix redirect to only check the next scheme if the policy action is to
follow.
- (wasm) Fix compilation error if `cookies` feature is enabled (by the
way, it's a noop feature in wasm).

###
[`v0.12.18`](https://redirect.github.com/seanmonstar/reqwest/blob/HEAD/CHANGELOG.md#v01218)

[Compare
Source](https://redirect.github.com/seanmonstar/reqwest/compare/v0.12.17...v0.12.18)

- Fix compilation when `socks` enabled without TLS.

###
[`v0.12.17`](https://redirect.github.com/seanmonstar/reqwest/blob/HEAD/CHANGELOG.md#v01217)

[Compare
Source](https://redirect.github.com/seanmonstar/reqwest/compare/v0.12.16...v0.12.17)

- Fix compilation on macOS.

###
[`v0.12.16`](https://redirect.github.com/seanmonstar/reqwest/blob/HEAD/CHANGELOG.md#v01216)

[Compare
Source](https://redirect.github.com/seanmonstar/reqwest/compare/v0.12.15...v0.12.16)

- Add `ClientBuilder::http3_congestion_bbr()` to enable BBR congestion
control.
- Add `ClientBuilder::http3_send_grease()` to configure whether to send
use QUIC grease.
- Add `ClientBuilder::http3_max_field_section_size()` to configure the
maximum response headers.
- Add `ClientBuilder::tcp_keepalive_interval()` to configure TCP probe
interval.
- Add `ClientBuilder::tcp_keepalive_retries()` to configure TCP probe
count.
- Add `Proxy::headers()` to add extra headers that should be sent to a
proxy.
- Fix `redirect::Policy::limit()` which had an off-by-1 error, allowing
1 more redirect than specified.
- Fix HTTP/3 to support streaming request bodies.
- (wasm) Fix null bodies when calling `Response::bytes_stream()`.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNy4yIiwidXBkYXRlZEluVmVyIjoiNDEuMTcuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW50ZXJuYWwiXX0=-->

---

Closes #14243

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: konstin <konstin@mailbox.org>
2025-07-07 13:39:57 +02:00
John Mumm
d31e6ad7c7
Move fragment preservation test to directly test our redirect handling logic (#14480)
When [updating](https://github.com/astral-sh/uv/pull/14475) to the
latest `reqwest` version, our fragment propagation test broke. That test
was partially testing the `reqwest` behavior, so this PR moves the
fragment test to directly test our logic for constructing redirect
requests.
2025-07-07 12:51:21 +02:00
renovate[bot]
3a77b9cdd9
Update aws-actions/configure-aws-credentials digest to f503a18 (#14473)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| aws-actions/configure-aws-credentials | action | digest | `3d8cba3` ->
`f503a18` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNy4yIiwidXBkYXRlZEluVmVyIjoiNDEuMTcuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW50ZXJuYWwiXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 11:31:31 +02:00
renovate[bot]
1d027bd92a
Update pre-commit dependencies (#14474)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[astral-sh/ruff-pre-commit](https://redirect.github.com/astral-sh/ruff-pre-commit)
| repository | patch | `v0.12.1` -> `v0.12.2` |
| [crate-ci/typos](https://redirect.github.com/crate-ci/typos) |
repository | minor | `v1.33.1` -> `v1.34.0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

Note: The `pre-commit` manager in Renovate is not supported by the
`pre-commit` maintainers or community. Please do not report any problems
there, instead [create a Discussion in the Renovate
repository](https://redirect.github.com/renovatebot/renovate/discussions/new)
if you have any questions.

---

### Release Notes

<details>
<summary>astral-sh/ruff-pre-commit (astral-sh/ruff-pre-commit)</summary>

###
[`v0.12.2`](https://redirect.github.com/astral-sh/ruff-pre-commit/releases/tag/v0.12.2)

[Compare
Source](https://redirect.github.com/astral-sh/ruff-pre-commit/compare/v0.12.1...v0.12.2)

See: https://github.com/astral-sh/ruff/releases/tag/0.12.2

</details>

<details>
<summary>crate-ci/typos (crate-ci/typos)</summary>

###
[`v1.34.0`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.34.0)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.33.1...v1.34.0)

#### \[1.34.0] - 2025-06-30

##### Features

- Updated the dictionary with the [June
2025](https://redirect.github.com/crate-ci/typos/issues/1309) changes

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (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.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNy4yIiwidXBkYXRlZEluVmVyIjoiNDEuMTcuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW50ZXJuYWwiXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 10:36:26 +02:00
renovate[bot]
bb738aeb44
Update Rust crate test-log to v0.2.18 (#14477)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [test-log](https://redirect.github.com/d-e-s-o/test-log) |
dev-dependencies | patch | `0.2.17` -> `0.2.18` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Release Notes

<details>
<summary>d-e-s-o/test-log (test-log)</summary>

###
[`v0.2.18`](https://redirect.github.com/d-e-s-o/test-log/blob/HEAD/CHANGELOG.md#0218)

[Compare
Source](https://redirect.github.com/d-e-s-o/test-log/compare/v0.2.17...v0.2.18)

- Improved cooperation with other similar procedural macros to enable
  attribute stacking

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNy4yIiwidXBkYXRlZEluVmVyIjoiNDEuMTcuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW50ZXJuYWwiXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 10:04:50 +02:00
renovate[bot]
fc758bb755
Update Rust crate schemars to v1.0.4 (#14476)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [schemars](https://graham.cool/schemars/)
([source](https://redirect.github.com/GREsau/schemars)) |
workspace.dependencies | patch | `1.0.3` -> `1.0.4` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Release Notes

<details>
<summary>GREsau/schemars (schemars)</summary>

###
[`v1.0.4`](https://redirect.github.com/GREsau/schemars/blob/HEAD/CHANGELOG.md#104---2025-07-06)

[Compare
Source](https://redirect.github.com/GREsau/schemars/compare/v1.0.3...v1.0.4)

##### Fixed

- Fix `JsonSchema` impl on
[atomic](https://doc.rust-lang.org/std/sync/atomic/) types being ignored
on non-nightly compilers due to a buggy `cfg` check
([https://github.com/GREsau/schemars/issues/453](https://redirect.github.com/GREsau/schemars/issues/453))
- Fix compatibility with minimal dependency versions, e.g. old(-ish)
versions of `syn`
([https://github.com/GREsau/schemars/issues/450](https://redirect.github.com/GREsau/schemars/issues/450))
- Fix derive for empty tuple variants
([https://github.com/GREsau/schemars/issues/455](https://redirect.github.com/GREsau/schemars/issues/455))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNy4yIiwidXBkYXRlZEluVmVyIjoiNDEuMTcuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW50ZXJuYWwiXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 10:00:52 +02:00
renovate[bot]
1308c85efe
Update Rust crate async-channel to v2.5.0 (#14478)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [async-channel](https://redirect.github.com/smol-rs/async-channel) |
workspace.dependencies | minor | `2.3.1` -> `2.5.0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Release Notes

<details>
<summary>smol-rs/async-channel (async-channel)</summary>

###
[`v2.5.0`](https://redirect.github.com/smol-rs/async-channel/blob/HEAD/CHANGELOG.md#Version-250)

[Compare
Source](https://redirect.github.com/smol-rs/async-channel/compare/v2.4.0...v2.5.0)

- Add `Sender::closed()`
([#&#8203;102](https://redirect.github.com/smol-rs/async-channel/issues/102))

###
[`v2.4.0`](https://redirect.github.com/smol-rs/async-channel/blob/HEAD/CHANGELOG.md#Version-240)

[Compare
Source](https://redirect.github.com/smol-rs/async-channel/compare/v2.3.1...v2.4.0)

- Add `Sender::same_channel()` and `Receiver::same_channel()`.
([#&#8203;98](https://redirect.github.com/smol-rs/async-channel/issues/98))
- Add `portable-atomic` feature to support platforms without atomics.
([#&#8203;106](https://redirect.github.com/smol-rs/async-channel/issues/106))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNy4yIiwidXBkYXRlZEluVmVyIjoiNDEuMTcuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW50ZXJuYWwiXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 09:58:05 +02:00
John Mumm
f609e1ddaf
Document that VerbatimUrl does not preserve original string after serialization (#14456)
Some checks failed
CI / check cache | macos aarch64 (push) Has been cancelled
CI / check system | python on debian (push) Has been cancelled
CI / check system | python on fedora (push) Has been cancelled
CI / check system | python on ubuntu (push) Has been cancelled
CI / check system | python on rocky linux 8 (push) Has been cancelled
CI / check system | python on rocky linux 9 (push) Has been cancelled
CI / check system | graalpy on ubuntu (push) Has been cancelled
CI / check system | pypy on ubuntu (push) Has been cancelled
CI / check system | python on macos aarch64 (push) Has been cancelled
CI / check system | homebrew python on macos aarch64 (push) Has been cancelled
CI / check system | python on macos x86-64 (push) Has been cancelled
CI / check system | python3.10 on windows x86-64 (push) Has been cancelled
CI / check system | python3.10 on windows x86 (push) Has been cancelled
CI / check system | python3.13 on windows x86-64 (push) Has been cancelled
CI / check system | x86-64 python3.13 on windows aarch64 (push) Has been cancelled
CI / check system | aarch64 python3.13 on windows aarch64 (push) Has been cancelled
CI / check system | windows registry (push) Has been cancelled
CI / check system | python3.12 via chocolatey (push) Has been cancelled
CI / check system | python3.9 via pyenv (push) Has been cancelled
CI / check system | python3.13 (push) Has been cancelled
CI / check system | conda3.11 on macos aarch64 (push) Has been cancelled
CI / check system | conda3.8 on macos aarch64 (push) Has been cancelled
CI / check system | conda3.11 on linux x86-64 (push) Has been cancelled
CI / check system | conda3.8 on linux x86-64 (push) Has been cancelled
CI / check system | conda3.11 on windows x86-64 (push) Has been cancelled
CI / check system | conda3.8 on windows x86-64 (push) Has been cancelled
CI / check system | amazonlinux (push) Has been cancelled
CI / check system | embedded python3.10 on windows x86-64 (push) Has been cancelled
CI / benchmarks | walltime aarch64 linux (push) Has been cancelled
CI / benchmarks | instrumented (push) Has been cancelled
This came up in
[discussion](https://github.com/astral-sh/uv/pull/14387#issuecomment-3032223670)
on #14387.
2025-07-04 22:42:56 +02:00
Tim de Jager
eaf517efd8
Add method to get packages involved in a NoSolutionError (#14457)
Some checks are pending
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
<!--
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

<!-- What's the purpose of the change? What does it do, and why? -->

In pixi we overlay the PyPI packages over the conda packages and we
sometimes need to figure out what PyPI packages are involved in the
no-solution error. We could parse the error message, but this is pretty
error-prone, so it would be good to get access to more information. A
lot of information in this module is private and should probably stay
this way, but package names are easy enough to expose. This would help
us a lot!

I collect into a HashSet to remove duplication, and did not want to
expose a rustc_hash datastructure directly, thats's why I've chosen to
expose as an iterator :)

Let me know if any changes need to be done, and thanks!

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2025-07-04 18:08:23 +00:00
Charlie Marsh
e8bc3950ef
Remove transparent variants in uv-extract to enable retries (#14450)
Some checks are pending
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
## Summary

We think this is the culprit for the lack of retries in some settings
(e.g., Python downloads).

See: https://github.com/astral-sh/uv/issues/14425.
2025-07-03 23:32:07 +00:00
konsti
06af93fce7
Fix optional cfg gates (#14448)
Running `cargo clippy` in individual crates could raise warnings due to
unused imports as `Cow` is only used with `#[cfg(feature = "schemars")]`
2025-07-03 15:29:03 -05:00
Simon Sure
8afbd86f03
make ErrorTree for NoSolutionError externally accessible (#14444)
Some checks are pending
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
Hey, are you okay with exposing the `ErrorTree` for library consumers?

We have a use case that needs more information on conflicts. We need the
tree-structure of the conflict and be able to traverse it in particular.

Signed-off-by: Simon Sure <ssure@palantir.com>
2025-07-03 11:43:59 -05:00
konsti
a1cda6213c
Make "exit code" -> "exit status" a default filter (#14441)
Remove some test boilerplate.

Revival of https://github.com/astral-sh/uv/pull/14439 with main as base.
2025-07-03 13:50:40 +00:00
konsti
39cdfe9981
Add a test for --force-pep517 (#14310)
There was previously a gap in the test coverage in ensuring that
`--force-pep517` was respected.
2025-07-03 13:34:44 +00:00
Zanie Blue
85c0fc963b
Fix forced resolution with all extras in uv version (#14434)
Closes https://github.com/astral-sh/uv/issues/14433

Same as https://github.com/astral-sh/uv/pull/13380
2025-07-03 07:29:59 -05:00
Zanie Blue
c3f13d2505
Finish incomplete sentence in pip migration guide (#14432)
Some checks are pending
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
Fixes https://github.com/astral-sh/uv/pull/12382#discussion_r2181237729
2025-07-03 01:02:17 +00:00
41 changed files with 459 additions and 271 deletions

View file

@ -1585,7 +1585,7 @@ jobs:
run: chmod +x ./uv
- name: "Configure AWS credentials"
uses: aws-actions/configure-aws-credentials@3d8cba388a057b13744d61818a337e40a119b1a7
uses: aws-actions/configure-aws-credentials@f503a1870408dcf2c35d5c2b8a68e69211042c7d
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

View file

@ -12,7 +12,7 @@ repos:
- id: validate-pyproject
- repo: https://github.com/crate-ci/typos
rev: v1.33.1
rev: v1.34.0
hooks:
- id: typos
@ -42,7 +42,7 @@ repos:
types_or: [yaml, json5]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.1
rev: v0.12.2
hooks:
- id: ruff-format
- id: ruff

115
Cargo.lock generated
View file

@ -189,9 +189,9 @@ dependencies = [
[[package]]
name = "async-channel"
version = "2.3.1"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
dependencies = [
"concurrent-queue",
"event-listener-strategy",
@ -1165,9 +1165,9 @@ dependencies = [
[[package]]
name = "event-listener-strategy"
version = "0.5.3"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
"event-listener",
"pin-project-lite",
@ -1698,7 +1698,7 @@ dependencies = [
"tokio",
"tokio-rustls",
"tower-service",
"webpki-roots",
"webpki-roots 0.26.8",
]
[[package]]
@ -1707,6 +1707,7 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb"
dependencies = [
"base64 0.22.1",
"bytes",
"futures-channel",
"futures-core",
@ -1714,7 +1715,9 @@ dependencies = [
"http",
"http-body",
"hyper",
"ipnet",
"libc",
"percent-encoding",
"pin-project-lite",
"socket2",
"tokio",
@ -1945,6 +1948,16 @@ version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
name = "iri-string"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "is-terminal"
version = "0.4.15"
@ -3062,9 +3075,9 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.12.15"
version = "0.12.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
dependencies = [
"async-compression",
"base64 0.22.1",
@ -3079,18 +3092,14 @@ dependencies = [
"hyper",
"hyper-rustls",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"mime_guess",
"once_cell",
"percent-encoding",
"pin-project-lite",
"quinn",
"rustls",
"rustls-native-certs",
"rustls-pemfile",
"rustls-pki-types",
"serde",
"serde_json",
@ -3098,17 +3107,16 @@ dependencies = [
"sync_wrapper",
"tokio",
"tokio-rustls",
"tokio-socks",
"tokio-util",
"tower",
"tower-http",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
"webpki-roots",
"windows-registry 0.4.0",
"webpki-roots 1.0.1",
]
[[package]]
@ -3351,15 +3359,6 @@ dependencies = [
"security-framework",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.11.0"
@ -3428,9 +3427,9 @@ dependencies = [
[[package]]
name = "schemars"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1375ba8ef45a6f15d83fa8748f1079428295d403d6ea991d09ab100155fbc06d"
checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0"
dependencies = [
"dyn-clone",
"ref-cast",
@ -3442,9 +3441,9 @@ dependencies = [
[[package]]
name = "schemars_derive"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b13ed22d6d49fe23712e068770b5c4df4a693a2b02eeff8e7ca3135627a24f6"
checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80"
dependencies = [
"proc-macro2",
"quote",
@ -3968,9 +3967,9 @@ dependencies = [
[[package]]
name = "test-log"
version = "0.2.17"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f46083d221181166e5b6f6b1e5f1d499f3a76888826e6cb1d057554157cd0f"
checksum = "1e33b98a582ea0be1168eba097538ee8dd4bbe0f2b01b22ac92ea30054e5be7b"
dependencies = [
"test-log-macros",
"tracing-subscriber",
@ -3978,9 +3977,9 @@ dependencies = [
[[package]]
name = "test-log-macros"
version = "0.2.17"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f"
checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36"
dependencies = [
"proc-macro2",
"quote",
@ -4172,18 +4171,6 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-socks"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f"
dependencies = [
"either",
"futures-util",
"thiserror 1.0.69",
"tokio",
]
[[package]]
name = "tokio-stream"
version = "0.1.17"
@ -4266,6 +4253,24 @@ dependencies = [
"tower-service",
]
[[package]]
name = "tower-http"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
dependencies = [
"bitflags 2.9.1",
"bytes",
"futures-util",
"http",
"http-body",
"iri-string",
"pin-project-lite",
"tower",
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
@ -5635,7 +5640,7 @@ dependencies = [
"uv-trampoline-builder",
"uv-warnings",
"which",
"windows-registry 0.5.3",
"windows-registry",
"windows-result 0.3.4",
"windows-sys 0.59.0",
]
@ -5839,7 +5844,7 @@ dependencies = [
"tracing",
"uv-fs",
"uv-static",
"windows-registry 0.5.3",
"windows-registry",
"windows-result 0.3.4",
"windows-sys 0.59.0",
]
@ -6221,6 +6226,15 @@ dependencies = [
"rustls-pki-types",
]
[[package]]
name = "webpki-roots"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "weezl"
version = "0.1.8"
@ -6448,17 +6462,6 @@ dependencies = [
"windows-link",
]
[[package]]
name = "windows-registry"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
dependencies = [
"windows-result 0.3.4",
"windows-strings 0.3.1",
"windows-targets 0.53.0",
]
[[package]]
name = "windows-registry"
version = "0.5.3"

View file

@ -142,7 +142,7 @@ ref-cast = { version = "1.0.24" }
reflink-copy = { version = "0.1.19" }
regex = { version = "1.10.6" }
regex-automata = { version = "0.4.8", default-features = false, features = ["dfa-build", "dfa-search", "perf", "std", "syntax"] }
reqwest = { version = "=0.12.15", default-features = false, features = ["json", "gzip", "deflate", "zstd", "stream", "rustls-tls", "rustls-tls-native-roots", "socks", "multipart", "http2", "blocking"] }
reqwest = { version = "0.12.22", default-features = false, features = ["json", "gzip", "deflate", "zstd", "stream", "rustls-tls", "rustls-tls-native-roots", "socks", "multipart", "http2", "blocking"] }
reqwest-middleware = { git = "https://github.com/astral-sh/reqwest-middleware", rev = "ad8b9d332d1773fde8b4cd008486de5973e0a3f8", features = ["multipart"] }
reqwest-retry = { git = "https://github.com/astral-sh/reqwest-middleware", rev = "ad8b9d332d1773fde8b4cd008486de5973e0a3f8" }
rkyv = { version = "0.8.8", features = ["bytecheck"] }

View file

@ -982,6 +982,45 @@ mod tests {
Ok(())
}
#[tokio::test]
async fn test_redirect_preserves_fragment() -> Result<()> {
for status in &[301, 302, 303, 307, 308] {
let server = MockServer::start().await;
Mock::given(method("GET"))
.respond_with(
ResponseTemplate::new(*status)
.insert_header("location", format!("{}/redirect", server.uri())),
)
.mount(&server)
.await;
let request = Client::new()
.get(format!("{}#fragment", server.uri()))
.build()
.unwrap();
let response = Client::builder()
.redirect(reqwest::redirect::Policy::none())
.build()
.unwrap()
.execute(request.try_clone().unwrap())
.await
.unwrap();
let redirect_request =
request_into_redirect(request, &response, CrossOriginCredentialsPolicy::Secure)?
.unwrap();
assert!(
redirect_request
.url()
.fragment()
.is_some_and(|fragment| fragment == "fragment")
);
}
Ok(())
}
#[tokio::test]
async fn test_redirect_removes_authorization_header_on_cross_origin() -> Result<()> {
for status in &[301, 302, 303, 307, 308] {

View file

@ -1416,44 +1416,6 @@ mod tests {
Ok(())
}
#[tokio::test]
async fn test_redirect_preserve_fragment() -> Result<(), Error> {
let redirect_server = MockServer::start().await;
// Configure the redirect server to respond with a 307 with a relative URL.
Mock::given(method("GET"))
.respond_with(ResponseTemplate::new(307).insert_header("Location", "/foo".to_string()))
.mount(&redirect_server)
.await;
Mock::given(method("GET"))
.and(path_regex("/foo"))
.respond_with(ResponseTemplate::new(200))
.mount(&redirect_server)
.await;
let cache = Cache::temp()?;
let registry_client = RegistryClientBuilder::new(cache).build();
let client = registry_client.cached_client().uncached();
let mut url = DisplaySafeUrl::parse(&redirect_server.uri())?;
url.set_fragment(Some("fragment"));
assert_eq!(
client
.for_host(&url)
.get(Url::from(url.clone()))
.send()
.await?
.url()
.to_string(),
format!("{}/foo#fragment", redirect_server.uri()),
"Requests should preserve fragment"
);
Ok(())
}
#[test]
fn ignore_failing_files() {
// 1.7.7 has an invalid requires-python field (double comma), 1.7.8 is valid

View file

@ -1,4 +1,6 @@
use std::{borrow::Cow, str::FromStr};
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::str::FromStr;
use uv_pep508::PackageName;

View file

@ -1,5 +1,6 @@
use std::str::FromStr;
use std::{borrow::Cow, fmt::Formatter};
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::{fmt::Formatter, str::FromStr};
use uv_pep440::{Version, VersionSpecifier, VersionSpecifiers, VersionSpecifiersParseError};

View file

@ -1,5 +1,7 @@
use serde::{Deserialize, Deserializer};
use std::{borrow::Cow, str::FromStr};
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::str::FromStr;
use url::Url;
/// A host specification (wildcard, or host, with optional scheme and/or port) for which

View file

@ -365,7 +365,7 @@ impl InstalledDist {
pub fn installer(&self) -> Result<Option<String>, InstalledDistError> {
let path = self.install_path().join("INSTALLER");
match fs::read_to_string(path) {
Ok(installer) => Ok(Some(installer)),
Ok(installer) => Ok(Some(installer.trim().to_owned())),
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(err) => Err(err.into()),
}

View file

@ -3,7 +3,9 @@
//! flags set.
use serde::{Deserialize, Deserializer, Serialize};
use std::{borrow::Cow, path::Path};
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::path::Path;
use crate::{Index, IndexUrl};

View file

@ -1,4 +1,6 @@
use std::{borrow::Cow, ops::Deref};
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::ops::Deref;
use http::StatusCode;
use rustc_hash::FxHashSet;

View file

@ -2,11 +2,11 @@ use std::{ffi::OsString, path::PathBuf};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
#[error("Failed to read from zip file")]
Zip(#[from] zip::result::ZipError),
#[error(transparent)]
#[error("Failed to read from zip file")]
AsyncZip(#[from] async_zip::error::ZipError),
#[error(transparent)]
#[error("I/O operation failed during extraction")]
Io(#[from] std::io::Error),
#[error(
"The top-level of the archive must only contain a list directory, but it contains: {0:?}"

View file

@ -18,11 +18,16 @@ use uv_redacted::DisplaySafeUrl;
use crate::Pep508Url;
/// A wrapper around [`Url`] that preserves the original string.
///
/// The original string is not preserved after serialization/deserialization.
#[derive(Debug, Clone, Eq)]
pub struct VerbatimUrl {
/// The parsed URL.
url: DisplaySafeUrl,
/// The URL as it was provided by the user.
///
/// Even if originally set, this will be [`None`] after
/// serialization/deserialization.
given: Option<ArcStr>,
}

View file

@ -33135,6 +33135,102 @@
"sha256": null,
"variant": "debug"
},
"pypy-3.11.13-darwin-aarch64-none": {
"name": "pypy",
"arch": {
"family": "aarch64",
"variant": null
},
"os": "darwin",
"libc": "none",
"major": 3,
"minor": 11,
"patch": 13,
"prerelease": "",
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-macos_arm64.tar.bz2",
"sha256": "84a48e09c97f57df62cc9f01b7a6d8c3e306b6270671d871aa8ab8c06945940d",
"variant": null
},
"pypy-3.11.13-darwin-x86_64-none": {
"name": "pypy",
"arch": {
"family": "x86_64",
"variant": null
},
"os": "darwin",
"libc": "none",
"major": 3,
"minor": 11,
"patch": 13,
"prerelease": "",
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-macos_x86_64.tar.bz2",
"sha256": "bb3ae80cf5fca5044af2e42933e7692c7c5e76a828ce0eb6404a5d5da83b313c",
"variant": null
},
"pypy-3.11.13-linux-aarch64-gnu": {
"name": "pypy",
"arch": {
"family": "aarch64",
"variant": null
},
"os": "linux",
"libc": "gnu",
"major": 3,
"minor": 11,
"patch": 13,
"prerelease": "",
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-aarch64.tar.bz2",
"sha256": "9347fe691a07fd9df17a1b186554fb9d9e6210178ffef19520a579ce1f9eb741",
"variant": null
},
"pypy-3.11.13-linux-i686-gnu": {
"name": "pypy",
"arch": {
"family": "i686",
"variant": null
},
"os": "linux",
"libc": "gnu",
"major": 3,
"minor": 11,
"patch": 13,
"prerelease": "",
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-linux32.tar.bz2",
"sha256": "d08ce15dd61e9ace5e010b047104f0137110a258184e448ea8239472f10cf99b",
"variant": null
},
"pypy-3.11.13-linux-x86_64-gnu": {
"name": "pypy",
"arch": {
"family": "x86_64",
"variant": null
},
"os": "linux",
"libc": "gnu",
"major": 3,
"minor": 11,
"patch": 13,
"prerelease": "",
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-linux64.tar.bz2",
"sha256": "1410db3a7ae47603e2b7cbfd7ff6390b891b2e041c9eb4f1599f333677bccb3e",
"variant": null
},
"pypy-3.11.13-windows-x86_64-none": {
"name": "pypy",
"arch": {
"family": "x86_64",
"variant": null
},
"os": "windows",
"libc": "none",
"major": 3,
"minor": 11,
"patch": 13,
"prerelease": "",
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-win64.zip",
"sha256": "a8d36f6ceb1d9be6cf24a73b0ba103e7567e396b2f7a33426b05e4a06330755b",
"variant": null
},
"pypy-3.11.11-darwin-aarch64-none": {
"name": "pypy",
"arch": {

View file

@ -1,3 +1,4 @@
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::fmt::{Display, Formatter};
use std::ops::Deref;

View file

@ -13,10 +13,9 @@ use uv_normalize::PackageName;
use uv_pep440::Version;
use uv_types::InstalledPackagesProvider;
use crate::preferences::{Entry, Preferences};
use crate::preferences::{Entry, PreferenceSource, Preferences};
use crate::prerelease::{AllowPrerelease, PrereleaseStrategy};
use crate::resolution_mode::ResolutionStrategy;
use crate::universal_marker::UniversalMarker;
use crate::version_map::{VersionMap, VersionMapDistHandle};
use crate::{Exclusions, Manifest, Options, ResolverEnvironment};
@ -188,7 +187,7 @@ impl CandidateSelector {
if index.is_some_and(|index| !entry.index().matches(index)) {
return None;
}
Either::Left(std::iter::once((entry.marker(), entry.pin().version())))
Either::Left(std::iter::once((entry.pin().version(), entry.source())))
}
[..] => {
type Entries<'a> = SmallVec<[&'a Entry; 3]>;
@ -219,7 +218,7 @@ impl CandidateSelector {
Either::Right(
preferences
.into_iter()
.map(|entry| (entry.marker(), entry.pin().version())),
.map(|entry| (entry.pin().version(), entry.source())),
)
}
};
@ -238,7 +237,7 @@ impl CandidateSelector {
/// Return the first preference that satisfies the current range and is allowed.
fn get_preferred_from_iter<'a, InstalledPackages: InstalledPackagesProvider>(
&'a self,
preferences: impl Iterator<Item = (&'a UniversalMarker, &'a Version)>,
preferences: impl Iterator<Item = (&'a Version, PreferenceSource)>,
package_name: &'a PackageName,
range: &Range<Version>,
version_maps: &'a [VersionMap],
@ -246,7 +245,7 @@ impl CandidateSelector {
reinstall: bool,
env: &ResolverEnvironment,
) -> Option<Candidate<'a>> {
for (marker, version) in preferences {
for (version, source) in preferences {
// Respect the version range for this requirement.
if !range.contains(version) {
continue;
@ -290,9 +289,14 @@ impl CandidateSelector {
let allow = match self.prerelease_strategy.allows(package_name, env) {
AllowPrerelease::Yes => true,
AllowPrerelease::No => false,
// If the pre-release is "global" (i.e., provided via a lockfile, rather than
// a fork), accept it unless pre-releases are completely banned.
AllowPrerelease::IfNecessary => marker.is_true(),
// If the pre-release was provided via an existing file, rather than from the
// current solve, accept it unless pre-releases are completely banned.
AllowPrerelease::IfNecessary => match source {
PreferenceSource::Resolver => false,
PreferenceSource::Lock
| PreferenceSource::Environment
| PreferenceSource::RequirementsTxt => true,
},
};
if !allow {
continue;

View file

@ -3,6 +3,7 @@ use std::fmt::Formatter;
use std::sync::Arc;
use indexmap::IndexSet;
use itertools::Itertools;
use owo_colors::OwoColorize;
use pubgrub::{
DefaultStringReporter, DerivationTree, Derived, External, Range, Ranges, Reporter, Term,
@ -156,7 +157,7 @@ impl<T> From<tokio::sync::mpsc::error::SendError<T>> for ResolveError {
}
}
pub(crate) type ErrorTree = DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>;
pub type ErrorTree = DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>;
/// A wrapper around [`pubgrub::error::NoSolutionError`] that displays a resolution failure report.
pub struct NoSolutionError {
@ -367,6 +368,11 @@ impl NoSolutionError {
NoSolutionHeader::new(self.env.clone())
}
/// Get the conflict derivation tree for external analysis
pub fn derivation_tree(&self) -> &ErrorTree {
&self.error
}
/// Hint at limiting the resolver environment if universal resolution failed for a target
/// that is not the current platform or not the current Python version.
fn hint_disjoint_targets(&self, f: &mut Formatter) -> std::fmt::Result {
@ -404,6 +410,15 @@ impl NoSolutionError {
}
Ok(())
}
/// Get the packages that are involved in this error.
pub fn packages(&self) -> impl Iterator<Item = &PackageName> {
self.error
.packages()
.into_iter()
.filter_map(|p| p.name())
.unique()
}
}
impl std::fmt::Debug for NoSolutionError {

View file

@ -1,4 +1,6 @@
use std::{borrow::Cow, str::FromStr};
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::str::FromStr;
use jiff::{Timestamp, ToSpan, tz::TimeZone};

View file

@ -1,5 +1,5 @@
pub use dependency_mode::DependencyMode;
pub use error::{NoSolutionError, NoSolutionHeader, ResolveError, SentinelRange};
pub use error::{ErrorTree, NoSolutionError, NoSolutionHeader, ResolveError, SentinelRange};
pub use exclude_newer::ExcludeNewer;
pub use exclusions::Exclusions;
pub use flat_index::{FlatDistributions, FlatIndex};
@ -54,7 +54,7 @@ mod options;
mod pins;
mod preferences;
mod prerelease;
mod pubgrub;
pub mod pubgrub;
mod python_requirement;
mod redirect;
mod resolution;

View file

@ -34,6 +34,8 @@ pub struct Preference {
/// is part of, otherwise `None`.
fork_markers: Vec<UniversalMarker>,
hashes: HashDigests,
/// The source of the preference.
source: PreferenceSource,
}
impl Preference {
@ -73,6 +75,7 @@ impl Preference {
.map(String::as_str)
.map(HashDigest::from_str)
.collect::<Result<_, _>>()?,
source: PreferenceSource::RequirementsTxt,
}))
}
@ -91,6 +94,7 @@ impl Preference {
index: PreferenceIndex::from(package.index(install_path)?),
fork_markers: package.fork_markers().to_vec(),
hashes: HashDigests::empty(),
source: PreferenceSource::Lock,
}))
}
@ -112,6 +116,7 @@ impl Preference {
// `pylock.toml` doesn't have fork annotations.
fork_markers: vec![],
hashes: HashDigests::empty(),
source: PreferenceSource::Lock,
}))
}
@ -127,6 +132,7 @@ impl Preference {
index: PreferenceIndex::Any,
fork_markers: vec![],
hashes: HashDigests::empty(),
source: PreferenceSource::Environment,
})
}
@ -171,11 +177,24 @@ impl From<Option<IndexUrl>> for PreferenceIndex {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PreferenceSource {
/// The preference is from an installed package in the environment.
Environment,
/// The preference is from a `uv.ock` file.
Lock,
/// The preference is from a `requirements.txt` file.
RequirementsTxt,
/// The preference is from the current solve.
Resolver,
}
#[derive(Debug, Clone)]
pub(crate) struct Entry {
marker: UniversalMarker,
index: PreferenceIndex,
pin: Pin,
source: PreferenceSource,
}
impl Entry {
@ -193,6 +212,11 @@ impl Entry {
pub(crate) fn pin(&self) -> &Pin {
&self.pin
}
/// Return the source of the entry.
pub(crate) fn source(&self) -> PreferenceSource {
self.source
}
}
/// A set of pinned packages that should be preserved during resolution, if possible.
@ -245,6 +269,7 @@ impl Preferences {
version: preference.version,
hashes: preference.hashes,
},
source: preference.source,
});
} else {
for fork_marker in preference.fork_markers {
@ -255,6 +280,7 @@ impl Preferences {
version: preference.version.clone(),
hashes: preference.hashes.clone(),
},
source: preference.source,
});
}
}
@ -270,11 +296,13 @@ impl Preferences {
index: Option<IndexUrl>,
markers: UniversalMarker,
pin: impl Into<Pin>,
source: PreferenceSource,
) {
self.0.entry(package_name).or_default().push(Entry {
marker: markers,
index: PreferenceIndex::from(index),
pin: pin.into(),
source,
});
}

View file

@ -1,6 +1,6 @@
pub(crate) use crate::pubgrub::dependencies::PubGrubDependency;
pub(crate) use crate::pubgrub::distribution::PubGrubDistribution;
pub(crate) use crate::pubgrub::package::{PubGrubPackage, PubGrubPackageInner, PubGrubPython};
pub use crate::pubgrub::package::{PubGrubPackage, PubGrubPackageInner, PubGrubPython};
pub(crate) use crate::pubgrub::priority::{PubGrubPriorities, PubGrubPriority, PubGrubTiebreaker};
pub(crate) use crate::pubgrub::report::PubGrubReportFormatter;

View file

@ -9,7 +9,7 @@ use crate::python_requirement::PythonRequirement;
/// [`Arc`] wrapper around [`PubGrubPackageInner`] to make cloning (inside PubGrub) cheap.
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub(crate) struct PubGrubPackage(Arc<PubGrubPackageInner>);
pub struct PubGrubPackage(Arc<PubGrubPackageInner>);
impl Deref for PubGrubPackage {
type Target = PubGrubPackageInner;
@ -39,7 +39,7 @@ impl From<PubGrubPackageInner> for PubGrubPackage {
/// package (e.g., `black[colorama]`), and mark it as a dependency of the real package (e.g.,
/// `black`). We then discard the virtual packages at the end of the resolution process.
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub(crate) enum PubGrubPackageInner {
pub enum PubGrubPackageInner {
/// The root package, which is used to start the resolution process.
Root(Option<PackageName>),
/// A Python version.
@ -295,7 +295,7 @@ impl PubGrubPackage {
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash, Ord)]
pub(crate) enum PubGrubPython {
pub enum PubGrubPython {
/// The Python version installed in the current environment.
Installed,
/// The Python version for which dependencies are being resolved.

View file

@ -7,7 +7,7 @@ use uv_platform_tags::{AbiTag, Tags};
/// The reason why a package or a version cannot be used.
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum UnavailableReason {
pub enum UnavailableReason {
/// The entire package cannot be used.
Package(UnavailablePackage),
/// A single version cannot be used.
@ -29,7 +29,7 @@ impl Display for UnavailableReason {
/// Most variant are from [`MetadataResponse`] without the error source, since we don't format
/// the source and we want to merge unavailable messages across versions.
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum UnavailableVersion {
pub enum UnavailableVersion {
/// Version is incompatible because it has no usable distributions
IncompatibleDist(IncompatibleDist),
/// The wheel metadata was found, but could not be parsed.
@ -123,7 +123,7 @@ impl From<&MetadataUnavailable> for UnavailableVersion {
/// The package is unavailable and cannot be used.
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum UnavailablePackage {
pub enum UnavailablePackage {
/// Index lookups were disabled (i.e., `--no-index`) and the package was not found in a flat index (i.e. from `--find-links`).
NoIndex,
/// Network requests were disabled (i.e., `--offline`), and the package was not found in the cache.

View file

@ -47,7 +47,7 @@ use crate::fork_strategy::ForkStrategy;
use crate::fork_urls::ForkUrls;
use crate::manifest::Manifest;
use crate::pins::FilePins;
use crate::preferences::Preferences;
use crate::preferences::{PreferenceSource, Preferences};
use crate::pubgrub::{
PubGrubDependency, PubGrubDistribution, PubGrubPackage, PubGrubPackageInner, PubGrubPriorities,
PubGrubPython,
@ -447,6 +447,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
.try_universal_markers()
.unwrap_or(UniversalMarker::TRUE),
version.clone(),
PreferenceSource::Resolver,
);
}
}

View file

@ -6,6 +6,7 @@
//!
//! Then lowers them into a dependency specification.
#[cfg(feature = "schemars")]
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::fmt::Formatter;

View file

@ -933,7 +933,7 @@ impl ValidatedLock {
lock.prerelease_mode().cyan(),
options.prerelease_mode.cyan()
);
return Ok(Self::Unusable(lock));
return Ok(Self::Preferable(lock));
}
if lock.fork_strategy() != options.fork_strategy {
let _ = writeln!(

View file

@ -1730,7 +1730,7 @@ pub(crate) async fn resolve_names(
}
#[derive(Debug, Clone)]
pub(crate) enum PreferenceSource<'lock> {
pub(crate) enum PreferenceLocation<'lock> {
/// The preferences should be extracted from a lockfile.
Lock {
lock: &'lock Lock,
@ -1745,7 +1745,7 @@ pub(crate) struct EnvironmentSpecification<'lock> {
/// The requirements to include in the environment.
requirements: RequirementsSpecification,
/// The preferences to respect when resolving.
preferences: Option<PreferenceSource<'lock>>,
preferences: Option<PreferenceLocation<'lock>>,
}
impl From<RequirementsSpecification> for EnvironmentSpecification<'_> {
@ -1758,9 +1758,9 @@ impl From<RequirementsSpecification> for EnvironmentSpecification<'_> {
}
impl<'lock> EnvironmentSpecification<'lock> {
/// Set the [`PreferenceSource`] for the specification.
/// Set the [`PreferenceLocation`] for the specification.
#[must_use]
pub(crate) fn with_preferences(self, preferences: PreferenceSource<'lock>) -> Self {
pub(crate) fn with_preferences(self, preferences: PreferenceLocation<'lock>) -> Self {
Self {
preferences: Some(preferences),
..self
@ -1869,7 +1869,7 @@ pub(crate) async fn resolve_environment(
// If an existing lockfile exists, build up a set of preferences.
let preferences = match spec.preferences {
Some(PreferenceSource::Lock { lock, install_path }) => {
Some(PreferenceLocation::Lock { lock, install_path }) => {
let LockedRequirements { preferences, git } =
read_lock_requirements(lock, install_path, &upgrade)?;
@ -1881,7 +1881,7 @@ pub(crate) async fn resolve_environment(
preferences
}
Some(PreferenceSource::Entries(entries)) => entries,
Some(PreferenceLocation::Entries(entries)) => entries,
None => vec![],
};

View file

@ -49,7 +49,7 @@ use crate::commands::project::install_target::InstallTarget;
use crate::commands::project::lock::LockMode;
use crate::commands::project::lock_target::LockTarget;
use crate::commands::project::{
EnvironmentSpecification, PreferenceSource, ProjectEnvironment, ProjectError,
EnvironmentSpecification, PreferenceLocation, ProjectEnvironment, ProjectError,
ScriptEnvironment, ScriptInterpreter, UniversalState, WorkspacePython,
default_dependency_groups, script_specification, update_environment,
validate_project_requires_python,
@ -958,10 +958,10 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
let spec = EnvironmentSpecification::from(spec).with_preferences(
if let Some((lock, install_path)) = base_lock.as_ref() {
// If we have a lockfile, use the locked versions as preferences.
PreferenceSource::Lock { lock, install_path }
PreferenceLocation::Lock { lock, install_path }
} else {
// Otherwise, extract preferences from the base environment.
PreferenceSource::Entries(
PreferenceLocation::Entries(
base_site_packages
.iter()
.filter_map(Preference::from_installed)

View file

@ -385,7 +385,7 @@ async fn lock_and_sync(
let default_groups = default_dependency_groups(project.pyproject_toml())?;
let default_extras = DefaultExtras::default();
let groups = DependencyGroups::default().with_defaults(default_groups);
let extras = ExtrasSpecification::from_all_extras().with_defaults(default_extras);
let extras = ExtrasSpecification::default().with_defaults(default_extras);
let install_options = InstallOptions::default();
// Convert to an `AddTarget` by attaching the appropriate interpreter or environment.

View file

@ -15,7 +15,7 @@ fn build_basic() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -133,7 +133,7 @@ fn build_sdist() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -189,7 +189,7 @@ fn build_wheel() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -245,7 +245,7 @@ fn build_sdist_wheel() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -303,7 +303,7 @@ fn build_wheel_from_sdist() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -412,7 +412,7 @@ fn build_fail() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -488,7 +488,6 @@ fn build_workspace() -> Result<()> {
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"\\\.", ""),
(r"\[project\]", "[PKG]"),
(r"\[member\]", "[PKG]"),
@ -694,7 +693,6 @@ fn build_all_with_failure() -> Result<()> {
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"\\\.", ""),
(r"\[project\]", "[PKG]"),
(r"\[member-\w+\]", "[PKG]"),
@ -840,7 +838,7 @@ fn build_constraints() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -901,7 +899,7 @@ fn build_sha() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -1187,7 +1185,7 @@ fn build_tool_uv_sources() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let build = context.temp_dir.child("backend");
@ -1337,7 +1335,6 @@ fn build_non_package() -> Result<()> {
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"\\\.", ""),
(r"\[project\]", "[PKG]"),
(r"\[member\]", "[PKG]"),
@ -1930,7 +1927,7 @@ fn build_with_nonnormalized_name() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();
let project = context.temp_dir.child("project");
@ -1981,3 +1978,60 @@ fn build_with_nonnormalized_name() -> Result<()> {
Ok(())
}
/// Check that `--force-pep517` is respected.
///
/// The error messages for a broken project are different for direct builds vs. PEP 517.
#[test]
fn force_pep517() -> Result<()> {
// We need to use a real `uv_build` package.
let context = TestContext::new("3.12").with_exclude_newer("2025-05-27T00:00:00Z");
context
.init()
.arg("--build-backend")
.arg("uv")
.assert()
.success();
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(indoc! {r#"
[project]
name = "project"
version = "1.0.0"
[tool.uv.build-backend]
module-name = "does_not_exist"
[build-system]
requires = ["uv_build>=0.5.15,<10000"]
build-backend = "uv_build"
"#})?;
uv_snapshot!(context.filters(), context.build().env("RUST_BACKTRACE", "0"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Building source distribution (uv build backend)...
× Failed to build `[TEMP_DIR]/`
Expected a Python module at: `src/does_not_exist/__init__.py`
");
uv_snapshot!(context.filters(), context.build().arg("--force-pep517").env("RUST_BACKTRACE", "0"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Building source distribution...
Error: Missing module directory for `does_not_exist` in `src`. Found: `temp`
× Failed to build `[TEMP_DIR]/`
The build backend returned an error
Call to `uv_build.build_sdist` failed (exit status: 1)
hint: This usually indicates a problem with the package or the build environment.
");
Ok(())
}

View file

@ -517,6 +517,8 @@ impl TestContext {
if cfg!(windows) {
filters.push((" --link-mode <LINK_MODE>".to_string(), String::new()));
filters.push((r#"link-mode = "copy"\n"#.to_string(), String::new()));
// Unix uses "exit status", Windows uses "exit code"
filters.push((r"exit code: ".to_string(), "exit status: ".to_string()));
}
filters.extend(

View file

@ -7246,10 +7246,7 @@ fn fail_to_add_revert_project() -> Result<()> {
.child("setup.py")
.write_str("1/0")?;
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(filters, context.add().arg("./child"), @r#"
uv_snapshot!(context.filters(), context.add().arg("./child"), @r#"
success: false
exit_code: 1
----- stdout -----
@ -7351,10 +7348,7 @@ fn fail_to_edit_revert_project() -> Result<()> {
.child("setup.py")
.write_str("1/0")?;
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(filters, context.add().arg("./child"), @r#"
uv_snapshot!(context.filters(), context.add().arg("./child"), @r#"
success: false
exit_code: 1
----- stdout -----

View file

@ -23617,10 +23617,7 @@ fn lock_derivation_chain_prod() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.lock(), @r###"
@ -23677,10 +23674,7 @@ fn lock_derivation_chain_extra() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.lock(), @r###"
@ -23739,10 +23733,7 @@ fn lock_derivation_chain_group() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.lock(), @r###"
@ -23812,10 +23803,7 @@ fn lock_derivation_chain_extended() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.lock(), @r###"

View file

@ -14679,10 +14679,7 @@ fn compile_derivation_chain() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.pip_compile().arg("pyproject.toml"), @r###"

View file

@ -342,10 +342,7 @@ dependencies = ["flask==1.0.x"]
let requirements_txt = context.temp_dir.child("requirements.txt");
requirements_txt.write_str("./path_dep")?;
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(filters, context.pip_install()
uv_snapshot!(context.filters(), context.pip_install()
.arg("-r")
.arg("requirements.txt"), @r###"
success: false
@ -4930,10 +4927,7 @@ fn no_build_isolation() -> Result<()> {
requirements_in.write_str("anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz")?;
// We expect the build to fail, because `setuptools` is not installed.
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(filters, context.pip_install()
uv_snapshot!(context.filters(), context.pip_install()
.arg("-r")
.arg("requirements.in")
.arg("--no-build-isolation"), @r###"
@ -5001,10 +4995,7 @@ fn respect_no_build_isolation_env_var() -> Result<()> {
requirements_in.write_str("anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz")?;
// We expect the build to fail, because `setuptools` is not installed.
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(filters, context.pip_install()
uv_snapshot!(context.filters(), context.pip_install()
.arg("-r")
.arg("requirements.in")
.env(EnvVars::UV_NO_BUILD_ISOLATION, "yes"), @r###"
@ -8601,10 +8592,7 @@ fn install_build_isolation_package() -> Result<()> {
)?;
// Running `uv pip install` should fail for iniconfig.
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(filters, context.pip_install()
uv_snapshot!(context.filters(), context.pip_install()
.arg("--no-build-isolation-package")
.arg("iniconfig")
.arg(package.path()), @r###"
@ -8931,10 +8919,7 @@ fn missing_top_level() {
fn sklearn() {
let context = TestContext::new("3.12");
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(filters, context.pip_install().arg("sklearn"), @r###"
uv_snapshot!(context.filters(), context.pip_install().arg("sklearn"), @r###"
success: false
exit_code: 1
----- stdout -----
@ -8984,10 +8969,7 @@ fn resolve_derivation_chain() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.pip_install()

View file

@ -1122,10 +1122,7 @@ fn sync_build_isolation_package() -> Result<()> {
)?;
// Running `uv sync` should fail for iniconfig.
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(filters, context.sync().arg("--no-build-isolation-package").arg("source-distribution"), @r###"
uv_snapshot!(context.filters(), context.sync().arg("--no-build-isolation-package").arg("source-distribution"), @r###"
success: false
exit_code: 1
----- stdout -----
@ -1215,10 +1212,7 @@ fn sync_build_isolation_extra() -> Result<()> {
)?;
// Running `uv sync` should fail for the `compile` extra.
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
.chain(context.filters())
.collect::<Vec<_>>();
uv_snapshot!(&filters, context.sync().arg("--extra").arg("compile"), @r###"
uv_snapshot!(context.filters(), context.sync().arg("--extra").arg("compile"), @r###"
success: false
exit_code: 1
----- stdout -----
@ -1239,7 +1233,7 @@ fn sync_build_isolation_extra() -> Result<()> {
"###);
// Running `uv sync` with `--all-extras` should also fail.
uv_snapshot!(&filters, context.sync().arg("--all-extras"), @r###"
uv_snapshot!(context.filters(), context.sync().arg("--all-extras"), @r###"
success: false
exit_code: 1
----- stdout -----
@ -6985,10 +6979,7 @@ fn sync_derivation_chain() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.sync(), @r###"
@ -7051,10 +7042,7 @@ fn sync_derivation_chain_extra() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.sync().arg("--extra").arg("wsgi"), @r###"
@ -7119,10 +7107,7 @@ fn sync_derivation_chain_group() -> Result<()> {
let filters = context
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"/.*/src", "/[TMP]/src"),
])
.chain([(r"/.*/src", "/[TMP]/src")])
.collect::<Vec<_>>();
uv_snapshot!(filters, context.sync().arg("--group").arg("wsgi"), @r###"

View file

@ -1682,7 +1682,6 @@ fn tool_install_uninstallable() {
.filters()
.into_iter()
.chain([
(r"exit code: 1", "exit status: 1"),
(r"bdist\.[^/\\\s]+(-[^/\\\s]+)?", "bdist.linux-x86_64"),
(r"\\\.", ""),
(r"#+", "#"),

View file

@ -1958,3 +1958,57 @@ fn version_set_evil_constraints() -> Result<()> {
Ok(())
}
/// Bump the version with conflicting extras, to ensure we're activating the correct subset of
/// extras during the resolve.
#[test]
fn version_extras() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "myproject"
version = "1.10.31"
requires-python = ">=3.12"
[project.optional-dependencies]
foo = ["requests"]
bar = ["httpx"]
baz = ["flask"]
[tool.uv]
conflicts = [[{"extra" = "foo"}, {"extra" = "bar"}]]
"#,
)?;
uv_snapshot!(context.filters(), context.version()
.arg("--bump").arg("patch"), @r"
success: true
exit_code: 0
----- stdout -----
myproject 1.10.31 => 1.10.32
----- stderr -----
Resolved 19 packages in [TIME]
Audited in [TIME]
");
// Sync an extra, we should not remove it.
context.sync().arg("--extra").arg("foo").assert().success();
uv_snapshot!(context.filters(), context.version()
.arg("--bump").arg("patch"), @r"
success: true
exit_code: 0
----- stdout -----
myproject 1.10.32 => 1.10.33
----- stderr -----
Resolved 19 packages in [TIME]
Audited in [TIME]
");
Ok(())
}

View file

@ -27,7 +27,7 @@ jobs:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v6
```
It is considered best practice to pin to a specific uv version, e.g., with:
@ -44,7 +44,7 @@ jobs:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v6
with:
# Install a specific version of uv.
version: "0.7.19"
@ -66,7 +66,7 @@ jobs:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v6
- name: Set up Python
run: uv python install
@ -93,10 +93,10 @@ jobs:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v6
- name: "Set up Python"
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version-file: ".python-version"
```
@ -116,10 +116,10 @@ jobs:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v6
- name: "Set up Python"
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version-file: "pyproject.toml"
```
@ -146,7 +146,7 @@ jobs:
- uses: actions/checkout@v4
- name: Install uv and set the python version
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}
```
@ -187,7 +187,7 @@ jobs:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v6
- name: Install the project
run: uv sync --locked --all-extras --dev
@ -212,44 +212,11 @@ persisting the cache:
```yaml title="example.yml"
- name: Enable caching
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
```
You can configure the action to use a custom cache directory on the runner:
```yaml title="example.yml"
- name: Define a custom uv cache path
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-local-path: "/path/to/cache"
```
Or invalidate it when the lockfile changes:
```yaml title="example.yml"
- name: Define a cache dependency glob
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
```
Or when any requirements file changes:
```yaml title="example.yml"
- name: Define a cache dependency glob
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-dependency-glob: "requirements**.txt"
```
Note that `astral-sh/setup-uv` will automatically use a separate cache key for each host
architecture and platform.
Alternatively, you can manage the cache manually with the `actions/cache` action:
```yaml title="example.yml"

View file

@ -324,7 +324,7 @@ so multiple files are not needed to lock development dependencies.
The uv lockfile is always [universal](../../concepts/resolution.md#universal-resolution), so
multiple files are not needed to
[lock dependencies for each platform](#platform-specific-dependencies). This ensures that all
developers
developers are using consistent, locked versions of dependencies regardless of their machine.
The uv lockfile also supports concepts like
[pinning packages to specific indexes](../../concepts/indexes.md#pinning-a-package-to-an-index),