Compare commits

...

51 Commits
0.9.16 ... main

Author SHA1 Message Date
Charlie Marsh 0a83bf7dd5
Respect `--torch-backend` in `uv tool` commands (#17117)
## Summary

Like `uv pip`, these don't require a universal resolution, so
`--torch-backend` is easy to support.
2025-12-16 19:23:50 -05:00
Charlie Marsh e603761862
Support remote `pylock.toml` files (#17119)
## Summary

Closes https://github.com/astral-sh/uv/issues/17112.
2025-12-16 19:16:23 -05:00
Zanie Blue 4f6f56b070
Add ty to the README (#17139) 2025-12-16 09:39:59 -06:00
Zanie Blue 66f7093ad2
Move a couple README items into the FAQ (#17148) 2025-12-16 08:36:06 -06:00
Zanie Blue 60df92f9aa
Copy the Code of Conduct from Ruff (#17145) 2025-12-16 14:12:15 +00:00
konsti 0cee76417f
Bump version to 0.9.18 (#17141)
It's been a week.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2025-12-16 13:32:35 +00:00
jkipper af348c2a88
Ignore pyproject index username in lockfile comparison (#16995)
<!--
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

Pyproject.toml index url may contain a username while lockfile doesn't.
Treat it as the same index to prevent unintended package updates

Fixes #16436

---------

Co-authored-by: konstin <konstin@mailbox.org>
2025-12-16 10:47:50 +00:00
Diyor Khayrutdinov b58f543e5e
Support redirects in `uv publish` (#17130)
<!--
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

Follow redirects for `uv publish`. Related issue:
https://github.com/astral-sh/uv/issues/17126.

## Test Plan

<!-- How was it tested? -->
Added a unit test to test the custom redirect logic.

---------

Co-authored-by: konstin <konstin@mailbox.org>
2025-12-16 09:04:28 +00:00
Charlie Marsh 13e7ad62cb
Accept `--torch-backend` in `[tool.uv]` (#17116)
## Summary

I'd like to add `--torch-backend` to `uv tool`, so this PR lifts the
setting out of `[tool.uv.pip]`. Like other settings, if it's in
`[tool.uv.pip]`, it will take preference for `uv pip` operations.
2025-12-15 20:18:40 -05:00
Tomasz Kramkowski 94c97b6434
Add value hints to command line arguments to improve shell completion accuracy (#17080)
## Summary

This partially addresses #17076 by adding `value_hint` to various
arguments.

For cases where an option takes a path to either specifically a file or
a directory directory, `ValueHint::FilePath` and `ValueHint::DirPath`
are used respectively to try to limit the amount of noise presented by
completions in shells which support it.

For cases where a URL (and only a URL, not a path) can be supplied,
`ValueHint::Url` is used.

For cases where a python interpreter is to be specified,
`ValueHint::CommandName` is used which will tab complete from `$PATH` by
default, but will fall back to completing executable filenames if you
start typing a path.

Finally, for the many cases where there is no built in completion which
would make sense, and where default completion of a path would make no
sense (e.g. a package name, or version specifier, or date)
`ValueHint::Other` is used to explicitly disable completion.

## Test Plan

Manually tested a bunch of these. These _could_ be automated in the
sense that we could snapshot the completion from zsh but I've not
thought about how that could be done yet.
2025-12-15 18:29:32 +00:00
konsti af95677b9b
Update cargo shear (#17106)
Requires a companion PR that updates the GitHub Action.
2025-12-15 18:46:35 +01:00
konsti a5d50a20d2
Better rendering for multiline error messages (#17132)
Split out from https://github.com/astral-sh/uv/pull/17110

Indent multiline error messages properly, and add a test with a
multiline context and a context below since that combination isn't
captured atm.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2025-12-15 16:29:11 +00:00
samypr100 a768a9d111
Relax error when using uv add with `UV_GIT_LFS` set (#17127)
## Summary

Closes https://github.com/astral-sh/uv/issues/17083

Previously having `UV_GIT_LFS` set would cause an error when adding a
non-git requirement such as ```error: `requirement` did not resolve to a
Git repository, but a Git extension (`--lfs`) was provided.```

## Test Plan

Additional test has been added.
2025-12-15 08:26:14 -06:00
Tomasz Kramkowski d20948bec2
Support creating lock files on ExFAT on MacOS (#17115)
## Summary

Fix #16859 by falling back to simply creating the lock file and then
attempting to apply permissions in cases where the temporary lockfile
cannot be renamed without overwriting (persist_noclobber) due to lack of
underlying support from the filesystem.

I've also improved the error handling.

## Test Plan

Manually on MacOS with an ExFAT partition.

~~~ bash session
$ hdiutil create -size 1g -fs ExFAT -volname EXFATDISK exfat.dmg
$ hdiutil attach exfat.dmg
$ cd /Volumes/EXFATDISK
$ uv init --bare --cache-dir build/uv/cache -v 
~~~
2025-12-15 14:05:05 +00:00
Ben Beasley a2d64aa224
Update spdx dependency to 0.13 (#17129)
<!--
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

Updates the `spdx` dependency from 0.12.x to the latest release, 0.13.2.

https://github.com/EmbarkStudios/spdx/blob/0.13.2/CHANGELOG.md

Here in uv upstream, this just helps keep dependencies up to date; there
isn’t any other particular specific motivation or benefit. Downstream in
Fedora, this change allows me to avoid maintaining a `rust-spdx0.12`
compat package.
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

<!-- How was it tested? -->
`cargo nextest run -- --skip python_install::python_install_pyodide`
2025-12-14 13:25:06 -05:00
haruna c43315f4eb
Change exclude-newer type into optional string (#17121)
<!--
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

fix: #17103 

## Test Plan

The following settings will be enabled for the schema.

```toml
[tool.uv]
exclude-newer = "P7D"
```
2025-12-13 13:42:01 -06:00
Charlie Marsh e77ee15204
Enforce latest-version in `@latest` requests (#17114)
## Summary

Given `uv tool install {name}@latest`, we make revalidation requests for
`{name}`, but we don't actually add a "latest" constraint when resolving
-- we just assume that since the package is unpinned, and we're fetching
the latest available versions, the resolver will select the latest
version.

However, imagine a package in which the latest version requires Python
3.13 or later, but prior versions support Python 3.9 and up. If we
happen to select Python 3.9 ahead of resolution, and the user requests
`{name}@latest`, we would backtrack to the non-latest version due to the
Python mismatch.

This PR modifies `uv tool install` and `uv tool run` to first determine
the latest version, then provide it as a constraint when resolving.
2025-12-13 10:39:01 -05:00
Zanie Blue ed37f3b432
Drop arm musl caveat from Docker documentation (#17111)
This works fine now

```
❯ docker run --rm -it ghcr.io/astral-sh/uv:alpine sh -c "uv python install 3.14"
Installed Python 3.14.2 in 2.77s
 + cpython-3.14.2-linux-aarch64-musl (python3.14)
```
2025-12-12 19:15:15 +00:00
konsti 3e80b10272
Avoid panics due to reads on failed requests (#17098)
Fixes https://github.com/astral-sh/uv/issues/17090, specifically the
panic, not the upstream bug.
2025-12-12 18:02:49 +01:00
konsti 7ad441a0bd
Better error handling for `uv publish` (#17096)
* Use `is_transient_network_error` as we do in all other cases, see also
https://github.com/astral-sh/uv/pull/16245
* Don't report success in the progress reporter if the upload failed
2025-12-12 18:02:37 +01:00
Zanie Blue 5a55bbe883
Include Docker images with the alpine version, e.g., `python3.x-alpine3.23` (#17100)
Closes https://github.com/astral-sh/uv/issues/17095

This also stabilizes the Alpine version for users that do not choose to
pin it. We could add this to the build matrix separately to avoid that,
but I think that's okay?
2025-12-12 14:17:15 +00:00
Tomasz Kramkowski 6ad80c5150
Refactor the Changelog for use in `report_dry_run` (#17039)
## Summary

Remove duplication in `report_dry_run` by making `Changelog` support
both local and remote dists. This is in support of #16653 and will form
a new basis for #16981.

This also involved refactoring `InstallLogger` and its implementations
to support dry run logging.

Additionally includes some minor refactoring in `SummaryInstallLogger`
and a fix to `InstalledVersion`.

See https://github.com/astral-sh/uv/compare/tk/dry-run-refactor for an
alternative approach (although obviously comes with some caveats).

## Test Plan

There are already quite a few tests which cover the output and they
pass. Manual testing was used to ensure styling stayed consistent.
2025-12-12 10:37:30 +00:00
Charlie Marsh 38ae414682
Initialize S3 signer once (#17092)
## Summary

Right now, we initialize the signer many times concurrently.
2025-12-11 20:36:41 +00:00
Matthew Mckee 6de869cc88
Speed up cache size command (#17015)
## Summary

`uv cache size` can be quite slow. Here i use
https://github.com/sharkdp/diskus to walk the cache directory with in
multiple threads.

Add cli option to set the number of threads and default to `
std:🧵:available_parallelism()` or 1.

## Test Plan

Added cli statement with info log test.

I believe this is a fair test, where i set cache dir to a large
directory.

```bash
matthew@matthew-main ~/develop/personal/uv                                                                                                                                                                                                                 [14:17:50]                                                                                                                                                                                                                                       [±cache-size-speed-up ✓▴]
> $ uv cache size --preview-features cache-size -H --cache-dir ~/develop/                                                                                                                                                                   [±cache-size-speed-up ✓▴]
75.7GiB

matthew@matthew-main ~/develop/personal/uv                                                                                                                                                                                                                 [14:18:24]
> $ hyperfine 'uv cache size --preview-features cache-size -H --cache-dir ~/develop/' 'target/debug/uv cache size --preview-features cache-size -H --cache-dir ~/develop/'                                                                  [±cache-size-speed-up ✓▴]
Benchmark 1: uv cache size --preview-features cache-size -H --cache-dir ~/develop/
  Time (mean ± σ):      1.059 s ±  0.014 s    [User: 0.171 s, System: 0.884 s]
  Range (min … max):    1.048 s …  1.097 s    10 runs

Benchmark 2: target/debug/uv cache size --preview-features cache-size -H --cache-dir ~/develop/
  Time (mean ± σ):     413.8 ms ±  17.1 ms    [User: 5789.2 ms, System: 1682.0 ms]
  Range (min … max):   386.3 ms … 441.6 ms    10 runs

Summary
  target/debug/uv cache size --preview-features cache-size -H --cache-dir ~/develop/ ran
    2.56 ± 0.11 times faster than uv cache size --preview-features cache-size -H --cache-dir ~/develop/  
```
2025-12-11 12:11:01 -05:00
Mathieu Kniewallner 59d73fdddf
docs(settings): better document `exclude-newer*` (#17079)
<!--
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

Following the changes in https://github.com/astral-sh/uv/pull/16814,
documentation for
[`--exclude-newer`](https://docs.astral.sh/uv/reference/cli/#uv-sync--exclude-newer)
and
[`--exclude-newer-package`](https://docs.astral.sh/uv/reference/cli/#uv-sync--exclude-newer-package)
arguments were updated, but not their settings counterparts, so this
just updates the settings ones to closely match the arguments ones.

## Test Plan

Ran documentation locally.
2025-12-11 09:23:48 -06:00
Charlie Marsh 4c1571fb76
Fix version reference in resolver example (#17085) 2025-12-11 15:53:48 +01:00
konsti ebdffaf728
CI Perf: fast-build (#16780)
Co-authored-by: Zanie Blue <contact@zanie.dev>
2025-12-11 13:51:37 +00:00
Eashwar Ranganathan 3bb7f67c71
Explicitly set EntryType for file entries in tar (#17043)
## Summary
This PR explicitly sets the entry type for files in an sdist. This
changes the entry type from `AREGTYPE` (the 'legacy' regular file type)
to `REGTYPE` (the 'normal' regular file type) in the generated tar.

This change works around a bug in the python `tarfile` module that
causes all entries after a certain point in the tar to be silently
ignored if any entry matches some very specific conditions. In `maturin`
this was very visible since the `PKG-INFO` was written at the very end
so `twine check` would loudly complain that the `PKG-INFO` was missing
and that the sdist was invalid. In `uv` the `PKG-INFO` is written at the
beginning so this issue is unlikely to be caught.

Note that this change does mean that sdists created with newer versions
of the uv build backend will not be byte-for-byte identical with sdists
from an older version.

See https://github.com/PyO3/maturin/issues/2855#issuecomment-3546501132

## Test Plan
This is the same as the change that was made in maturin to work around
the same issue

---------

Co-authored-by: konstin <konstin@mailbox.org>
2025-12-11 10:37:35 +00:00
konsti caac4814df
Add crate graph to contributing guide (#17062)
I share this regularly with people, we should document it.

---------

Co-authored-by: Tomasz Kramkowski <tom@astral.sh>
2025-12-10 09:01:00 -06:00
Zanie Blue a550743bed
Drop some non-integration exclude-newer tests (#17071)
Closes https://github.com/astral-sh/uv/issues/17070

Claude added these and they're unstable and just not useful imo.
2025-12-10 14:04:05 +00:00
Zanie Blue 94f1f02d85
Update the exclude newer duration tests to demonstrate package version changes (#17055)
Follows #16814 updating the test cases with Claude so that the
timestamps and durations are on the boundary of package versions so we
see actual version changes in the lockfile.
2025-12-10 07:47:44 -06:00
Ben Beasley 36806f8e66
Gate a few more tests on the pypi feature (#17059)
<!--
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

Gate a few more tests on the `pypi` feature. All of these fail in
offline environments because they try to communicate with PyPI.
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

<!-- How was it tested? -->
Applied as a patch to Fedora’s `uv` package, version 0.9.16.
2025-12-10 10:41:47 +01:00
Zanie Blue 2b5d65e61d
Bump version to 0.9.17 (#17058) 2025-12-09 16:36:00 -06:00
github-actions[bot] 81c99dd438
Sync latest Python releases (#17057)
Automated update for Python releases.

Co-authored-by: zanieb <2586601+zanieb@users.noreply.github.com>
2025-12-09 22:30:11 +00:00
Zanie Blue b931c6687c
Increase the size of binary build runners (#17016)
Summary from asking Claude to compare the runtime

```
  | Job                       | Before | After | Saved | Reduction |
  |---------------------------|--------|-------|-------|-----------|
  | macos-aarch64             | 19.1m  | 9.8m  | 9.2m  | 48%       |
  | macos-x86_64              | 15.1m  | 9.2m  | 5.9m  | 39%       |
  | linux-arm (aarch64)       | 18.6m  | 12.2m | 6.4m  | 34%       |
  | linux-arm (armv7)         | 17.4m  | 11.5m | 5.9m  | 34%       |
  | musllinux-cross (aarch64) | 19.3m  | 13.2m | 6.1m  | 32%       |
  | linux-arm (arm)           | 16.6m  | 11.4m | 5.2m  | 31%       |
  | musllinux-cross (armv7)   | 16.4m  | 10.8m | 5.6m  | 34%       |
```
The longest-running affected job went from 19.3m → 13.2m (saved 6.1
minutes, 32% faster).
2025-12-09 16:04:43 -06:00
Zanie Blue eca36eed08
Fix a typo (#17056) 2025-12-09 21:49:52 +00:00
William Woodruff 69910b4aab
Publish PyPI releases before crates.io artifacts (#16989)
## Summary

Closes #16987.

## Test Plan

We need a good way to dry-run this...

---------

Signed-off-by: William Woodruff <william@astral.sh>
2025-12-09 15:20:21 -06:00
konsti 8d2c2e8cdf
Better source-exclude reference docs (#16832)
Fixed https://github.com/astral-sh/uv/issues/16821

This is already explained in the guide, but it was missing from the
reference docs.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2025-12-09 21:14:28 +00:00
Niko Pikall b6686fbce3
Update UV_VERSION in docs for GitLab CI/CD (#17040)
<!--
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
Update the `UV_VERSION`, such that a `copy-to-clipboard` action and
pasting into a `.gitlab-ci.yml` is not 4 minor versions behind, as it
happened to me a couple of times.

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

## Test Plan
I ran `mkdocs serve` and it worked (I literally only changed one
character)
<!-- How was it tested? -->
2025-12-09 14:56:27 -06:00
Charlie Marsh 4af2d2b922
Add `torch-tensorrt` and `torchao` to the PyTorch list (#17053)
## Summary

Closes https://github.com/astral-sh/uv/issues/17050.
2025-12-09 20:29:32 +00:00
Charlie Marsh 2502577c9d
Sort packages in GPU lists (#17054)
## Summary

No semantic changes; this is just bothering me.
2025-12-09 15:10:06 -05:00
Zanie Blue d0a6f5d13f
Add support for relative durations in `exclude-newer` (#16814)
Adds support for "friendly" durations like, 1 week, 7 days, 24 hours
using Jiff's parser. During resolution, we calculate this relative to
the current time and resolve it into a concrete timestamp for the
lockfile. If the span has not changed, e.g., to another relative value,
then locking again will not change the lockfile. The locked timestamp
will only be updated when the lockfile is invalidated, e.g., with
`--upgrade`. This prevents the lockfile from repeatedly churning when a
relative value is used.
2025-12-09 19:52:14 +00:00
Zanie Blue 7b6b02a7d1
Recommend `UV_NO_DEV` in Docker installs (#17030)
Closes https://github.com/astral-sh/uv/issues/17027

See also, https://github.com/astral-sh/uv-docker-example/pull/73
2025-12-09 12:12:08 -06:00
William Woodruff 0dd71f4382
Bump ambient-id to 0.0.7 (#17048) 2025-12-09 09:08:26 -08:00
F4RAN 38ce3b2919
Add hint for misplaced `--verbose` in `uv tool run` (#17020)
Resolves #16777

## Summary
When a command fails, users sometimes add --verbose after the package
name (e.g., uvx foo --verbose) instead of before it (e.g., uvx --verbose
foo). This adds a hint that suggests moving --verbose before the
command.
The hint appears when a verbose flag is detected in the subcommand
arguments and the command fails to resolve. It works for both uvx and uv
tool run.

## Test Plan
Tested by running:
uvx foo-does-not-exist --verbose - shows the hint
uv tool run foo-does-not-exist --verbose - shows the hint
The hint only appears when verbose flags are detected, and the message
shows the correct command format.

## Screenshot
<img width="920" height="34" alt="image"
src="https://github.com/user-attachments/assets/f6c303f6-b5e6-441f-8d8d-9f5e6ab87c87"
/>

Open to feedback and happy to make changes as needed! 💯

---------

Co-authored-by: Tomasz (Tom) Kramkowski <tom@astral.sh>
2025-12-09 10:15:06 -06:00
Zanie Blue a70ee58ae1
Move test support files out of `scripts/` into `test/`
(#17032)

It's been bothering me that we have a bunch of stub packages and such in
a `scripts` directory.
2025-12-09 10:06:05 -06:00
chisato 9774f8f1d4
Fix relocatable nushell activation script (#17036)
<!--
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? -->
Nushell activation now computes the venv root dynamically via path self
for relocatable venvs, while non-relocatable venvs still embed a quoted
absolute path

Still keep `activate.csh` (maybe delete is also an option)

close https://github.com/astral-sh/uv/issues/16973

<!-- How was it tested? -->
2025-12-09 14:39:55 +00:00
Zanie Blue 77df5887e4
Add a Claude hook for formatting (#17033)
Inspired by
https://github.com/oven-sh/bun/blob/main/.claude/hooks/pre-bash-zig-build.js

This has been driving me pretty crazy and the fix is easy enough.
2025-12-08 16:57:17 +00:00
Zanie Blue 4e1469b151
Remove now unused generate tests (#17031)
I missed this in #16969
2025-12-08 15:50:40 +00:00
Zanie Blue 5a6f2ea319
Generate reference documentation at publish-time and the JSON schema at release-time (#16969)
It'd be nice to avoid churn for contributors. This is a pretty frequent
cause of CI failures and I don't think we really need to have the
reference documentation committed.
2025-12-08 12:31:38 +00:00
Charlie Marsh 28a8194a67
Respect dropped (but explicit) indexes in dependency groups (#17012)
## Summary

There are a class of outcomes whereby an index might not be included in
"allowed indexes", but could still correctly appear in a lockfile. In
the linked case, we have two `default = true` indexes, and one of them
is also named. We omit the second `default = true` index from the list
of "allowed indexes", but since it's named, a dependency can reference
it explicitly. We handle this correctly for `project.dependencies`, but
the handling was incorrectly omitting dependency groups.

Closes https://github.com/astral-sh/uv/issues/16843.
2025-12-06 14:06:46 +00:00
460 changed files with 6262 additions and 14453 deletions

View File

@ -0,0 +1,81 @@
# /// script
# requires-python = ">=3.12"
# dependencies = []
# ///
"""Post-edit hook to auto-format files after Claude edits."""
import json
import subprocess
import sys
from pathlib import Path
def format_rust(file_path: str, cwd: str) -> None:
"""Format Rust files with cargo fmt."""
try:
subprocess.run(
["cargo", "fmt", "--", file_path],
cwd=cwd,
capture_output=True,
)
except FileNotFoundError:
pass
def format_python(file_path: str, cwd: str) -> None:
"""Format Python files with ruff."""
try:
subprocess.run(
["uvx", "ruff", "format", file_path],
cwd=cwd,
capture_output=True,
)
except FileNotFoundError:
pass
def format_prettier(file_path: str, cwd: str, prose_wrap: bool = False) -> None:
"""Format files with prettier."""
args = ["npx", "prettier", "--write"]
if prose_wrap:
args.extend(["--prose-wrap", "always"])
args.append(file_path)
try:
subprocess.run(args, cwd=cwd, capture_output=True)
except FileNotFoundError:
pass
def main() -> None:
import os
input_data = json.load(sys.stdin)
tool_name = input_data.get("tool_name")
tool_input = input_data.get("tool_input", {})
file_path = tool_input.get("file_path")
# Only process Write, Edit, and MultiEdit tools
if tool_name not in ("Write", "Edit", "MultiEdit"):
return
if not file_path:
return
cwd = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
path = Path(file_path)
ext = path.suffix
if ext == ".rs":
format_rust(file_path, cwd)
elif ext in (".py", ".pyi"):
format_python(file_path, cwd)
elif ext in (".json5", ".yaml", ".yml"):
format_prettier(file_path, cwd)
elif ext == ".md":
format_prettier(file_path, cwd, prose_wrap=True)
if __name__ == "__main__":
main()

15
.claude/settings.json Normal file
View File

@ -0,0 +1,15 @@
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "uv run .claude/hooks/post-edit-format.py"
}
]
}
]
}
}

View File

@ -98,7 +98,7 @@ jobs:
macos-x86_64:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: macos-14
runs-on: depot-macos-14
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
@ -157,7 +157,7 @@ jobs:
macos-aarch64:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: macos-14
runs-on: depot-macos-14
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
@ -417,7 +417,7 @@ jobs:
linux-arm:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: ubuntu-latest
runs-on: depot-ubuntu-22.04-8
timeout-minutes: 30
strategy:
matrix:
@ -956,7 +956,7 @@ jobs:
musllinux-cross:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: ubuntu-latest
runs-on: depot-ubuntu-22.04-8
strategy:
matrix:
platform:

View File

@ -184,13 +184,13 @@ jobs:
- buildpack-deps:trixie,trixie,debian
- debian:bookworm-slim,bookworm-slim
- buildpack-deps:bookworm,bookworm
- python:3.14-alpine,python3.14-alpine
- python:3.13-alpine,python3.13-alpine
- python:3.12-alpine,python3.12-alpine
- python:3.11-alpine,python3.11-alpine
- python:3.10-alpine,python3.10-alpine
- python:3.9-alpine,python3.9-alpine
- python:3.8-alpine,python3.8-alpine
- python:3.14-alpine3.23,python3.14-alpine3.23,python3.14-alpine
- python:3.13-alpine3.23,python3.13-alpine3.23,python3.13-alpine
- python:3.12-alpine3.23,python3.12-alpine3.23,python3.12-alpine
- python:3.11-alpine3.23,python3.11-alpine3.23,python3.11-alpine
- python:3.10-alpine3.23,python3.10-alpine3.23,python3.10-alpine
- python:3.9-alpine3.22,python3.9-alpine3.22,python3.9-alpine
- python:3.8-alpine3.20,python3.8-alpine3.20,python3.8-alpine
- python:3.14-trixie,python3.14-trixie
- python:3.13-trixie,python3.13-trixie
- python:3.12-trixie,python3.12-trixie

View File

@ -27,6 +27,8 @@ jobs:
outputs:
# Flag that is raised when any code is changed
code: ${{ steps.changed.outputs.code_any_changed }}
# Flag that is raised when uv.schema.json is changed (e.g., in a release PR)
schema: ${{ steps.changed.outputs.schema_changed }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
@ -40,10 +42,16 @@ jobs:
CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha || 'origin/main' }}...HEAD)
CODE_CHANGED=false
SCHEMA_CHANGED=false
while IFS= read -r file; do
# Generated markdown and JSON files are checked during test runs.
if [[ "${file}" =~ ^docs/ && ! "${file}" =~ ^docs/reference/(cli|settings).md && ! "${file}" =~ ^docs/reference/environment.md ]]; then
# Check if the schema file changed (e.g., in a release PR)
if [[ "${file}" == "uv.schema.json" ]]; then
echo "Detected schema change: ${file}"
SCHEMA_CHANGED=true
fi
if [[ "${file}" =~ ^docs/ ]]; then
echo "Skipping ${file} (matches docs/ pattern)"
continue
fi
@ -70,6 +78,7 @@ jobs:
done <<< "${CHANGED_FILES}"
echo "code_any_changed=${CODE_CHANGED}" >> "${GITHUB_OUTPUT}"
echo "schema_changed=${SCHEMA_CHANGED}" >> "${GITHUB_OUTPUT}"
lint:
timeout-minutes: 10
name: "lint"
@ -208,7 +217,12 @@ jobs:
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: "Generate all"
run: cargo dev generate-all --mode check
run: cargo dev generate-all --mode dry-run
- name: "Check sysconfig mappings"
run: cargo dev generate-sysconfig-metadata --mode check
- name: "Check JSON schema"
if: ${{ needs.determine_changes.outputs.schema == 'true' }}
run: cargo dev generate-json-schema --mode check
cargo-shear:
timeout-minutes: 10
@ -219,7 +233,7 @@ jobs:
with:
persist-credentials: false
- name: "Install cargo shear"
uses: taiki-e/install-action@a416ddeedbd372e614cc1386e8b642692f66865e # v2.57.1
uses: taiki-e/install-action@d850aa816998e5cf15f67a78c7b933f2a5033f8a # v2.63.3
with:
tool: cargo-shear
- run: cargo shear
@ -275,6 +289,7 @@ jobs:
UV_HTTP_RETRIES: 5
run: |
cargo nextest run \
--cargo-profile fast-build \
--features python-patch,native-auth,secret-service \
--workspace \
--status-level skip --failure-output immediate-final --no-fail-fast -j 20 --final-status-level slow
@ -316,6 +331,7 @@ jobs:
UV_HTTP_RETRIES: 5
run: |
cargo nextest run \
--cargo-profile fast-build \
--no-default-features \
--features python,python-managed,pypi,git,git-lfs,performance,crates-io,native-auth,apple-native \
--workspace \
@ -371,6 +387,7 @@ jobs:
shell: bash
run: |
cargo nextest run \
--cargo-profile fast-build \
--no-default-features \
--features python,pypi,python-managed,native-auth,windows-native \
--workspace \
@ -510,6 +527,14 @@ jobs:
version: "0.9.13"
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: "Generate reference documentation"
run: |
cargo dev generate-options-reference
cargo dev generate-cli-reference
cargo dev generate-env-vars-reference
- name: "Add SSH key"
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
@ -539,15 +564,15 @@ jobs:
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
- name: "Build"
run: cargo build
run: cargo build --profile no-debug
- name: "Upload binary"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: uv-linux-libc-${{ github.sha }}
path: |
./target/debug/uv
./target/debug/uvx
./target/no-debug/uv
./target/no-debug/uvx
retention-days: 1
build-binary-linux-aarch64:
@ -566,15 +591,15 @@ jobs:
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
- name: "Build"
run: cargo build
run: cargo build --profile no-debug
- name: "Upload binary"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: uv-linux-aarch64-${{ github.sha }}
path: |
./target/debug/uv
./target/debug/uvx
./target/no-debug/uv
./target/no-debug/uvx
retention-days: 1
build-binary-linux-musl:
@ -598,15 +623,15 @@ jobs:
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
- name: "Build"
run: cargo build --target x86_64-unknown-linux-musl --bin uv --bin uvx
run: cargo build --profile no-debug --target x86_64-unknown-linux-musl --bin uv --bin uvx
- name: "Upload binary"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: uv-linux-musl-${{ github.sha }}
path: |
./target/x86_64-unknown-linux-musl/debug/uv
./target/x86_64-unknown-linux-musl/debug/uvx
./target/x86_64-unknown-linux-musl/no-debug/uv
./target/x86_64-unknown-linux-musl/no-debug/uvx
retention-days: 1
build-binary-macos-aarch64:
@ -624,15 +649,15 @@ jobs:
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
- name: "Build"
run: cargo build --bin uv --bin uvx
run: cargo build --profile no-debug --bin uv --bin uvx
- name: "Upload binary"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: uv-macos-aarch64-${{ github.sha }}
path: |
./target/debug/uv
./target/debug/uvx
./target/no-debug/uv
./target/no-debug/uvx
retention-days: 1
build-binary-macos-x86_64:
@ -650,15 +675,15 @@ jobs:
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
- name: "Build"
run: cargo build --bin uv --bin uvx
run: cargo build --profile no-debug --bin uv --bin uvx
- name: "Upload binary"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: uv-macos-x86_64-${{ github.sha }}
path: |
./target/debug/uv
./target/debug/uvx
./target/no-debug/uv
./target/no-debug/uvx
retention-days: 1
build-binary-windows-x86_64:
@ -686,15 +711,15 @@ jobs:
- name: "Build"
working-directory: ${{ env.UV_WORKSPACE }}
run: cargo build --bin uv --bin uvx
run: cargo build --profile no-debug --bin uv --bin uvx
- name: "Upload binary"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: uv-windows-x86_64-${{ github.sha }}
path: |
${{ env.UV_WORKSPACE }}/target/debug/uv.exe
${{ env.UV_WORKSPACE }}/target/debug/uvx.exe
${{ env.UV_WORKSPACE }}/target/no-debug/uv.exe
${{ env.UV_WORKSPACE }}/target/no-debug/uvx.exe
retention-days: 1
build-binary-windows-aarch64:
@ -726,15 +751,15 @@ jobs:
- name: "Build"
working-directory: ${{ env.UV_WORKSPACE }}
run: cargo build --target aarch64-pc-windows-msvc
run: cargo build --profile no-debug --target aarch64-pc-windows-msvc
- name: "Upload binary"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: uv-windows-aarch64-${{ github.sha }}
path: |
${{ env.UV_WORKSPACE }}/target/aarch64-pc-windows-msvc/debug/uv.exe
${{ env.UV_WORKSPACE }}/target/aarch64-pc-windows-msvc/debug/uvx.exe
${{ env.UV_WORKSPACE }}/target/aarch64-pc-windows-msvc/no-debug/uv.exe
${{ env.UV_WORKSPACE }}/target/aarch64-pc-windows-msvc/no-debug/uvx.exe
retention-days: 1
build-binary-msrv:
@ -759,10 +784,10 @@ jobs:
- name: "Install mold"
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
- run: cargo +${MSRV} build
- run: cargo +${MSRV} build --profile no-debug
env:
MSRV: ${{ steps.msrv.outputs.value }}
- run: ./target/debug/uv --version
- run: ./target/no-debug/uv --version
build-binary-freebsd:
needs: determine_changes
@ -783,7 +808,7 @@ jobs:
chmod +x cross
mv cross /usr/local/bin/cross
cross build --target x86_64-unknown-freebsd
cross build --target x86_64-unknown-freebsd --profile no-debug
- name: Test in Firecracker VM
uses: acj/freebsd-firecracker-action@a5a3fc1709c5b5368141a5699f10259aca3cd965 # v0.6.0
@ -797,8 +822,8 @@ jobs:
cat <<EOF > $include_path
target
target/x86_64-unknown-freebsd
target/x86_64-unknown-freebsd/debug
target/x86_64-unknown-freebsd/debug/uv
target/x86_64-unknown-freebsd/no-debug
target/x86_64-unknown-freebsd/no-debug/uv
EOF
rsync -r -e "ssh" \
@ -808,7 +833,7 @@ jobs:
--exclude "*" \
. firecracker:
run-in-vm: |
mv target/x86_64-unknown-freebsd/debug/uv uv
mv target/x86_64-unknown-freebsd/no-debug/uv uv
chmod +x uv
./uv --version
@ -2042,22 +2067,22 @@ jobs:
# Test the main path (`build_wheel`) through pip
./uv venv -v --seed
./uv run --no-project python -m pip install -v scripts/packages/built-by-uv --find-links crates/uv-build/dist --no-index --no-deps
./uv run --no-project python -m pip install -v test/packages/built-by-uv --find-links crates/uv-build/dist --no-index --no-deps
./uv run --no-project python -c "from built_by_uv import greet; print(greet())"
# Test both `build_wheel` and `build_sdist` through uv
./uv venv -c -v
./uv build -v --force-pep517 scripts/packages/built-by-uv --find-links crates/uv-build/dist --offline
./uv pip install -v scripts/packages/built-by-uv/dist/*.tar.gz --find-links crates/uv-build/dist --offline --no-deps
./uv build -v --force-pep517 test/packages/built-by-uv --find-links crates/uv-build/dist --offline
./uv pip install -v test/packages/built-by-uv/dist/*.tar.gz --find-links crates/uv-build/dist --offline --no-deps
./uv run --no-project python -c "from built_by_uv import greet; print(greet())"
# Test both `build_wheel` and `build_sdist` through the official `build`
rm -rf scripts/packages/built-by-uv/dist/
rm -rf test/packages/built-by-uv/dist/
./uv venv -c -v
./uv pip install build
# Add the uv binary to PATH for `build` to find
PATH="$(pwd):$PATH" UV_OFFLINE=1 UV_FIND_LINKS=crates/uv-build/dist ./uv run --no-project python -m build -v --installer uv scripts/packages/built-by-uv
./uv pip install -v scripts/packages/built-by-uv/dist/*.tar.gz --find-links crates/uv-build/dist --offline --no-deps
PATH="$(pwd):$PATH" UV_OFFLINE=1 UV_FIND_LINKS=crates/uv-build/dist ./uv run --no-project python -m build -v --installer uv test/packages/built-by-uv
./uv pip install -v test/packages/built-by-uv/dist/*.tar.gz --find-links crates/uv-build/dist --offline --no-deps
./uv run --no-project python -c "from built_by_uv import greet; print(greet())"
cache-test-ubuntu:
@ -2921,8 +2946,8 @@ jobs:
sudo apt-get update
sudo apt-get install -y libsasl2-dev libldap2-dev libkrb5-dev
cargo run --bin uv -- venv --cache-dir .cache
cargo run --bin uv -- pip compile scripts/requirements/jupyter.in --universal --exclude-newer 2024-08-08 --cache-dir .cache
cargo run --bin uv -- pip compile scripts/requirements/airflow.in --universal --exclude-newer 2024-08-08 --cache-dir .cache
cargo run --bin uv -- pip compile test/requirements/jupyter.in --universal --exclude-newer 2024-08-08 --cache-dir .cache
cargo run --bin uv -- pip compile test/requirements/airflow.in --universal --exclude-newer 2024-08-08 --cache-dir .cache
- name: "Build benchmarks"
run: cargo codspeed build --profile profiling -p uv-bench
@ -2961,8 +2986,8 @@ jobs:
sudo apt-get update
sudo apt-get install -y libsasl2-dev libldap2-dev libkrb5-dev
cargo run --bin uv -- venv --cache-dir .cache
cargo run --bin uv -- pip compile scripts/requirements/jupyter.in --universal --exclude-newer 2024-08-08 --cache-dir .cache
cargo run --bin uv -- pip compile scripts/requirements/airflow.in --universal --exclude-newer 2024-08-08 --cache-dir .cache
cargo run --bin uv -- pip compile test/requirements/jupyter.in --universal --exclude-newer 2024-08-08 --cache-dir .cache
cargo run --bin uv -- pip compile test/requirements/airflow.in --universal --exclude-newer 2024-08-08 --cache-dir .cache
- name: "Build benchmarks"
run: cargo codspeed build --profile profiling -p uv-bench

View File

@ -36,6 +36,14 @@ jobs:
with:
python-version: 3.12
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
- name: "Generate reference documentation"
run: |
cargo dev generate-options-reference
cargo dev generate-cli-reference
cargo dev generate-env-vars-reference
- name: "Set docs display name"
run: |
version="${VERSION}"

View File

@ -226,6 +226,7 @@ jobs:
needs:
- plan
- host
- custom-publish-pypi # DIRTY: see #16989
if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
uses: ./.github/workflows/publish-crates.yml
with:

5
.gitignore vendored
View File

@ -37,6 +37,11 @@ profile.json.gz
# MkDocs
/site
# Generated reference docs (use `cargo dev generate-all` to regenerate)
/docs/reference/cli.md
/docs/reference/environment.md
/docs/reference/settings.md
# macOS
**/.DS_Store

View File

@ -4,5 +4,5 @@ PREVIEW-CHANGELOG.md
docs/reference/cli.md
docs/reference/settings.md
docs/reference/environment.md
ecosystem/home-assistant-core/LICENSE.md
test/ecosystem/home-assistant-core/LICENSE.md
docs/guides/integration/gitlab.md

View File

@ -3,6 +3,64 @@
<!-- prettier-ignore-start -->
## 0.9.18
Released on 2025-12-16.
### Enhancements
- Add value hints to command line arguments to improve shell completion accuracy ([#17080](https://github.com/astral-sh/uv/pull/17080))
- Improve error handling in `uv publish` ([#17096](https://github.com/astral-sh/uv/pull/17096))
- Improve rendering of multiline error messages ([#17132](https://github.com/astral-sh/uv/pull/17132))
- Support redirects in `uv publish` ([#17130](https://github.com/astral-sh/uv/pull/17130))
- Include Docker images with the alpine version, e.g., `python3.x-alpine3.23` ([#17100](https://github.com/astral-sh/uv/pull/17100))
### Configuration
- Accept `--torch-backend` in `[tool.uv]` ([#17116](https://github.com/astral-sh/uv/pull/17116))
### Performance
- Speed up `uv cache size` ([#17015](https://github.com/astral-sh/uv/pull/17015))
- Initialize S3 signer once ([#17092](https://github.com/astral-sh/uv/pull/17092))
### Bug fixes
- Avoid panics due to reads on failed requests ([#17098](https://github.com/astral-sh/uv/pull/17098))
- Enforce latest-version in `@latest` requests ([#17114](https://github.com/astral-sh/uv/pull/17114))
- Explicitly set `EntryType` for file entries in tar ([#17043](https://github.com/astral-sh/uv/pull/17043))
- Ignore `pyproject.toml` index username in lockfile comparison ([#16995](https://github.com/astral-sh/uv/pull/16995))
- Relax error when using `uv add` with `UV_GIT_LFS` set ([#17127](https://github.com/astral-sh/uv/pull/17127))
- Support file locks on ExFAT on macOS ([#17115](https://github.com/astral-sh/uv/pull/17115))
- Change schema for `exclude-newer` into optional string ([#17121](https://github.com/astral-sh/uv/pull/17121))
### Documentation
- Drop arm musl caveat from Docker documentation ([#17111](https://github.com/astral-sh/uv/pull/17111))
- Fix version reference in resolver example ([#17085](https://github.com/astral-sh/uv/pull/17085))
- Better documentation for `exclude-newer*` ([#17079](https://github.com/astral-sh/uv/pull/17079))
## 0.9.17
Released on 2025-12-09.
### Enhancements
- Add `torch-tensorrt` and `torchao` to the PyTorch list ([#17053](https://github.com/astral-sh/uv/pull/17053))
- Add hint for misplaced `--verbose` in `uv tool run` ([#17020](https://github.com/astral-sh/uv/pull/17020))
- Add support for relative durations in `exclude-newer` (a.k.a., dependency cooldowns) ([#16814](https://github.com/astral-sh/uv/pull/16814))
- Add support for relocatable nushell activation script ([#17036](https://github.com/astral-sh/uv/pull/17036))
### Bug fixes
- Respect dropped (but explicit) indexes in dependency groups ([#17012](https://github.com/astral-sh/uv/pull/17012))
### Documentation
- Improve `source-exclude` reference docs ([#16832](https://github.com/astral-sh/uv/pull/16832))
- Recommend `UV_NO_DEV` in Docker installs ([#17030](https://github.com/astral-sh/uv/pull/17030))
- Update `UV_VERSION` in docs for GitLab CI/CD ([#17040](https://github.com/astral-sh/uv/pull/17040))
## 0.9.16
Released on 2025-12-06.
@ -445,25 +503,25 @@ There are no breaking changes to [`uv_build`](https://docs.astral.sh/uv/concepts
### Breaking changes
- **Python 3.14 is now the default stable version**
The default Python version has changed from 3.13 to 3.14. This applies to Python version installation when no Python version is requested, e.g., `uv python install`. By default, uv will use the system Python version if present, so this may not cause changes to general use of uv. For example, if Python 3.13 is installed already, then `uv venv` will use that version. If no Python versions are installed on a machine and automatic downloads are enabled, uv will now use 3.14 instead of 3.13, e.g., for `uv venv` or `uvx python`. This change will not affect users who are using a `.python-version` file to pin to a specific Python version.
- **Allow use of free-threaded variants in Python 3.14+ without explicit opt-in** ([#16142](https://github.com/astral-sh/uv/pull/16142))
Previously, free-threaded variants of Python were considered experimental and required explicit opt-in (i.e., with `3.14t`) for usage. Now uv will allow use of free-threaded Python 3.14+ interpreters without explicit selection. The GIL-enabled build of Python will still be preferred, e.g., when performing an installation with `uv python install 3.14`. However, e.g., if a free-threaded interpreter comes before a GIL-enabled build on the `PATH`, it will be used. This change does not apply to free-threaded Python 3.13 interpreters, which will continue to require opt-in.
- **Use Python 3.14 stable Docker images** ([#16150](https://github.com/astral-sh/uv/pull/16150))
Previously, the Python 3.14 images had an `-rc` suffix, e.g., `python:3.14-rc-alpine` or
`python:3.14-rc-trixie`. Now, the `-rc` suffix has been removed to match the stable
[upstream images](https://hub.docker.com/_/python). The `-rc` images tags will no longer be
updated. This change should not break existing workflows.
- **Upgrade Alpine Docker image to Alpine 3.22**
Previously, the `uv:alpine` Docker image was based on Alpine 3.21. Now, this image is based on Alpine 3.22. The previous image can be recovered with `uv:alpine3.21` and will continue to be updated until a future release.
- **Upgrade Debian Docker images to Debian 13 "Trixie"**
Previously, the `uv:debian` and `uv:debian-slim` Docker images were based on Debian 12 "Bookworm". Now, these images are based on Debian 13 "Trixie". The previous images can be recovered with `uv:bookworm` and `uv:bookworm-slim` and will continue to be updated until a future release.
- **Fix incorrect output path when a trailing `/` is used in `uv build`** ([#15133](https://github.com/astral-sh/uv/pull/15133))
When using `uv build` in a workspace, the artifacts are intended to be written to a `dist` directory in the workspace root. A bug caused workspace root determination to fail when the input path included a trailing `/` causing the `dist` directory to be placed in the child directory. This bug has been fixed in this release. For example, `uv build child/` is used, the output path will now be in `<workspace root>/dist/` rather than `<workspace root>/child/dist/`.
### Python

125
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,125 @@
# Contributor Covenant Code of Conduct
- [Our Pledge](#our-pledge)
- [Our Standards](#our-standards)
- [Enforcement Responsibilities](#enforcement-responsibilities)
- [Scope](#scope)
- [Enforcement](#enforcement)
- [Enforcement Guidelines](#enforcement-guidelines)
- [1. Correction](#1-correction)
- [2. Warning](#2-warning)
- [3. Temporary Ban](#3-temporary-ban)
- [4. Permanent Ban](#4-permanent-ban)
- [Attribution](#attribution)
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a
harassment-free experience for everyone, regardless of age, body size, visible or invisible
disability, ethnicity, sex characteristics, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and
healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the
experience
- Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address, without their
explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior
and will take appropriate and fair corrective action in response to any behavior that they deem
inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits,
code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and
will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is
officially representing the community in public spaces. Examples of representing our community
include using an official e-mail address, posting via an official social media account, or acting as
an appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community
leaders responsible for enforcement at <hey@astral.sh>. All complaints will be reviewed and
investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any
incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for
any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or
unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing clarity around the
nature of the violation and an explanation of why the behavior was inappropriate. A public apology
may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of actions.
**Consequence**: A warning with consequences for continued behavior. No interaction with the people
involved, including unsolicited interaction with those enforcing the Code of Conduct, for a
specified period of time. This includes avoiding interactions in community spaces as well as
external channels like social media. Violating these terms may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including sustained inappropriate
behavior.
**Consequence**: A temporary ban from any sort of interaction or public communication with the
community for a specified period of time. No public or private interaction with the people involved,
including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this
period. Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community standards, including
sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement
of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available
[here](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
For answers to common questions about this code of conduct, see the
[FAQ](https://www.contributor-covenant.org/faq). Translations are available
[here](https://www.contributor-covenant.org/translations).
[homepage]: https://www.contributor-covenant.org

View File

@ -102,6 +102,15 @@ cargo run -- venv
cargo run -- pip install requests
```
## Crate structure
Rust does not allow circular dependencies between crates. To visualize the crate hierarchy, install
[cargo-depgraph](https://github.com/jplatte/cargo-depgraph) and graphviz, then run:
```shell
cargo depgraph --dedup-transitive-deps --workspace-only | dot -Tpng > graph.png
```
## Running inside a Docker container
Source distributions can run arbitrary code on build and can make unwanted modifications to your
@ -127,7 +136,7 @@ Please refer to Ruff's
it applies to uv, too.
We provide diverse sets of requirements for testing and benchmarking the resolver in
`scripts/requirements` and for the installer in `scripts/requirements/compiled`.
`test/requirements` and for the installer in `test/requirements/compiled`.
You can use `scripts/benchmark` to benchmark predefined workloads between uv versions and with other
tools, e.g., from the `scripts/benchmark` directory:
@ -138,7 +147,7 @@ uv run resolver \
--poetry \
--benchmark \
resolve-cold \
../scripts/requirements/trio.in
../test/requirements/trio.in
```
### Analyzing concurrency
@ -148,7 +157,7 @@ visualize parallel requests and find any spots where uv is CPU-bound. Example us
`uv-dev` respectively:
```shell
RUST_LOG=uv=info TRACING_DURATIONS_FILE=target/traces/jupyter.ndjson cargo run --features tracing-durations-export --profile profiling -- pip compile scripts/requirements/jupyter.in
RUST_LOG=uv=info TRACING_DURATIONS_FILE=target/traces/jupyter.ndjson cargo run --features tracing-durations-export --profile profiling -- pip compile test/requirements/jupyter.in
```
```shell

170
Cargo.lock generated
View File

@ -45,9 +45,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "ambient-id"
version = "0.0.6"
version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36b48a3b1ad866e5034859be45edd1ebba2f097289c8a34b61623c76f10480f3"
checksum = "b8cad022ed72ad2176498be1c097bb46e598193e92f3491ea0766980edeee168"
dependencies = [
"astral-reqwest-middleware",
"reqwest",
@ -1038,6 +1038,15 @@ dependencies = [
"itertools 0.10.5",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
@ -1255,6 +1264,16 @@ dependencies = [
"windows-sys 0.61.0",
]
[[package]]
name = "diskus"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec07379c016f78e7ddcd953663b9ed17928ff384928d34d824ed7e463bd3d908"
dependencies = [
"crossbeam-channel",
"rayon",
]
[[package]]
name = "dispatch2"
version = "0.3.0"
@ -3443,9 +3462,9 @@ dependencies = [
[[package]]
name = "rayon"
version = "1.10.0"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
@ -3453,9 +3472,9 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.12.1"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
@ -4378,9 +4397,9 @@ dependencies = [
[[package]]
name = "spdx"
version = "0.12.0"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cf87c0efffc158b9dde4d6e0567a43e4383adc4c949e687a2039732db2f23a"
checksum = "35107b1c818f4e9cb9e6c4444ca560ba03b4ee1288dcecc6d7830c2023a7609e"
dependencies = [
"smallvec",
]
@ -5387,7 +5406,7 @@ dependencies = [
[[package]]
name = "uv"
version = "0.9.16"
version = "0.9.18"
dependencies = [
"anstream",
"anyhow",
@ -5402,6 +5421,7 @@ dependencies = [
"clap",
"console 0.16.1",
"ctrlc",
"diskus",
"dotenvy",
"dunce",
"embed-manifest",
@ -5409,7 +5429,6 @@ dependencies = [
"flate2",
"fs-err",
"futures",
"h2",
"http",
"ignore",
"indexmap",
@ -5506,7 +5525,7 @@ dependencies = [
[[package]]
name = "uv-auth"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"arcstr",
@ -5549,7 +5568,7 @@ dependencies = [
[[package]]
name = "uv-bench"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"codspeed-criterion-compat",
@ -5576,7 +5595,7 @@ dependencies = [
[[package]]
name = "uv-bin-install"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"astral-reqwest-middleware",
"astral-reqwest-retry",
@ -5593,7 +5612,6 @@ dependencies = [
"uv-client",
"uv-distribution-filename",
"uv-extract",
"uv-fs",
"uv-pep440",
"uv-platform",
"uv-redacted",
@ -5601,7 +5619,7 @@ dependencies = [
[[package]]
name = "uv-build"
version = "0.9.16"
version = "0.9.18"
dependencies = [
"anstream",
"anyhow",
@ -5613,7 +5631,7 @@ dependencies = [
[[package]]
name = "uv-build-backend"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"astral-version-ranges",
"base64 0.22.1",
@ -5629,7 +5647,7 @@ dependencies = [
"schemars",
"serde",
"sha2",
"spdx 0.12.0",
"spdx 0.13.2",
"tar",
"tempfile",
"thiserror 2.0.17",
@ -5653,7 +5671,7 @@ dependencies = [
[[package]]
name = "uv-build-frontend"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anstream",
"fs-err",
@ -5691,7 +5709,7 @@ dependencies = [
[[package]]
name = "uv-cache"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"clap",
"fs-err",
@ -5701,6 +5719,7 @@ dependencies = [
"same-file",
"serde",
"tempfile",
"thiserror 2.0.17",
"tracing",
"uv-cache-info",
"uv-cache-key",
@ -5716,7 +5735,7 @@ dependencies = [
[[package]]
name = "uv-cache-info"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"fs-err",
@ -5733,7 +5752,7 @@ dependencies = [
[[package]]
name = "uv-cache-key"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"hex",
"memchr",
@ -5745,7 +5764,7 @@ dependencies = [
[[package]]
name = "uv-cli"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anstream",
"anyhow",
@ -5777,7 +5796,7 @@ dependencies = [
[[package]]
name = "uv-client"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"astral-reqwest-middleware",
@ -5840,7 +5859,7 @@ dependencies = [
[[package]]
name = "uv-configuration"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"clap",
@ -5869,14 +5888,14 @@ dependencies = [
[[package]]
name = "uv-console"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"console 0.16.1",
]
[[package]]
name = "uv-dev"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anstream",
"anyhow",
@ -5925,7 +5944,7 @@ dependencies = [
[[package]]
name = "uv-dirs"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"assert_fs",
"etcetera",
@ -5937,7 +5956,7 @@ dependencies = [
[[package]]
name = "uv-dispatch"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"futures",
@ -5969,7 +5988,7 @@ dependencies = [
[[package]]
name = "uv-distribution"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"astral-reqwest-middleware",
@ -6018,7 +6037,7 @@ dependencies = [
[[package]]
name = "uv-distribution-filename"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"insta",
"memchr",
@ -6035,7 +6054,7 @@ dependencies = [
[[package]]
name = "uv-distribution-types"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"arcstr",
"astral-version-ranges",
@ -6075,7 +6094,7 @@ dependencies = [
[[package]]
name = "uv-extract"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"astral-tokio-tar",
"astral_async_zip",
@ -6105,14 +6124,14 @@ dependencies = [
[[package]]
name = "uv-flags"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"bitflags 2.9.4",
]
[[package]]
name = "uv-fs"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"backon",
"dunce",
@ -6136,7 +6155,7 @@ dependencies = [
[[package]]
name = "uv-git"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"astral-reqwest-middleware",
@ -6162,7 +6181,7 @@ dependencies = [
[[package]]
name = "uv-git-types"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"serde",
"thiserror 2.0.17",
@ -6174,7 +6193,7 @@ dependencies = [
[[package]]
name = "uv-globfilter"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anstream",
"fs-err",
@ -6191,7 +6210,7 @@ dependencies = [
[[package]]
name = "uv-install-wheel"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"assert_fs",
@ -6231,7 +6250,7 @@ dependencies = [
[[package]]
name = "uv-installer"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"async-channel",
@ -6272,7 +6291,7 @@ dependencies = [
[[package]]
name = "uv-keyring"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"async-trait",
"byteorder",
@ -6289,7 +6308,7 @@ dependencies = [
[[package]]
name = "uv-logging"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"jiff",
"owo-colors",
@ -6299,7 +6318,7 @@ dependencies = [
[[package]]
name = "uv-macros"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"proc-macro2",
"quote",
@ -6309,7 +6328,7 @@ dependencies = [
[[package]]
name = "uv-metadata"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"astral_async_zip",
"fs-err",
@ -6326,7 +6345,7 @@ dependencies = [
[[package]]
name = "uv-normalize"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"rkyv",
"schemars",
@ -6336,7 +6355,7 @@ dependencies = [
[[package]]
name = "uv-once-map"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"dashmap",
"futures",
@ -6345,14 +6364,14 @@ dependencies = [
[[package]]
name = "uv-options-metadata"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"serde",
]
[[package]]
name = "uv-pep440"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"astral-version-ranges",
"indoc",
@ -6366,7 +6385,7 @@ dependencies = [
[[package]]
name = "uv-pep508"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"arcstr",
"astral-version-ranges",
@ -6395,7 +6414,7 @@ dependencies = [
[[package]]
name = "uv-performance-memory-allocator"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"mimalloc",
"tikv-jemallocator",
@ -6403,7 +6422,7 @@ dependencies = [
[[package]]
name = "uv-platform"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"fs-err",
"goblin",
@ -6420,7 +6439,7 @@ dependencies = [
[[package]]
name = "uv-platform-tags"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"insta",
"memchr",
@ -6433,7 +6452,7 @@ dependencies = [
[[package]]
name = "uv-preview"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"bitflags 2.9.4",
"thiserror 2.0.17",
@ -6442,9 +6461,10 @@ dependencies = [
[[package]]
name = "uv-publish"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"ambient-id",
"anstream",
"astral-reqwest-middleware",
"astral-reqwest-retry",
"astral-tokio-tar",
@ -6478,11 +6498,12 @@ dependencies = [
"uv-redacted",
"uv-static",
"uv-warnings",
"wiremock",
]
[[package]]
name = "uv-pypi-types"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"hashbrown 0.16.1",
@ -6514,7 +6535,7 @@ dependencies = [
[[package]]
name = "uv-python"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"assert_fs",
@ -6576,7 +6597,7 @@ dependencies = [
[[package]]
name = "uv-redacted"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"ref-cast",
"schemars",
@ -6587,7 +6608,7 @@ dependencies = [
[[package]]
name = "uv-requirements"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"configparser",
@ -6622,7 +6643,7 @@ dependencies = [
[[package]]
name = "uv-requirements-txt"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"assert_fs",
@ -6655,7 +6676,7 @@ dependencies = [
[[package]]
name = "uv-resolver"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"arcstr",
"astral-pubgrub",
@ -6720,7 +6741,7 @@ dependencies = [
[[package]]
name = "uv-scripts"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"fs-err",
"indoc",
@ -6744,7 +6765,7 @@ dependencies = [
[[package]]
name = "uv-settings"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"clap",
"fs-err",
@ -6779,7 +6800,7 @@ dependencies = [
[[package]]
name = "uv-shell"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"fs-err",
@ -6796,7 +6817,7 @@ dependencies = [
[[package]]
name = "uv-small-str"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"arcstr",
"rkyv",
@ -6806,7 +6827,7 @@ dependencies = [
[[package]]
name = "uv-state"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"fs-err",
"tempfile",
@ -6815,14 +6836,14 @@ dependencies = [
[[package]]
name = "uv-static"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"uv-macros",
]
[[package]]
name = "uv-tool"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"fs-err",
"pathdiff",
@ -6851,7 +6872,7 @@ dependencies = [
[[package]]
name = "uv-torch"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"clap",
"either",
@ -6871,7 +6892,7 @@ dependencies = [
[[package]]
name = "uv-trampoline-builder"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"assert_cmd",
@ -6888,7 +6909,7 @@ dependencies = [
[[package]]
name = "uv-types"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"dashmap",
@ -6910,11 +6931,11 @@ dependencies = [
[[package]]
name = "uv-version"
version = "0.9.16"
version = "0.9.18"
[[package]]
name = "uv-virtualenv"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"console 0.16.1",
"fs-err",
@ -6936,16 +6957,19 @@ dependencies = [
[[package]]
name = "uv-warnings"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anstream",
"anyhow",
"indoc",
"insta",
"owo-colors",
"rustc-hash",
]
[[package]]
name = "uv-workspace"
version = "0.0.6"
version = "0.0.8"
dependencies = [
"anyhow",
"assert_fs",

View File

@ -16,66 +16,66 @@ authors = ["uv"]
license = "MIT OR Apache-2.0"
[workspace.dependencies]
uv-auth = { version = "0.0.6", path = "crates/uv-auth" }
uv-bin-install = { version = "0.0.6", path = "crates/uv-bin-install" }
uv-build-backend = { version = "0.0.6", path = "crates/uv-build-backend" }
uv-build-frontend = { version = "0.0.6", path = "crates/uv-build-frontend" }
uv-cache = { version = "0.0.6", path = "crates/uv-cache" }
uv-cache-info = { version = "0.0.6", path = "crates/uv-cache-info" }
uv-cache-key = { version = "0.0.6", path = "crates/uv-cache-key" }
uv-cli = { version = "0.0.6", path = "crates/uv-cli" }
uv-client = { version = "0.0.6", path = "crates/uv-client" }
uv-configuration = { version = "0.0.6", path = "crates/uv-configuration" }
uv-console = { version = "0.0.6", path = "crates/uv-console" }
uv-dirs = { version = "0.0.6", path = "crates/uv-dirs" }
uv-dispatch = { version = "0.0.6", path = "crates/uv-dispatch" }
uv-distribution = { version = "0.0.6", path = "crates/uv-distribution" }
uv-distribution-filename = { version = "0.0.6", path = "crates/uv-distribution-filename" }
uv-distribution-types = { version = "0.0.6", path = "crates/uv-distribution-types" }
uv-extract = { version = "0.0.6", path = "crates/uv-extract" }
uv-flags = { version = "0.0.6", path = "crates/uv-flags" }
uv-fs = { version = "0.0.6", path = "crates/uv-fs", features = ["serde", "tokio"] }
uv-git = { version = "0.0.6", path = "crates/uv-git" }
uv-git-types = { version = "0.0.6", path = "crates/uv-git-types" }
uv-globfilter = { version = "0.0.6", path = "crates/uv-globfilter" }
uv-install-wheel = { version = "0.0.6", path = "crates/uv-install-wheel", default-features = false }
uv-installer = { version = "0.0.6", path = "crates/uv-installer" }
uv-keyring = { version = "0.0.6", path = "crates/uv-keyring" }
uv-logging = { version = "0.0.6", path = "crates/uv-logging" }
uv-macros = { version = "0.0.6", path = "crates/uv-macros" }
uv-metadata = { version = "0.0.6", path = "crates/uv-metadata" }
uv-normalize = { version = "0.0.6", path = "crates/uv-normalize" }
uv-once-map = { version = "0.0.6", path = "crates/uv-once-map" }
uv-options-metadata = { version = "0.0.6", path = "crates/uv-options-metadata" }
uv-performance-memory-allocator = { version = "0.0.6", path = "crates/uv-performance-memory-allocator" }
uv-pep440 = { version = "0.0.6", path = "crates/uv-pep440", features = ["tracing", "rkyv", "version-ranges"] }
uv-pep508 = { version = "0.0.6", path = "crates/uv-pep508", features = ["non-pep508-extensions"] }
uv-platform = { version = "0.0.6", path = "crates/uv-platform" }
uv-platform-tags = { version = "0.0.6", path = "crates/uv-platform-tags" }
uv-preview = { version = "0.0.6", path = "crates/uv-preview" }
uv-publish = { version = "0.0.6", path = "crates/uv-publish" }
uv-pypi-types = { version = "0.0.6", path = "crates/uv-pypi-types" }
uv-python = { version = "0.0.6", path = "crates/uv-python" }
uv-redacted = { version = "0.0.6", path = "crates/uv-redacted" }
uv-requirements = { version = "0.0.6", path = "crates/uv-requirements" }
uv-requirements-txt = { version = "0.0.6", path = "crates/uv-requirements-txt" }
uv-resolver = { version = "0.0.6", path = "crates/uv-resolver" }
uv-scripts = { version = "0.0.6", path = "crates/uv-scripts" }
uv-settings = { version = "0.0.6", path = "crates/uv-settings" }
uv-shell = { version = "0.0.6", path = "crates/uv-shell" }
uv-small-str = { version = "0.0.6", path = "crates/uv-small-str" }
uv-state = { version = "0.0.6", path = "crates/uv-state" }
uv-static = { version = "0.0.6", path = "crates/uv-static" }
uv-tool = { version = "0.0.6", path = "crates/uv-tool" }
uv-torch = { version = "0.0.6", path = "crates/uv-torch" }
uv-trampoline-builder = { version = "0.0.6", path = "crates/uv-trampoline-builder" }
uv-types = { version = "0.0.6", path = "crates/uv-types" }
uv-version = { version = "0.9.16", path = "crates/uv-version" }
uv-virtualenv = { version = "0.0.6", path = "crates/uv-virtualenv" }
uv-warnings = { version = "0.0.6", path = "crates/uv-warnings" }
uv-workspace = { version = "0.0.6", path = "crates/uv-workspace" }
uv-auth = { version = "0.0.8", path = "crates/uv-auth" }
uv-bin-install = { version = "0.0.8", path = "crates/uv-bin-install" }
uv-build-backend = { version = "0.0.8", path = "crates/uv-build-backend" }
uv-build-frontend = { version = "0.0.8", path = "crates/uv-build-frontend" }
uv-cache = { version = "0.0.8", path = "crates/uv-cache" }
uv-cache-info = { version = "0.0.8", path = "crates/uv-cache-info" }
uv-cache-key = { version = "0.0.8", path = "crates/uv-cache-key" }
uv-cli = { version = "0.0.8", path = "crates/uv-cli" }
uv-client = { version = "0.0.8", path = "crates/uv-client" }
uv-configuration = { version = "0.0.8", path = "crates/uv-configuration" }
uv-console = { version = "0.0.8", path = "crates/uv-console" }
uv-dirs = { version = "0.0.8", path = "crates/uv-dirs" }
uv-dispatch = { version = "0.0.8", path = "crates/uv-dispatch" }
uv-distribution = { version = "0.0.8", path = "crates/uv-distribution" }
uv-distribution-filename = { version = "0.0.8", path = "crates/uv-distribution-filename" }
uv-distribution-types = { version = "0.0.8", path = "crates/uv-distribution-types" }
uv-extract = { version = "0.0.8", path = "crates/uv-extract" }
uv-flags = { version = "0.0.8", path = "crates/uv-flags" }
uv-fs = { version = "0.0.8", path = "crates/uv-fs", features = ["serde", "tokio"] }
uv-git = { version = "0.0.8", path = "crates/uv-git" }
uv-git-types = { version = "0.0.8", path = "crates/uv-git-types" }
uv-globfilter = { version = "0.0.8", path = "crates/uv-globfilter" }
uv-install-wheel = { version = "0.0.8", path = "crates/uv-install-wheel", default-features = false }
uv-installer = { version = "0.0.8", path = "crates/uv-installer" }
uv-keyring = { version = "0.0.8", path = "crates/uv-keyring" }
uv-logging = { version = "0.0.8", path = "crates/uv-logging" }
uv-macros = { version = "0.0.8", path = "crates/uv-macros" }
uv-metadata = { version = "0.0.8", path = "crates/uv-metadata" }
uv-normalize = { version = "0.0.8", path = "crates/uv-normalize" }
uv-once-map = { version = "0.0.8", path = "crates/uv-once-map" }
uv-options-metadata = { version = "0.0.8", path = "crates/uv-options-metadata" }
uv-performance-memory-allocator = { version = "0.0.8", path = "crates/uv-performance-memory-allocator" }
uv-pep440 = { version = "0.0.8", path = "crates/uv-pep440", features = ["tracing", "rkyv", "version-ranges"] }
uv-pep508 = { version = "0.0.8", path = "crates/uv-pep508", features = ["non-pep508-extensions"] }
uv-platform = { version = "0.0.8", path = "crates/uv-platform" }
uv-platform-tags = { version = "0.0.8", path = "crates/uv-platform-tags" }
uv-preview = { version = "0.0.8", path = "crates/uv-preview" }
uv-publish = { version = "0.0.8", path = "crates/uv-publish" }
uv-pypi-types = { version = "0.0.8", path = "crates/uv-pypi-types" }
uv-python = { version = "0.0.8", path = "crates/uv-python" }
uv-redacted = { version = "0.0.8", path = "crates/uv-redacted" }
uv-requirements = { version = "0.0.8", path = "crates/uv-requirements" }
uv-requirements-txt = { version = "0.0.8", path = "crates/uv-requirements-txt" }
uv-resolver = { version = "0.0.8", path = "crates/uv-resolver" }
uv-scripts = { version = "0.0.8", path = "crates/uv-scripts" }
uv-settings = { version = "0.0.8", path = "crates/uv-settings" }
uv-shell = { version = "0.0.8", path = "crates/uv-shell" }
uv-small-str = { version = "0.0.8", path = "crates/uv-small-str" }
uv-state = { version = "0.0.8", path = "crates/uv-state" }
uv-static = { version = "0.0.8", path = "crates/uv-static" }
uv-tool = { version = "0.0.8", path = "crates/uv-tool" }
uv-torch = { version = "0.0.8", path = "crates/uv-torch" }
uv-trampoline-builder = { version = "0.0.8", path = "crates/uv-trampoline-builder" }
uv-types = { version = "0.0.8", path = "crates/uv-types" }
uv-version = { version = "0.9.18", path = "crates/uv-version" }
uv-virtualenv = { version = "0.0.8", path = "crates/uv-virtualenv" }
uv-warnings = { version = "0.0.8", path = "crates/uv-warnings" }
uv-workspace = { version = "0.0.8", path = "crates/uv-workspace" }
ambient-id = { version = "0.0.6", default-features = false, features = ["astral-reqwest-middleware"] }
ambient-id = { version = "0.0.7", default-features = false, features = ["astral-reqwest-middleware"] }
anstream = { version = "0.6.15" }
anyhow = { version = "1.0.89" }
arcstr = { version = "1.2.0" }
@ -103,6 +103,7 @@ ctrlc = { version = "3.4.5" }
cyclonedx-bom = { version = "0.8.0" }
dashmap = { version = "6.1.0" }
data-encoding = { version = "2.6.0" }
diskus = { version = "0.9.0", default-features = false }
dotenvy = { version = "0.15.7" }
dunce = { version = "1.0.5" }
either = { version = "1.13.0" }
@ -169,7 +170,7 @@ serde-untagged = { version = "0.1.6" }
serde_json = { version = "1.0.128" }
sha2 = { version = "0.10.8" }
smallvec = { version = "1.13.2" }
spdx = { version = "0.12.0" }
spdx = { version = "0.13.0" }
syn = { version = "2.0.77" }
sys-info = { version = "0.9.1" }
tar = { version = "0.4.43" }
@ -224,9 +225,6 @@ test-log = { version = "0.2.16", features = ["trace"], default-features = false
tokio-rustls = { version = "0.26.2", default-features = false }
whoami = { version = "1.6.0" }
[workspace.metadata.cargo-shear]
ignored = ["flate2", "xz2", "h2", "uv-performance-memory-allocator"]
[workspace.lints.rust]
unsafe_code = "warn"
unreachable_pub = "warn"
@ -312,12 +310,21 @@ strip = false
debug = "full"
lto = false
# Profile for fast test execution: Skip debug info generation, and
# apply basic optimization, which speed up build and running tests.
[profile.fast-build]
inherits = "dev"
opt-level = 1
debug = 0
strip = "debuginfo"
# Profile for faster builds: Skip debug info generation, for faster
# builds of smaller binaries.
[profile.no-debug]
inherits = "dev"
debug = 0
strip = "debuginfo"
# Profile to build a minimally sized binary for uv-build
[profile.minimal-size]
inherits = "release"

View File

@ -42,7 +42,7 @@ An extremely fast Python package and project manager, written in Rust.
- 🖥️ Supports macOS, Linux, and Windows.
uv is backed by [Astral](https://astral.sh), the creators of
[Ruff](https://github.com/astral-sh/ruff).
[Ruff](https://github.com/astral-sh/ruff) and [ty](https://github.com/astral-sh/ty).
## Installation
@ -192,14 +192,12 @@ uv installs Python and allows quickly switching between versions.
Install multiple Python versions:
```console
$ uv python install 3.10 3.11 3.12
Searching for Python versions matching: Python 3.10
Searching for Python versions matching: Python 3.11
Searching for Python versions matching: Python 3.12
Installed 3 versions in 3.42s
+ cpython-3.10.14-macos-aarch64-none
+ cpython-3.11.9-macos-aarch64-none
+ cpython-3.12.4-macos-aarch64-none
$ uv python install 3.12 3.13 3.14
Installed 3 versions in 972ms
+ cpython-3.12.12-macos-aarch64-none (python3.12)
+ cpython-3.13.9-macos-aarch64-none (python3.13)
+ cpython-3.14.0-macos-aarch64-none (python3.14)
```
Download Python versions as needed:
@ -270,14 +268,6 @@ Installed 43 packages in 208ms
See the [pip interface documentation](https://docs.astral.sh/uv/pip/index/) to get started.
## Platform support
See uv's [platform support](https://docs.astral.sh/uv/reference/platforms/) document.
## Versioning policy
See uv's [versioning policy](https://docs.astral.sh/uv/reference/versioning/) document.
## Contributing
We are passionate about supporting contributors of all levels of experience and would love to see
@ -294,6 +284,15 @@ It's pronounced as "you - vee" ([`/juː viː/`](https://en.wikipedia.org/wiki/He
Just "uv", please. See the [style guide](./STYLE.md#styling-uv) for details.
#### What platforms does uv support?
See uv's [platform support](https://docs.astral.sh/uv/reference/platforms/) document.
#### Is uv ready for production?
Yes, uv is stable and widely used in production. See uv's
[versioning policy](https://docs.astral.sh/uv/reference/versioning/) document for details.
## Acknowledgements
uv's dependency resolver uses [PubGrub](https://github.com/pubgrub-rs/pubgrub) under the hood. We're

View File

@ -1,8 +1,8 @@
[files]
extend-exclude = [
"**/snapshots/",
"ecosystem/**",
"scripts/**/*.in",
"test/ecosystem/**",
"test/requirements/**/*.in",
"crates/uv-build-frontend/src/pipreqs/mapping",
]
ignore-hidden = false

View File

@ -1,6 +1,6 @@
[package]
name = "uv-auth"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-auth).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-auth).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -129,6 +129,15 @@ enum TokenState {
Initialized(Option<AccessToken>),
}
#[derive(Clone)]
enum S3CredentialState {
/// The S3 credential state has not yet been initialized.
Uninitialized,
/// The S3 credential state has been initialized, with either a signer or `None` if
/// no S3 endpoint is configured.
Initialized(Option<Arc<Authentication>>),
}
/// A middleware that adds basic authentication to requests.
///
/// Uses a cache to propagate credentials from previously seen requests and
@ -150,6 +159,8 @@ pub struct AuthMiddleware {
pyx_token_store: Option<PyxTokenStore>,
/// Tokens to use for persistent credentials.
pyx_token_state: Mutex<TokenState>,
/// Cached S3 credentials to avoid running the credential helper multiple times.
s3_credential_state: Mutex<S3CredentialState>,
preview: Preview,
}
@ -172,6 +183,7 @@ impl AuthMiddleware {
base_client: None,
pyx_token_store: None,
pyx_token_state: Mutex::new(TokenState::Uninitialized),
s3_credential_state: Mutex::new(S3CredentialState::Uninitialized),
preview: Preview::default(),
}
}
@ -678,13 +690,26 @@ impl AuthMiddleware {
return Some(credentials);
}
if let Some(credentials) = S3EndpointProvider::credentials_for(url, self.preview)
.map(Authentication::from)
.map(Arc::new)
{
debug!("Found S3 credentials for {url}");
self.cache().fetches.done(key, Some(credentials.clone()));
return Some(credentials);
if S3EndpointProvider::is_s3_endpoint(url, self.preview) {
let mut s3_state = self.s3_credential_state.lock().await;
// If the S3 credential state is uninitialized, initialize it.
let credentials = match &*s3_state {
S3CredentialState::Uninitialized => {
trace!("Initializing S3 credentials for {url}");
let signer = S3EndpointProvider::create_signer();
let credentials = Arc::new(Authentication::from(signer));
*s3_state = S3CredentialState::Initialized(Some(credentials.clone()));
Some(credentials)
}
S3CredentialState::Initialized(credentials) => credentials.clone(),
};
if let Some(credentials) = credentials {
debug!("Found S3 credentials for {url}");
self.cache().fetches.done(key, Some(credentials.clone()));
return Some(credentials);
}
}
// If this is a known URL, authenticate it via the token store.

View File

@ -66,8 +66,8 @@ static S3_ENDPOINT_REALM: LazyLock<Option<Realm>> = LazyLock::new(|| {
pub(crate) struct S3EndpointProvider;
impl S3EndpointProvider {
/// Returns the credentials for the S3 endpoint, if available.
pub(crate) fn credentials_for(url: &Url, preview: Preview) -> Option<DefaultSigner> {
/// Returns `true` if the URL matches the configured S3 endpoint.
pub(crate) fn is_s3_endpoint(url: &Url, preview: Preview) -> bool {
if let Some(s3_endpoint_realm) = S3_ENDPOINT_REALM.as_ref().map(RealmRef::from) {
if !preview.is_enabled(PreviewFeatures::S3_ENDPOINT) {
warn_user_once!(
@ -79,19 +79,26 @@ impl S3EndpointProvider {
// Treat any URL on the same domain or subdomain as available for S3 signing.
let realm = RealmRef::from(url);
if realm == s3_endpoint_realm || realm.is_subdomain_of(s3_endpoint_realm) {
// TODO(charlie): Can `reqsign` infer the region for us? Profiles, for example,
// often have a region set already.
let region = std::env::var(EnvVars::AWS_REGION)
.map(Cow::Owned)
.unwrap_or_else(|_| {
std::env::var(EnvVars::AWS_DEFAULT_REGION)
.map(Cow::Owned)
.unwrap_or_else(|_| Cow::Borrowed("us-east-1"))
});
let signer = reqsign::aws::default_signer("s3", &region);
return Some(signer);
return true;
}
}
None
false
}
/// Creates a new S3 signer with the configured region.
///
/// This is potentially expensive as it may invoke credential helpers, so the result
/// should be cached.
pub(crate) fn create_signer() -> DefaultSigner {
// TODO(charlie): Can `reqsign` infer the region for us? Profiles, for example,
// often have a region set already.
let region = std::env::var(EnvVars::AWS_REGION)
.map(Cow::Owned)
.unwrap_or_else(|_| {
std::env::var(EnvVars::AWS_DEFAULT_REGION)
.map(Cow::Owned)
.unwrap_or_else(|_| Cow::Borrowed("us-east-1"))
});
reqsign::aws::default_signer("s3", &region)
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "uv-bench"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
publish = false
authors = { workspace = true }
@ -22,14 +22,14 @@ name = "uv"
path = "benches/uv.rs"
harness = false
[dependencies]
[dev-dependencies]
uv-cache = { workspace = true }
uv-client = { workspace = true }
uv-configuration = { workspace = true }
uv-dispatch = { workspace = true }
uv-distribution = { workspace = true }
uv-distribution-types = { workspace = true }
uv-extract = { workspace = true, optional = true }
uv-extract = { workspace = true }
uv-install-wheel = { workspace = true }
uv-pep440 = { workspace = true }
uv-pep508 = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-bench).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-bench).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-bin-install"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }
@ -20,7 +20,6 @@ uv-cache = { workspace = true }
uv-client = { workspace = true }
uv-distribution-filename = { workspace = true }
uv-extract = { workspace = true }
uv-fs = { workspace = true }
uv-pep440 = { workspace = true }
uv-platform = { workspace = true }
uv-redacted = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-bin-install).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-bin-install).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -19,10 +19,9 @@ use tracing::debug;
use url::Url;
use uv_distribution_filename::SourceDistExtension;
use uv_cache::{Cache, CacheBucket, CacheEntry};
use uv_cache::{Cache, CacheBucket, CacheEntry, Error as CacheError};
use uv_client::{BaseClient, is_transient_network_error};
use uv_extract::{Error as ExtractError, stream};
use uv_fs::LockedFileError;
use uv_pep440::Version;
use uv_platform::Platform;
use uv_redacted::DisplaySafeUrl;
@ -137,7 +136,7 @@ pub enum Error {
Io(#[from] std::io::Error),
#[error(transparent)]
LockedFile(#[from] LockedFileError),
Cache(#[from] CacheError),
#[error("Failed to detect platform")]
Platform(#[from] uv_platform::Error),

View File

@ -1,6 +1,6 @@
[package]
name = "uv-build-backend"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-build-backend).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-build-backend).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -599,7 +599,7 @@ mod tests {
/// platform-independent deterministic builds.
#[test]
fn built_by_uv_building() {
let built_by_uv = Path::new("../../scripts/packages/built-by-uv");
let built_by_uv = Path::new("../../test/packages/built-by-uv");
let src = TempDir::new().unwrap();
for dir in [
"src",
@ -662,7 +662,7 @@ mod tests {
// Check that the source dist is reproducible across platforms.
assert_snapshot!(
format!("{:x}", sha2::Sha256::digest(fs_err::read(&source_dist_path).unwrap())),
@"871d1f859140721b67cbeaca074e7a2740c88c38028d0509eba87d1285f1da9e"
@"bb74bff575b135bb39e5c9bce56349441fb0923bb8857e32a5eaf34ec1843967"
);
// Check both the files we report and the actual files
assert_snapshot!(format_file_list(build.source_dist_list_files, src.path()), @r"

View File

@ -70,6 +70,9 @@ pub struct BuildBackendSettings {
pub default_excludes: bool,
/// Glob expressions which files and directories to exclude from the source distribution.
///
/// These exclusions are also applied to wheels to ensure that a wheel built from a source tree
/// is consistent with a wheel built from a source distribution.
#[option(
default = r#"[]"#,
value_type = "list[str]",

View File

@ -299,6 +299,10 @@ impl TarGzWriter {
impl DirectoryWriter for TarGzWriter {
fn write_bytes(&mut self, path: &str, bytes: &[u8]) -> Result<(), Error> {
let mut header = Header::new_gnu();
// Work around bug in Python's std tar module
// https://github.com/python/cpython/issues/141707
// https://github.com/astral-sh/uv/pull/17043#issuecomment-3636841022
header.set_entry_type(EntryType::Regular);
header.set_size(bytes.len() as u64);
// Reasonable default to avoid 0o000 permissions, the user's umask will be applied on
// unpacking.
@ -312,6 +316,10 @@ impl DirectoryWriter for TarGzWriter {
fn write_file(&mut self, path: &str, file: &Path) -> Result<(), Error> {
let metadata = fs_err::metadata(file)?;
let mut header = Header::new_gnu();
// Work around bug in Python's std tar module
// https://github.com/python/cpython/issues/141707
// https://github.com/astral-sh/uv/pull/17043#issuecomment-3636841022
header.set_entry_type(EntryType::Regular);
// Preserve the executable bit, especially for scripts
#[cfg(unix)]
let executable_bit = {

View File

@ -840,7 +840,7 @@ mod test {
#[test]
fn test_prepare_metadata() {
let metadata_dir = TempDir::new().unwrap();
let built_by_uv = Path::new("../../scripts/packages/built-by-uv");
let built_by_uv = Path::new("../../test/packages/built-by-uv");
metadata(built_by_uv, metadata_dir.path(), "1.0.0+test").unwrap();
let mut files: Vec<_> = WalkDir::new(metadata_dir.path())

View File

@ -1,6 +1,6 @@
[package]
name = "uv-build-frontend"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-build-frontend).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-build-frontend).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-build"
version = "0.9.16"
version = "0.9.18"
description = "A Python build backend"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -1,6 +1,6 @@
[project]
name = "uv-build"
version = "0.9.16"
version = "0.9.18"
description = "The uv build backend"
authors = [{ name = "Astral Software Inc.", email = "hey@astral.sh" }]
requires-python = ">=3.8"

View File

@ -1,6 +1,6 @@
[package]
name = "uv-cache-info"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-cache-info).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-cache-info).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-cache-key"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-cache-key).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-cache-key).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-cache"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }
@ -34,5 +34,6 @@ rustc-hash = { workspace = true }
same-file = { workspace = true }
serde = { workspace = true, features = ["derive"] }
tempfile = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
walkdir = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-cache).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-cache).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
use uv_static::EnvVars;
use crate::Cache;
use clap::Parser;
use clap::{Parser, ValueHint};
use tracing::{debug, warn};
#[derive(Parser, Debug, Clone)]
@ -27,7 +27,7 @@ pub struct CacheArgs {
/// `%LOCALAPPDATA%\uv\cache` on Windows.
///
/// To view the location of the cache directory, run `uv cache dir`.
#[arg(global = true, long, env = EnvVars::UV_CACHE_DIR)]
#[arg(global = true, long, env = EnvVars::UV_CACHE_DIR, value_hint = ValueHint::DirPath)]
pub cache_dir: Option<PathBuf>,
}

View File

@ -35,6 +35,17 @@ mod wheel;
/// Must be kept in-sync with the version in [`CacheBucket::to_str`].
pub const ARCHIVE_VERSION: u8 = 0;
/// Error locking a cache entry or shard
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
Io(#[from] io::Error),
#[error("Could not make the path absolute")]
Absolute(#[source] io::Error),
#[error("Could not acquire lock")]
Acquire(#[from] LockedFileError),
}
/// A [`CacheEntry`] which may or may not exist yet.
#[derive(Debug, Clone)]
pub struct CacheEntry(PathBuf);
@ -80,14 +91,14 @@ impl CacheEntry {
}
/// Acquire the [`CacheEntry`] as an exclusive lock.
pub async fn lock(&self) -> Result<LockedFile, LockedFileError> {
pub async fn lock(&self) -> Result<LockedFile, Error> {
fs_err::create_dir_all(self.dir())?;
LockedFile::acquire(
Ok(LockedFile::acquire(
self.path(),
LockedFileMode::Exclusive,
self.path().display(),
)
.await
.await?)
}
}
@ -114,14 +125,14 @@ impl CacheShard {
}
/// Acquire the cache entry as an exclusive lock.
pub async fn lock(&self) -> Result<LockedFile, LockedFileError> {
pub async fn lock(&self) -> Result<LockedFile, Error> {
fs_err::create_dir_all(self.as_ref())?;
LockedFile::acquire(
Ok(LockedFile::acquire(
self.join(".lock"),
LockedFileMode::Exclusive,
self.display(),
)
.await
.await?)
}
/// Return the [`CacheShard`] as a [`PathBuf`].
@ -391,7 +402,7 @@ impl Cache {
}
/// Populate the cache scaffold.
fn create_base_files(root: &PathBuf) -> Result<(), io::Error> {
fn create_base_files(root: &PathBuf) -> io::Result<()> {
// Create the cache directory, if it doesn't exist.
fs_err::create_dir_all(root)?;
@ -441,7 +452,7 @@ impl Cache {
}
/// Initialize the [`Cache`].
pub async fn init(self) -> Result<Self, LockedFileError> {
pub async fn init(self) -> Result<Self, Error> {
let root = &self.root;
Self::create_base_files(root)?;
@ -466,18 +477,18 @@ impl Cache {
);
None
}
Err(err) => return Err(err),
Err(err) => return Err(err.into()),
};
Ok(Self {
root: std::path::absolute(root)?,
root: std::path::absolute(root).map_err(Error::Absolute)?,
lock_file,
..self
})
}
/// Initialize the [`Cache`], assuming that there are no other uv processes running.
pub fn init_no_wait(self) -> Result<Option<Self>, io::Error> {
pub fn init_no_wait(self) -> Result<Option<Self>, Error> {
let root = &self.root;
Self::create_base_files(root)?;
@ -491,7 +502,7 @@ impl Cache {
return Ok(None);
};
Ok(Some(Self {
root: std::path::absolute(root)?,
root: std::path::absolute(root).map_err(Error::Absolute)?,
lock_file: Some(Arc::new(lock_file)),
..self
}))
@ -531,7 +542,7 @@ impl Cache {
/// Remove a package from the cache.
///
/// Returns the number of entries removed from the cache.
pub fn remove(&self, name: &PackageName) -> Result<Removal, io::Error> {
pub fn remove(&self, name: &PackageName) -> io::Result<Removal> {
// Collect the set of referenced archives.
let references = self.find_archive_references()?;

View File

@ -1,6 +1,6 @@
[package]
name = "uv-cli"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-cli).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-cli).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

File diff suppressed because it is too large Load Diff

View File

@ -366,6 +366,7 @@ pub fn resolver_options(
exclude_newer_package.unwrap_or_default(),
),
link_mode,
torch_backend: None,
no_build: flag(no_build, build, "build"),
no_build_package: Some(no_build_package),
no_binary: flag(no_binary, binary, "binary"),
@ -495,5 +496,6 @@ pub fn resolver_installer_options(
Some(no_binary_package)
},
no_sources: if no_sources { Some(true) } else { None },
torch_backend: None,
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "uv-client"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-client).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-client).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -50,7 +50,7 @@ pub const DEFAULT_RETRIES: u32 = 3;
/// Maximum number of redirects to follow before giving up.
///
/// This is the default used by [`reqwest`].
const DEFAULT_MAX_REDIRECTS: u32 = 10;
pub const DEFAULT_MAX_REDIRECTS: u32 = 10;
/// Selectively skip parts or the entire auth middleware.
#[derive(Debug, Clone, Copy, Default)]
@ -104,6 +104,8 @@ pub enum RedirectPolicy {
BypassMiddleware,
/// Handle redirects manually, re-triggering our custom middleware for each request.
RetriggerMiddleware,
/// No redirect for non-cloneable (e.g., streaming) requests with custom redirect logic.
NoRedirect,
}
impl RedirectPolicy {
@ -111,6 +113,7 @@ impl RedirectPolicy {
match self {
Self::BypassMiddleware => reqwest::redirect::Policy::default(),
Self::RetriggerMiddleware => reqwest::redirect::Policy::none(),
Self::NoRedirect => reqwest::redirect::Policy::none(),
}
}
}
@ -729,6 +732,7 @@ impl RedirectClientWithMiddleware {
match self.redirect_policy {
RedirectPolicy::BypassMiddleware => self.client.execute(req).await,
RedirectPolicy::RetriggerMiddleware => self.execute_with_redirect_handling(req).await,
RedirectPolicy::NoRedirect => self.client.execute(req).await,
}
}

View File

@ -5,8 +5,8 @@ use std::fmt::{Display, Formatter};
use std::ops::Deref;
use std::path::PathBuf;
use uv_cache::Error as CacheError;
use uv_distribution_filename::{WheelFilename, WheelFilenameError};
use uv_fs::LockedFileError;
use uv_normalize::PackageName;
use uv_redacted::DisplaySafeUrl;
@ -339,7 +339,7 @@ pub enum ErrorKind {
CacheWrite(#[source] std::io::Error),
#[error("Failed to acquire lock on the client cache")]
CacheLock(#[source] LockedFileError),
CacheLock(#[source] CacheError),
#[error(transparent)]
Io(std::io::Error),

View File

@ -1,7 +1,7 @@
pub use base_client::{
AuthIntegration, BaseClient, BaseClientBuilder, DEFAULT_RETRIES, ExtraMiddleware,
RedirectClientWithMiddleware, RequestBuilder, RetryParsingError, UvRetryableStrategy,
is_transient_network_error,
AuthIntegration, BaseClient, BaseClientBuilder, DEFAULT_MAX_REDIRECTS, DEFAULT_RETRIES,
ExtraMiddleware, RedirectClientWithMiddleware, RedirectPolicy, RequestBuilder,
RetryParsingError, UvRetryableStrategy, is_transient_network_error,
};
pub use cached_client::{CacheControl, CachedClient, CachedClientError, DataWithCachePolicy};
pub use error::{Error, ErrorKind, WrappedReqwestError};

View File

@ -1,6 +1,6 @@
[package]
name = "uv-configuration"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-configuration).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-configuration).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -94,3 +94,32 @@ wheels/
# Virtual environments
.venv
";
/// Setting for Git LFS (Large File Storage) support.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum GitLfsSetting {
/// Git LFS is disabled (default).
#[default]
Disabled,
/// Git LFS is enabled. Tracks whether it came from an environment variable.
Enabled { from_env: bool },
}
impl GitLfsSetting {
pub fn new(from_arg: Option<bool>, from_env: Option<bool>) -> Self {
match (from_arg, from_env) {
(Some(true), _) => Self::Enabled { from_env: false },
(_, Some(true)) => Self::Enabled { from_env: true },
_ => Self::Disabled,
}
}
}
impl From<GitLfsSetting> for Option<bool> {
fn from(setting: GitLfsSetting) -> Self {
match setting {
GitLfsSetting::Enabled { .. } => Some(true),
GitLfsSetting::Disabled => None,
}
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "uv-console"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-console).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-console).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-dev"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
publish = false
@ -79,4 +79,4 @@ performance-memory-allocator = ["dep:uv-performance-memory-allocator"]
render = ["poloto", "resvg", "tagu"]
[package.metadata.cargo-shear]
ignored = ["flate2", "uv-extract", "uv-performance-memory-allocator"]
ignored = ["uv-performance-memory-allocator"]

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-dev).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-dev).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -342,31 +342,3 @@ fn emit_possible_options(opt: &clap::Arg, output: &mut String) {
output.push_str(&markdown::to_html(&value));
}
}
#[cfg(test)]
mod tests {
use std::env;
use anyhow::Result;
use uv_static::EnvVars;
use crate::generate_all::Mode;
use super::{Args, main};
#[test]
fn test_generate_cli_reference() -> Result<()> {
// Skip this test in CI to avoid redundancy with the dedicated CI job
if env::var_os(EnvVars::CI).is_some() {
return Ok(());
}
let mode = if env::var(EnvVars::UV_UPDATE_SCHEMA).as_deref() == Ok("1") {
Mode::Write
} else {
Mode::Check
};
main(&Args { mode })
}
}

View File

@ -106,31 +106,3 @@ fn render(var: &str, doc: &str, added_in: Option<&str>) -> String {
format!("### `{var}`\n\n{doc}\n\n")
}
}
#[cfg(test)]
mod tests {
use std::env;
use anyhow::Result;
use uv_static::EnvVars;
use crate::generate_all::Mode;
use super::{Args, main};
#[test]
fn test_generate_env_vars_reference() -> Result<()> {
// Skip this test in CI to avoid redundancy with the dedicated CI job
if env::var_os(EnvVars::CI).is_some() {
return Ok(());
}
let mode = if env::var(EnvVars::UV_UPDATE_SCHEMA).as_deref() == Ok("1") {
Mode::Write
} else {
Mode::Check
};
main(&Args { mode })
}
}

View File

@ -387,31 +387,3 @@ impl Visit for CollectOptionsVisitor {
self.fields.push((name.to_owned(), field));
}
}
#[cfg(test)]
mod tests {
use std::env;
use anyhow::Result;
use uv_static::EnvVars;
use crate::generate_all::Mode;
use super::{Args, main};
#[test]
fn test_generate_options_reference() -> Result<()> {
// Skip this test in CI to avoid redundancy with the dedicated CI job
if env::var_os(EnvVars::CI).is_some() {
return Ok(());
}
let mode = if env::var(EnvVars::UV_UPDATE_SCHEMA).as_deref() == Ok("1") {
Mode::Write
} else {
Mode::Check
};
main(&Args { mode })
}
}

View File

@ -11,7 +11,7 @@ use crate::ROOT_DIR;
use crate::generate_all::Mode;
/// Contains current supported targets
const TARGETS_YML_URL: &str = "https://raw.githubusercontent.com/astral-sh/python-build-standalone/refs/tags/20251205/cpython-unix/targets.yml";
const TARGETS_YML_URL: &str = "https://raw.githubusercontent.com/astral-sh/python-build-standalone/refs/tags/20251209/cpython-unix/targets.yml";
#[derive(clap::Args)]
pub(crate) struct Args {
@ -130,7 +130,7 @@ async fn generate() -> Result<String> {
output.push_str("//! DO NOT EDIT\n");
output.push_str("//!\n");
output.push_str("//! Generated with `cargo run dev generate-sysconfig-metadata`\n");
output.push_str("//! Targets from <https://github.com/astral-sh/python-build-standalone/blob/20251205/cpython-unix/targets.yml>\n");
output.push_str("//! Targets from <https://github.com/astral-sh/python-build-standalone/blob/20251209/cpython-unix/targets.yml>\n");
output.push_str("//!\n");
// Disable clippy/fmt

View File

@ -1,6 +1,6 @@
[package]
name = "uv-dirs"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-dirs).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-dirs).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-dispatch"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-dispatch).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-dispatch).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-distribution-filename"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-distribution-filename).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-distribution-filename).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-distribution-types"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-distribution-types).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-distribution-types).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -159,9 +159,9 @@ pub enum InstalledVersion<'a> {
Url(&'a DisplaySafeUrl, &'a Version),
}
impl InstalledVersion<'_> {
impl<'a> InstalledVersion<'a> {
/// If it is a URL, return its value.
pub fn url(&self) -> Option<&DisplaySafeUrl> {
pub fn url(&self) -> Option<&'a DisplaySafeUrl> {
match self {
Self::Version(_) => None,
Self::Url(url, _) => Some(url),
@ -169,7 +169,7 @@ impl InstalledVersion<'_> {
}
/// If it is a version, return its value.
pub fn version(&self) -> &Version {
pub fn version(&self) -> &'a Version {
match self {
Self::Version(version) => version,
Self::Url(_, version) => version,

View File

@ -1,6 +1,6 @@
[package]
name = "uv-distribution"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-distribution).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-distribution).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -5,10 +5,11 @@ use tokio::task::JoinError;
use zip::result::ZipError;
use crate::metadata::MetadataError;
use uv_cache::Error as CacheError;
use uv_client::WrappedReqwestError;
use uv_distribution_filename::{WheelFilename, WheelFilenameError};
use uv_distribution_types::{InstalledDist, InstalledDistError, IsBuildBackendError};
use uv_fs::{LockedFileError, Simplified};
use uv_fs::Simplified;
use uv_git::GitError;
use uv_normalize::PackageName;
use uv_pep440::{Version, VersionSpecifiers};
@ -42,7 +43,7 @@ pub enum Error {
#[error("Failed to write to the distribution cache")]
CacheWrite(#[source] std::io::Error),
#[error("Failed to acquire lock on the distribution cache")]
CacheLock(#[source] LockedFileError),
CacheLock(#[source] CacheError),
#[error("Failed to deserialize cache entry")]
CacheDecode(#[from] rmp_serde::decode::Error),
#[error("Failed to serialize cache entry")]

View File

@ -1,6 +1,6 @@
[package]
name = "uv-extract"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-extract).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-extract).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-flags"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-flags).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-flags).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-fs"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-fs).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-fs).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,3 +1,4 @@
use std::convert::Into;
use std::fmt::Display;
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
@ -59,10 +60,18 @@ pub enum LockedFileError {
source: io::Error,
},
#[error(transparent)]
Io(#[from] io::Error),
#[error(transparent)]
#[cfg(feature = "tokio")]
JoinError(#[from] tokio::task::JoinError),
#[error("Could not create temporary file")]
CreateTemporary(#[source] io::Error),
#[error("Could not persist temporary file `{}`", path.user_display())]
PersistTemporary {
path: PathBuf,
#[source]
source: io::Error,
},
#[error(transparent)]
Io(#[from] io::Error),
}
impl LockedFileError {
@ -72,6 +81,8 @@ impl LockedFileError {
#[cfg(feature = "tokio")]
Self::JoinError(_) => None,
Self::Lock { source, .. } => Some(source),
Self::CreateTemporary(err) => Some(err),
Self::PersistTemporary { source, .. } => Some(source),
Self::Io(err) => Some(err),
}
}
@ -201,7 +212,7 @@ impl LockedFile {
mode: LockedFileMode,
resource: impl Display,
) -> Result<Self, LockedFileError> {
let file = Self::create(path)?;
let file = Self::create(&path)?;
let resource = resource.to_string();
Self::lock_file(file, mode, &resource).await
}
@ -222,10 +233,25 @@ impl LockedFile {
}
#[cfg(unix)]
fn create(path: impl AsRef<Path>) -> Result<fs_err::File, std::io::Error> {
use std::os::unix::fs::PermissionsExt;
fn create(path: impl AsRef<Path>) -> Result<fs_err::File, LockedFileError> {
use rustix::io::Errno;
#[allow(clippy::disallowed_types)]
use std::{fs::File, os::unix::fs::PermissionsExt};
use tempfile::NamedTempFile;
/// The permissions the lockfile should end up with
const DESIRED_MODE: u32 = 0o666;
#[allow(clippy::disallowed_types)]
fn try_set_permissions(file: &File, path: &Path) {
if let Err(err) = file.set_permissions(std::fs::Permissions::from_mode(DESIRED_MODE)) {
warn!(
"Failed to set permissions on temporary file `{path}`: {err}",
path = path.user_display()
);
}
}
// If path already exists, return it.
if let Ok(file) = fs_err::OpenOptions::new()
.read(true)
@ -238,16 +264,12 @@ impl LockedFile {
// Otherwise, create a temporary file with 666 permissions. We must set
// permissions _after_ creating the file, to override the `umask`.
let file = if let Some(parent) = path.as_ref().parent() {
NamedTempFile::new_in(parent)?
NamedTempFile::new_in(parent)
} else {
NamedTempFile::new()?
};
if let Err(err) = file
.as_file()
.set_permissions(std::fs::Permissions::from_mode(0o666))
{
warn!("Failed to set permissions on temporary file: {err}");
NamedTempFile::new()
}
.map_err(LockedFileError::CreateTemporary)?;
try_set_permissions(file.as_file(), file.path());
// Try to move the file to path, but if path exists now, just open path
match file.persist_noclobber(path.as_ref()) {
@ -258,20 +280,60 @@ impl LockedFile {
.read(true)
.write(true)
.open(path.as_ref())
.map_err(Into::into)
} else if matches!(
Errno::from_io_error(&err.error),
Some(Errno::NOTSUP | Errno::INVAL)
) {
// Fallback in case `persist_noclobber`, which uses `renameat2` or
// `renameatx_np` under the hood, is not supported by the FS. Linux reports this
// with `EINVAL` and MacOS with `ENOTSUP`. For these reasons and many others,
// there isn't an ErrorKind we can use here, and in fact on MacOS `ENOTSUP` gets
// mapped to `ErrorKind::Other`
// There is a race here where another process has just created the file, and we
// try to open it and get permission errors because the other process hasn't set
// the permission bits yet. This will lead to a transient failure, but unlike
// alternative approaches it won't ever lead to a situation where two processes
// are locking two different files. Also, since `persist_noclobber` is more
// likely to not be supported on special filesystems which don't have permission
// bits, it's less likely to ever matter.
let file = fs_err::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(path.as_ref())?;
// We don't want to `try_set_permissions` in cases where another user's process
// has already created the lockfile and changed its permissions because we might
// not have permission to change the permissions which would produce a confusing
// warning.
if file
.metadata()
.is_ok_and(|metadata| metadata.permissions().mode() != DESIRED_MODE)
{
try_set_permissions(file.file(), path.as_ref());
}
Ok(file)
} else {
Err(err.error)
let temp_path = err.file.into_temp_path();
Err(LockedFileError::PersistTemporary {
path: <tempfile::TempPath as AsRef<Path>>::as_ref(&temp_path).to_path_buf(),
source: err.error,
})
}
}
}
}
#[cfg(not(unix))]
fn create(path: impl AsRef<Path>) -> std::io::Result<fs_err::File> {
fn create(path: impl AsRef<Path>) -> Result<fs_err::File, LockedFileError> {
fs_err::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(path.as_ref())
.map_err(Into::into)
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "uv-git-types"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-git-types).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-git-types).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-git"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-git).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-git).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-globfilter"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
readme = "README.md"
edition = { workspace = true }

View File

@ -1,6 +1,6 @@
[package]
name = "uv-install-wheel"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
keywords = ["wheel", "python"]

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-install-wheel).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-install-wheel).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-installer"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-installer).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-installer).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-keyring"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -1,6 +1,6 @@
[package]
name = "uv-logging"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-logging).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-logging).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-macros"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-macros).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-macros).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-metadata"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-metadata).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-metadata).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

View File

@ -1,6 +1,6 @@
[package]
name = "uv-normalize"
version = "0.0.6"
version = "0.0.8"
description = "This is an internal component crate of uv"
edition = { workspace = true }
rust-version = { workspace = true }

View File

@ -5,8 +5,8 @@
This crate is an internal component of [uv](https://crates.io/crates/uv). The Rust API exposed here
is unstable and will have frequent breaking changes.
This version (0.0.6) is a component of [uv 0.9.16](https://crates.io/crates/uv/0.9.16). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.16/crates/uv-normalize).
This version (0.0.8) is a component of [uv 0.9.18](https://crates.io/crates/uv/0.9.18). The source
can be found [here](https://github.com/astral-sh/uv/blob/0.9.18/crates/uv-normalize).
See uv's
[crate versioning policy](https://docs.astral.sh/uv/reference/policies/versioning/#crate-versioning)

Some files were not shown because too many files have changed in this diff Show More