Files
astral-uv/CONTRIBUTING.md
Zanie Blue b6854d77bf Upgrade reqwest to 0.13 (#18550)
The following user-facing changes are included here:

- `aws-lc` is used instead of `ring` for a cryptography backend
- Expands our certificate signature algorithm support to include
ECDSA_P256_SHA512, ECDSA_P384_SHA512, ECDSA_P521_SHA256,
ECDSA_P521_SHA384, and ECDSA_P521_SHA512
- `--native-tls` is deprecated in favor of a new `--system-certs` flag,
avoiding confusion with the TLS implementation used (we use `rustls` not
`native-tls`, see prior confusion at
https://github.com/astral-sh/uv/issues/11595)
- NASM is a new build requirement on Windows, it is required by `aws-lc`
on x86-64 and i386
- `rustls-platform-verifier` is used instead of `rustls-native-certs`
for system certificate verification
- On macOS, certificate validation is now delegated to
`Security.framework` (`SecTrust`). Performance when using
`--system-certs` is improved by avoiding exporting and parsing all the
certificates from the keychain at startup.
- On Windows, certificate validation is now delegated to
`CertGetCertificateChain` and `CertVerifyCertificateChainPolicy`
    - On Linux, certificate validation should be approximately unchanged
- Some previously failing chains may succeed, and some previously
accepted chains may fail; generally, this should result in behavior
closer matching browsers and other native applications
- macOS and Windows may now perform live OCSP fetches for early
revocation, which could add latency to some requests
- Empty `SSL_CERT_FILE` values are ignored (for consistency with
`SSL_CERT_DIR`)

The following internal changes are included here:

- Certificate loading has been refactored to use a newtype with helper
methods
- The certificate tests have been rewritten
- We use `webpki-root-certs` instead of `webpki-roots`, see
https://github.com/astral-sh/uv/pull/17543#discussion_r2820187691
- We request `identity` encoding for range requests, see
https://github.com/astral-sh/async_http_range_reader/pull/3#discussion_r2700194798
- Various dependencies (including forks) updates to versions which use
reqwest 0.13+

This is a replacement of #17543 with an updated description. See that
pull request for prior discussion. I've made the following changes from
the initial approach there:

- Previously, the `native-tls` TLS implementation was added which
included an OpenSSL build. We don't currently use the `native-tls`
implementation, but the `--native-tls` flag there was erroneously
updated to enable it.
- Previously, there was a `--tls-backend` flag to toggle between
`native-tls` and `rustls`. Since we currently always use `rustls`, this
is deferred to future work (if we need it at all).
- Previously, there were unintentional breaking changes to
`SSL_CERT_FILE` and `SSL_CERT_DIR` handling, including merging with the
base certificates instead of replacing them, dropping support for
OpenSSL hash-named certificate files, skipping deduplication of
certificates. Here, we retain use of `rustls-native-certs` for loading
certificates from the system as it handles these edge cases.


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

---------

Co-authored-by: salmonsd <22984014+salmonsd@users.noreply.github.com>
2026-03-23 13:22:19 -05:00

11 KiB

Contributing

Finding ways to help

We label issues that would be good for a first time contributor as good first issue. These usually do not require significant experience with Rust or the uv code base.

We label issues that we think are a good opportunity for subsequent contributions as help wanted. These require varying levels of experience with Rust and uv. Often, we want to accomplish these tasks but do not have the resources to do so ourselves.

You don't need our permission to start on an issue we have labeled as appropriate for community contribution as described above. However, it's a good idea to indicate that you are going to work on an issue to avoid concurrent attempts to solve the same problem.

Please check in with us before starting work on an issue that has not been labeled as appropriate for community contribution. We're happy to receive contributions for other issues, but it's important to make sure we have consensus on the solution to the problem first.

Outside of issues with the labels above, issues labeled as bug are the best candidates for contribution. In contrast, issues labeled with needs-decision or needs-design are not good candidates for contribution. Please do not open pull requests for issues with these labels.

Please do not open pull requests for new features without prior discussion. While we appreciate exploration of new features, we will almost always close these pull requests immediately. Adding a new feature to uv creates a long-term maintenance burden and requires strong consensus from the uv team before it is appropriate to begin work on an implementation.

Use of AI

We require all use of AI in contributions to follow our AI Policy.

If your contribution does not follow the policy, it will be closed.

Setup

Rust (and a C compiler) are required to build uv.

On Ubuntu and other Debian-based distributions, you can install a C compiler with:

sudo apt install build-essential

On Fedora-based distributions, you can install a C compiler with:

sudo dnf install gcc

On Windows, NASM is required for building the TLS backend (aws-lc-sys). If it is not present, a prebuilt blob provided by aws-lc-sys will be used instead. WinGet can be used to install NASM:

winget install NASM.NASM

After installation, add C:\Program Files\NASM to your PATH. While the prebuilt blob will not be used when NASM is found, you can guarantee this behavior by setting AWS_LC_SYS_PREBUILT_NASM=0.

Testing

For running tests, we recommend nextest.

To run a specific test by name:

cargo nextest run -E 'test(test_name)'

To run all tests and accept snapshot changes:

cargo insta test --accept --test-runner nextest

To update snapshots for a specific test:

cargo insta test --accept --test-runner nextest -- <test_name>

Python

Testing uv requires multiple specific Python versions; they can be installed with:

cargo run python install

The storage directory can be configured with UV_PYTHON_INSTALL_DIR. (It must be an absolute path.)

Snapshot testing

uv uses insta for snapshot testing. It's recommended (but not necessary) to use cargo-insta for a better snapshot review experience. See the installation guide for more information.

In tests, you can use uv_snapshot! macro to simplify creating snapshots for uv commands. For example:

#[test]
fn test_add() {
    let context = TestContext::new("3.12");
    uv_snapshot!(context.filters(), context.add().arg("requests"), @"");
}

To run and review a specific snapshot test:

cargo test --package <package> --test <test> -- <test_name> -- --exact
cargo insta review

A script is available to update the snapshots based on results in CI. This is useful for updating snapshots without re-running the test suite and for updating platform-specific snapshots.

./scripts/apply-ci-snapshots.sh

Git and Git LFS

A subset of uv tests require both Git and Git LFS to execute properly.

These tests can be disabled by turning off either git or git-lfs uv features.

Local testing

You can invoke your development version of uv with cargo run -- <args>. For example:

cargo run -- venv
cargo run -- pip install requests

Formatting

# Rust
cargo fmt --all

# Python
uvx ruff format .

# Markdown, YAML, and other files (requires Node.js)
npx prettier --write .
# or in Docker
docker run --rm -v .:/src/ -w /src/ node:alpine npx prettier --write .

Linting

Linting requires shellcheck and cargo-shear to be installed separately.

# Rust
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings

# Python
uvx ruff check .

# Python type checking
uvx ty check python/uv

# Shell scripts
shellcheck <script>

# Spell checking
uvx typos

# Unused Rust dependencies
cargo shear

Compiling for Windows from Unix

To run clippy for a Windows target from Linux or macOS, you can use cargo-xwin:

# Install cargo-xwin
cargo install cargo-xwin --locked

# Add the Windows target
rustup target add x86_64-pc-windows-msvc

# Run clippy for Windows
cargo xwin clippy --workspace --all-targets --all-features --locked -- -D warnings

Crate structure

Rust does not allow circular dependencies between crates. To visualize the crate hierarchy, install cargo-depgraph and graphviz, then run:

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 system ("Someone's Been Messing With My Subnormals!" on Blogspot, "nvidia-pyindex" on PyPI), which can even occur when just resolving requirements. To prevent this, there's a Docker container you can run commands in:

$ docker build -t uv-builder -f crates/uv-dev/builder.dockerfile --load .
# Build for musl to avoid glibc errors, might not be required with your OS version
cargo build --target x86_64-unknown-linux-musl --profile profiling
docker run --rm -it -v $(pwd):/app uv-builder /app/target/x86_64-unknown-linux-musl/profiling/uv-dev resolve-many --cache-dir /app/cache-docker /app/scripts/popular_packages/pypi_10k_most_dependents.txt

We recommend using this container if you don't trust the dependency tree of the package(s) you are trying to resolve or install.

Profiling and Benchmarking

Please refer to Ruff's Profiling Guide, it applies to uv, too.

We provide diverse sets of requirements for testing and benchmarking the resolver in 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:

uv run resolver \
    --uv-pip \
    --poetry \
    --benchmark \
    resolve-cold \
    ../test/requirements/trio.in

Analyzing concurrency

You can use tracing-durations-export to visualize parallel requests and find any spots where uv is CPU-bound. Example usage, with uv and uv-dev respectively:

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
RUST_LOG=uv=info TRACING_DURATIONS_FILE=target/traces/jupyter.ndjson cargo run --features tracing-durations-export --bin uv-dev --profile profiling -- resolve jupyter

Trace-level logging

You can enable trace level logging using the RUST_LOG environment variable, i.e.

RUST_LOG=trace uv

Documentation

To preview any changes to the documentation locally:

  1. Install the Rust toolchain.

  2. Run cargo dev generate-all, to update any auto-generated documentation.

  3. Run the development server with:

    uv run --only-group docs mkdocs serve -f mkdocs.yml
    

The documentation should then be available locally at http://127.0.0.1:8000/uv/.

Documentation is deployed automatically on release by publishing to the Astral documentation repository, which itself deploys via Cloudflare Pages.

After making changes to the documentation, format the markdown files using Prettier.

Development code signing on macOS

Code signing can only be performed by Astral team members.

Code signing on macOS can improve developer experience when running tests, e.g., when running tests that access the macOS keychain, a signed binary can be approved once but an unsigned binary will need to be approved on each re-compile.

Acquiring a development certificate

  1. Generate a request for the certificate

  2. Create a certificate in the Apple Developer portal

  3. Download and install the certificate to your login keychain

    security import ~/Downloads/mac_development.cer -k ~/Library/Keychains/login.keychain-db
    
  4. Identify your code signing identity

    security find-identity -v -p codesigning
    
  5. If the above fails to find your identity, install the intermediate certificates

    curl -sLO "https://www.apple.com/certificateauthority/AppleWWDRCAG3.cer"
    security import AppleWWDRCAG3.cer -k ~/Library/Keychains/login.keychain-db
    rm AppleWWDRCAG3.cer
    
  6. Set UV_TEST_CODESIGN_IDENTITY

    export UV_TEST_CODESIGN_IDENTITY="Mac Developer: Your Name (TEAM_ID)"
    

Note UV_TEST_CODESIGN_IDENTITY is only supported via nextest.

Releases

Releases can only be performed by Astral team members.

Changelog entries and version bumps are automated. First, run:

./scripts/release.sh

Then, editorialize the CHANGELOG.md file to ensure entries are consistently styled.

Then, open a pull request, e.g., Bump version to ....

Binary builds will automatically be tested for the release.

After merging the pull request, run the release workflow with the version tag. Do not include a leading v. The release will automatically be created on GitHub after everything else publishes.