Open-Source Wikis

/

uv

/

Crates

/

uv-installer

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 ResolverOutput or a subset thereof.
  • A target PythonEnvironment (from uv-python).
  • A Cache (from uv-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 files

Key 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| venv

Planning

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:

  • cloneclonefile()/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

  • SitePackages is the integration with uv-install-wheel: it parses each package's .dist-info directory to recover layout, RECORD entries, and metadata.
  • The Reporter traits accept Arc<dyn ...> and are implemented by the binary's crates/uv/src/commands/reporters.rs for progress bars and by tests for assertions.
  • For source distributions, the preparer calls into uv-build-frontend via the BuildContext trait from uv-types to avoid a circular dependency.
  • The cache layout (archive-v0, wheels-v6, built-wheels-v0) is owned by uv-cache.

Entry points for modification

  • A new install mode — extend LinkMode in uv-install-wheel and thread it through Installer::with_link_mode.
  • A new pre/post-install hookInstaller::install is the join point. The compile_bytecode helper in crates/uv/src/commands/mod.rs is an example post-install step.
  • Changing the planning policyplan.rs is the place. The Plan struct's fields are the contract with the preparer/installer.
  • Improving uninstall safetyuninstall.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

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

uv-installer – uv wiki | Factory