astral-sh/uv
Patterns and conventions
Conventions that recur throughout uv. Most are documented in AGENTS.md and STYLE.md; this
page collects the ones that show up in code reviews most often.
Rust style
Imports
Use top-level imports rather than local imports or fully-qualified paths. The exception is
when the type name would conflict with a local one, in which case rename via use ... as:
use std::io;
use std::path::{Path, PathBuf};
use anyhow::{Result, anyhow};
use tracing::{debug, instrument};
use uv_cache::Cache;
use uv_resolver::{Resolver, ResolverEnvironment};Naming
- Don't shorten variable names. Use
versionnotver,requires_pythonnotrp,interpreternotint. Names should make a reader who is unfamiliar with the code understand what's happening. - Use
[TypeName]references in doc comments so they render as Rustdoc links.
Error handling
uv treats user-visible errors as a first-class concern.
- Library crates use
thiserrorto define typed error enums. Errors should have specific variants per failure mode and ideally carry the offending value (path, version, URL, …) so the error message can render it. - The top-level binary (
crates/uv/) usesanyhowfor orchestration where the error source no longer matters. - Fancy error reports are produced via
miettewith thefancy-no-backtracefeature. - Always prefer
if letand let-chains (if let X = y && condition) over deeply nested pattern matches. - Avoid
panic!,unreachable!,.unwrap(), andunsafeoutside of well-justified performance paths. Whenunsafeis required, write aSAFETY:comment in the project's usual style explaining why the invariant holds. - Prefer
#[expect(rule = "...")]over#[allow(...)]when a clippy rule must be disabled. This way the suppression breaks if the underlying issue is fixed.
Lints
The workspace enables clippy::pedantic with a small allowlist (see [workspace.lints.clippy]
in Cargo.toml). Notably:
print_stdoutandprint_stderrare denied in library crates. The user-facing CLI output uses thePrinterabstraction incrates/uv/src/printer.rs(with structuredanstream-aware streams).dbg_macro,exit,get_unwrap,rc_buffer, andrc_mutexare warnings.use_selfis required.unsafe_codeandunreachable_pubare workspace-wide warnings.
The project's stance is: clippy warnings on main are bugs, not technical debt.
Concurrency
tokiofor I/O. HTTP, filesystem reads/writes, and process spawns are async. The resolver in particular uses tokio channels andoneshots to coordinate with prefetchers.rayonfor CPU-bound work. Wheel installation and bytecode compilation parallelize over rayon. Theinitialize_rayon_oncehelper inuv-configurationensures the global pool is configured once.- The resolver uses
std::thread::scopeto drive PubGrub on an OS thread while async prefetchers feed it metadata via channels (seecrates/uv-resolver/src/resolver/mod.rs).
Crate boundaries
uv enforces a strict crate hierarchy because Cargo forbids circular dependencies. A few conventions help:
- Trait-based abstractions. When a resolver needs to call into install/build code, it does
so via a trait defined in
uv-types(BuildContext,InstalledPackagesProvider,SourceBuildTrait, …). The implementations live in concrete crates that depend onuv-types. *-typescrates for shared data models.uv-distribution-types,uv-pypi-types, anduv-git-typeshold pure data structures that downstream crates can use without pulling in the full implementation.- The dependency graph can be visualized with
cargo depgraph --dedup-transitive-deps --workspace-only | dot -Tpng > graph.png(cargo-depgraph + graphviz needed).
Logging
tracingeverywhere. Thetracing::{debug, trace, info, warn}macros are imported at the top of most files.#[instrument(skip_all, ...)]on hot paths. Span fields (fields(num_wheels = ...)) show up in the durations export.- No
println!in libraries. Usetracingor, in the binary crate, thePrinterabstraction.
User-facing output
STYLE.md codifies the conventions for messages and docs. Highlights:
- Stylize uv as
uv— neverUv(capitalized) orUV(uppercased). The exception is environment variables (UV_PYTHON,UV_CACHE_DIR). - Backticks for paths, packages, and commands.
- Cyan for paths and important literals; green for commands; red for errors; yellow for
warnings; cyan for hints. The CLI must remain interpretable when colors are disabled
(
NO_COLORis respected). - Hints follow errors, separated by a blank line, prefixed with
hint:. warn_userandwarn_user_onceare the right way to surface actionable warnings; they show up without--verbose.tracing::warn!is reserved for diagnostic warnings the user might never see.- All logging goes to stderr. Stdout is reserved for "data" the user might pipe.
- Lockfile (one word), pre-release (hyphenated),
requires_pythonin code,requires-pythonin docs/CLI.
Testing
Conventions covered in detail in Testing, but the must-knows:
- Prefer integration tests under
crates/uv/tests/it/. Snapshot viauv_snapshot!andinsta. Copy the style of nearby tests. - Add a test for every behavior change. When fixing a bug, the test should fail before the fix and pass after.
- Run focused tests, not the whole suite, during iteration. Full runs are slow.
Async patterns
Arc<dyn Reporter>for progress. Most long-running APIs (resolver, installer, preparer) accept an optionalArc<dyn Reporter>for progress callbacks. This keeps the business logic free of UI concerns and lets the CLI (or a test) plug in different reporters.Sender/Receiverchannels for resolver coordination. The resolver and its prefetcher live on different threads/futures and exchangeMetadataResponseandVersionsResponsevalues via tokio channels.
On-disk formats
- TOML for everything user-visible.
pyproject.toml,uv.toml,uv.lock,uv-receipt.toml. Usetomlfor read-only andtoml_editfor mutate-and-preserve-style edits (seecrates/uv-workspace/src/pyproject_mut.rs). - rkyv for cache files. Registry responses, metadata, and even some
Version/VersionSpecifierrepresentations are stored as rkyv archives so they can be memory-mapped on read. - Atomic writes.
uv_fs::write_atomicis the standard way to write to a path that other uv processes might be reading.
Dependency hygiene
- Don't
cargo updatein bulk. Usecargo update --precisefor targeted lockfile changes. Routine bumps are handled by Renovate. - Audit new dependencies. uv has a small, deliberately curated set. Adding a new dependency needs prior discussion.
cargo shearruns in CI to flag unused dependencies.
Documentation style
The user docs in docs/ use mkdocs. The STYLE.md distinguishes three doc types:
- Guides assume no prior uv knowledge, second person, imperative voice, link to concepts.
- Concepts explain behavior in detail, third person, no imperative voice.
- Reference is generated from code, third person.
Rust doc comments target the in-repo cargo doc reader (uv-internal API is not "stable") so
they can be terse. Use [TypeName] references for navigation.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.