astral-sh/uv
uv-installer
crates/uv-installer/ turns a resolved set of distributions into a concrete set of files in a
virtual environment. It plans which wheels need to be downloaded, prepares them in parallel,
links them into the venv, and (optionally) compiles bytecode.
Purpose
Given:
- A
ResolverOutputor a subset thereof. - A target
PythonEnvironment(fromuv-python). - A
Cache(fromuv-cache).
…produce a fully populated venv with the right wheels installed, the right entry points written, and (optionally) bytecode pre-compiled.
The crate is deliberately layered. It builds on uv-install-wheel (the
low-level wheel layout / record / RECORD healing logic) and on uv-distribution
(for fetching distributions).
Directory layout
crates/uv-installer/src/
├── lib.rs # Re-exports Installer, Plan, Planner, Preparer, SitePackages, …
├── installer.rs # The Installer: links cached wheels into a venv with rayon parallelism
├── preparer.rs # The Preparer: downloads + builds wheels, deduping via OnceMap
├── plan.rs # The Planner: diffs wanted vs. installed and produces a Plan
├── satisfies.rs # Logic for "is this installed package compatible with this requirement?"
├── site_packages.rs # SitePackages: enumerate and reason about an existing site-packages dir
├── compile.rs # Parallel bytecode compilation via the embedded pip_compileall.py
├── pip_compileall.py # The Python helper invoked by compile.rs
└── uninstall.rs # Wheel-aware uninstall using RECORD filesKey abstractions
| Type | File | Role |
|---|---|---|
Plan / Planner |
plan.rs |
Diff the resolved set against SitePackages and produce a categorized Plan (cached / remote / built / extraneous / reinstalled). |
Preparer |
preparer.rs |
Async pipeline that downloads wheels, builds source distributions, hashes archives, and produces CachedDists. Uses OnceMap for dedup. |
Installer |
installer.rs |
Takes the prepared CachedDists and links/copies/clones them into the venv on a rayon thread pool. |
SitePackages |
site_packages.rs |
A view of an existing site-packages directory: which packages are installed, their metadata, dist-info digests, broken symlinks. |
SitePackagesDiagnostic |
site_packages.rs |
Surfaces broken installs (missing metadata, invalid RECORD, dangling symlinks). |
InstallationStrategy |
site_packages.rs |
"Exact" vs. "inexact" install — whether to remove extraneous packages. |
SatisfiesResult |
site_packages.rs / satisfies.rs |
Whether the existing venv satisfies a requirement set, used to skip work. |
Reporter (InstallReporter, PrepareReporter) |
installer.rs, preparer.rs |
Trait callbacks for progress bars. The binary's crates/uv/src/commands/reporters.rs implements them. |
compile_tree |
compile.rs |
Walks site-packages and bytecode-compiles every .py file using a single Python subprocess that reads tasks over stdin. |
uninstall |
uninstall.rs |
Removes a package by parsing its RECORD file, deleting listed paths, and pruning empty directories. |
How it works
flowchart LR
resolver[ResolverOutput<br/>or Lock + InstallTarget] --> planner[Planner]
sitepkgs[SitePackages<br/>existing venv state] --> planner
planner --> plan[Plan<br/>cached / remote / extraneous / reinstalled]
plan --> preparer[Preparer]
preparer -->|fetch metadata + bytes| client[uv-client]
preparer -->|build sdists| frontend[uv-build-frontend]
preparer --> cached[Vec<CachedDist>]
cached --> installer[Installer]
installer -->|rayon link/copy/clone| venv[(.venv/site-packages)]
venv --> compile[compile_tree]
compile -->|bytecode| venvPlanning
Planner::build walks the requested set and the existing SitePackages. For each package it
classifies the work:
- Already installed at the right version — skip.
- Already installed but wrong version / hash — slate for reinstall.
- Wheel cached locally — copy from the cache (no network).
- Wheel known to the resolver but not cached — fetch.
- Source distribution — download and build, then install.
- Extraneous — present in the venv but not in the resolution. In "exact" mode, mark for removal.
The result is a Plan whose cached, remote, built, installed, extraneous, and
reinstalls fields drive the next phases.
Preparation
Preparer::prepare fans out across the planned distributions using tokio tasks plus a
OnceMap keyed by distribution identity. This means:
- Two requests for the same wheel deduplicate.
- Source distributions are built once and the resulting wheel is shared.
- Hash verification happens during the read, not as a second pass.
The preparer is also the integration point with the build frontend: when an sdist needs to be
built, the preparer obtains a fresh build environment via the BuildContext trait
(implemented by the binary crate to use uv-build-frontend).
Installation
Installer::install (in installer.rs) takes the prepared CachedDists and rayon-parallelizes
the actual file linking. The LinkMode from uv-install-wheel decides
how files are placed:
clone—clonefile()/copy_file_range()on macOS APFS / Linux btrfs; copy elsewhere.copy— plain copy.hardlink— hard links (default on most platforms).symlink— symbolic links (only when explicit, since they break some installers).
Installer is configured with builder methods (with_link_mode, with_cache, with_reporter,
with_installer_name, with_installer_metadata) and an opt-out for installer metadata files
(INSTALLER, REQUESTED, direct_url.json).
Uninstall
uninstall::uninstall(installed) reads the RECORD file from the package's dist-info and
removes every listed file, then prunes empty directories. The function is hardened against
malicious RECORDs after GHSA-pjjw-68hj-v9mw
(Apr 2026) — RECORD entries that escape the venv or contain symlink traversal are validated and
healed before the deletion happens (see #18942 / #18943).
Bytecode compilation
compile.rs runs Python with pip_compileall.py once per venv and feeds it .py paths over
stdin. The Python child writes back per-file timing/results, which the Rust side aggregates.
This is dramatically faster than spawning Python per file because of Python's startup cost.
Integration points
SitePackagesis the integration withuv-install-wheel: it parses each package's.dist-infodirectory to recover layout, RECORD entries, and metadata.- The
Reportertraits acceptArc<dyn ...>and are implemented by the binary'scrates/uv/src/commands/reporters.rsfor progress bars and by tests for assertions. - For source distributions, the preparer calls into
uv-build-frontendvia theBuildContexttrait fromuv-typesto avoid a circular dependency. - The cache layout (
archive-v0,wheels-v6,built-wheels-v0) is owned byuv-cache.
Entry points for modification
- A new install mode — extend
LinkModeinuv-install-wheeland thread it throughInstaller::with_link_mode. - A new pre/post-install hook —
Installer::installis the join point. Thecompile_bytecodehelper incrates/uv/src/commands/mod.rsis an example post-install step. - Changing the planning policy —
plan.rsis the place. ThePlanstruct's fields are the contract with the preparer/installer. - Improving uninstall safety —
uninstall.rs. The recent RECORD-validation work shows the pattern: validate before mutating, never delete outside the venv.
Key source files
| File | Purpose |
|---|---|
crates/uv-installer/src/plan.rs |
Diffs requested vs. installed and produces a Plan. |
crates/uv-installer/src/preparer.rs |
Downloads + builds wheels in parallel. |
crates/uv-installer/src/installer.rs |
Links wheels into the venv. |
crates/uv-installer/src/site_packages.rs |
Site-packages enumeration and diagnostics. |
crates/uv-installer/src/compile.rs |
Bytecode compilation orchestrator. |
crates/uv-installer/src/uninstall.rs |
RECORD-driven uninstall. |
crates/uv-installer/src/satisfies.rs |
"Does this package satisfy this requirement?" |
See also
uv-install-wheelfor the low-level wheel layout.uv-distributionfor where wheels and sdists come from.uv-build-frontendfor sdist builds.uv-cachefor the on-disk archive cache.- features/project-workflow — install in context of
uv sync.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.