Skip to content

Commit

Permalink
feat: add environment variable to disable writing extra dist-info files
Browse files Browse the repository at this point in the history
This change introduces the `UV_EXTRA_DIST_INFO` environment variable
as a way to opt out of the extra dist-info files that `uv` is creating.

This is important to achieve reproducible builds in distribution
packaging, allowing to replace usage of
[installer](https://pypi.org/project/installer) with `uv pip install`.

At the time of writing these files are:
- `uv_cache.json`
    Contains timestamps which are non-reproducible.
    These hashes also leak in to `RECORD`.

- `direct_url.json`
    Contains the path to the installed wheel.
    While not non-reproducible it's not required for distribution packaging.

- `INSTALLER`
    Again, not non-reproducible, but of no value in distribution packaging.
  • Loading branch information
adisbladis committed Nov 7, 2024
1 parent 2340d73 commit aaa8644
Show file tree
Hide file tree
Showing 21 changed files with 153 additions and 14 deletions.
27 changes: 15 additions & 12 deletions crates/uv-install-wheel/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::time::SystemTime;

use crate::script::{scripts_from_ini, Script};
use crate::wheel::{
extra_dist_info, install_data, parse_wheel_file, read_record_file, write_script_entrypoints,
LibKind,
install_data, parse_wheel_file, read_record_file, write_extra_dist_info,
write_script_entrypoints, LibKind,
};
use crate::{Error, Layout};
use fs_err as fs;
Expand Down Expand Up @@ -45,6 +45,7 @@ pub fn install_wheel(
installer: Option<&str>,
link_mode: LinkMode,
locks: &Locks,
extra_dist_info: bool,
) -> Result<(), Error> {
let dist_info_prefix = find_dist_info(&wheel)?;
let metadata = dist_info_metadata(&dist_info_prefix, &wheel)?;
Expand Down Expand Up @@ -140,16 +141,18 @@ pub fn install_wheel(
trace!(?name, "No data");
}

trace!(?name, "Writing extra metadata");
extra_dist_info(
site_packages,
&dist_info_prefix,
true,
direct_url,
cache_info,
installer,
&mut record,
)?;
if extra_dist_info {
trace!(?name, "Writing extra metadata");
write_extra_dist_info(
site_packages,
&dist_info_prefix,
true,
direct_url,
cache_info,
installer,
&mut record,
)?;
}

trace!(?name, "Writing record");
let mut record_writer = csv::WriterBuilder::new()
Expand Down
4 changes: 2 additions & 2 deletions crates/uv-install-wheel/src/wheel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ pub(crate) fn write_file_recorded(
}

/// Adds `INSTALLER`, `REQUESTED` and `direct_url.json` to the .dist-info dir
pub(crate) fn extra_dist_info(
pub(crate) fn write_extra_dist_info(
site_packages: &Path,
dist_info_prefix: &str,
requested: bool,
Expand Down Expand Up @@ -767,7 +767,7 @@ mod test {
Wheel-Version: 1.0
Generator: bdist_wheel (0.37.1)
Root-Is-Purelib: false
Tag: cp38-cp38-manylinux_2_17_x86_64
Tag: cp38-cp38-manylinux_2_17_x86_64
"};

let wheel = parse_email_message_file(&mut text.as_bytes(), "WHEEL").unwrap();
Expand Down
16 changes: 16 additions & 0 deletions crates/uv-installer/src/installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct Installer<'a> {
cache: Option<&'a Cache>,
reporter: Option<Box<dyn Reporter>>,
installer_name: Option<String>,
extra_dist_info: bool,
}

impl<'a> Installer<'a> {
Expand All @@ -26,6 +27,7 @@ impl<'a> Installer<'a> {
cache: None,
reporter: None,
installer_name: Some("uv".to_string()),
extra_dist_info: true,
}
}

Expand Down Expand Up @@ -62,6 +64,15 @@ impl<'a> Installer<'a> {
}
}

/// Set the whether to link Uv specific files in dist-info
#[must_use]
pub fn with_extra_dist_info(self, extra_dist_info: bool) -> Self {
Self {
extra_dist_info,
..self
}
}

/// Install a set of wheels into a Python virtual environment.
#[instrument(skip_all, fields(num_wheels = %wheels.len()))]
pub async fn install(self, wheels: Vec<CachedDist>) -> Result<Vec<CachedDist>> {
Expand All @@ -71,6 +82,7 @@ impl<'a> Installer<'a> {
link_mode,
reporter,
installer_name,
extra_dist_info,
} = self;

if cache.is_some_and(Cache::is_temporary) {
Expand All @@ -93,6 +105,7 @@ impl<'a> Installer<'a> {
link_mode,
reporter,
relocatable,
extra_dist_info,
);

// This may fail if the main task was cancelled.
Expand Down Expand Up @@ -122,6 +135,7 @@ impl<'a> Installer<'a> {
self.link_mode,
self.reporter,
self.venv.relocatable(),
self.extra_dist_info,
)
}
}
Expand All @@ -135,6 +149,7 @@ fn install(
link_mode: LinkMode,
reporter: Option<Box<dyn Reporter>>,
relocatable: bool,
extra_dist_info: bool,
) -> Result<Vec<CachedDist>> {
let locks = uv_install_wheel::linker::Locks::default();
wheels.par_iter().try_for_each(|wheel| {
Expand All @@ -157,6 +172,7 @@ fn install(
installer_name.as_deref(),
link_mode,
&locks,
extra_dist_info,
)
.with_context(|| format!("Failed to install: {} ({wheel})", wheel.filename()))?;

Expand Down
3 changes: 3 additions & 0 deletions crates/uv-static/src/env_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,4 +525,7 @@ impl EnvVars {

/// Ignore `.env` files when executing `uv run` commands.
pub const UV_NO_ENV_FILE: &'static str = "UV_NO_ENV_FILE";

/// Skip writing `uv` cache & installer files to site-packages dist-info.
pub const UV_EXTRA_DIST_INFO: &'static str = "UV_EXTRA_DIST_INFO";
}
2 changes: 2 additions & 0 deletions crates/uv/src/commands/pip/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub(crate) async fn pip_install(
cache: Cache,
dry_run: bool,
printer: Printer,
extra_dist_info: bool,
) -> anyhow::Result<ExitStatus> {
let start = std::time::Instant::now();

Expand Down Expand Up @@ -449,6 +450,7 @@ pub(crate) async fn pip_install(
Box::new(DefaultInstallLogger),
dry_run,
printer,
extra_dist_info,
)
.await?;

Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/pip/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ pub(crate) async fn install(
logger: Box<dyn InstallLogger>,
dry_run: bool,
printer: Printer,
extra_dist_info: bool,
) -> Result<Changelog, Error> {
let start = std::time::Instant::now();

Expand Down Expand Up @@ -514,6 +515,7 @@ pub(crate) async fn install(
installs = uv_installer::Installer::new(venv)
.with_link_mode(link_mode)
.with_cache(cache)
.with_extra_dist_info(extra_dist_info)
.with_reporter(InstallReporter::from(printer).with_length(installs.len() as u64))
// This technically can block the runtime, but we are on the main thread and
// have no other running tasks at this point, so this lets us avoid spawning a blocking
Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/pip/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub(crate) async fn pip_sync(
cache: Cache,
dry_run: bool,
printer: Printer,
extra_dist_info: bool,
) -> Result<ExitStatus> {
let client_builder = BaseClientBuilder::new()
.connectivity(connectivity)
Expand Down Expand Up @@ -393,6 +394,7 @@ pub(crate) async fn pip_sync(
Box::new(DefaultInstallLogger),
dry_run,
printer,
extra_dist_info,
)
.await?;

Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/commands/project/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub(crate) async fn add(
native_tls: bool,
cache: &Cache,
printer: Printer,
extra_dist_info: bool,
) -> Result<ExitStatus> {
for source in &requirements {
match source {
Expand Down Expand Up @@ -638,6 +639,7 @@ pub(crate) async fn add(
native_tls,
cache,
printer,
extra_dist_info,
)
.await
{
Expand Down Expand Up @@ -698,6 +700,7 @@ async fn lock_and_sync(
native_tls: bool,
cache: &Cache,
printer: Printer,
extra_dist_info: bool,
) -> Result<(), ProjectError> {
let mode = if locked {
LockMode::Locked(venv.interpreter())
Expand Down Expand Up @@ -897,6 +900,7 @@ async fn lock_and_sync(
native_tls,
cache,
printer,
extra_dist_info,
)
.await?;

Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/project/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ impl CachedEnvironment {
native_tls: bool,
cache: &Cache,
printer: Printer,
extra_dist_info: bool,
) -> Result<Self, ProjectError> {
// When caching, always use the base interpreter, rather than that of the virtual
// environment.
Expand Down Expand Up @@ -118,6 +119,7 @@ impl CachedEnvironment {
native_tls,
cache,
printer,
extra_dist_info,
)
.await?;

Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/commands/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,7 @@ pub(crate) async fn sync_environment(
native_tls: bool,
cache: &Cache,
printer: Printer,
extra_dist_info: bool,
) -> anyhow::Result<PythonEnvironment> {
let InstallerSettingsRef {
index_locations,
Expand Down Expand Up @@ -1070,6 +1071,7 @@ pub(crate) async fn sync_environment(
logger,
dry_run,
printer,
extra_dist_info,
)
.await?;

Expand Down Expand Up @@ -1108,6 +1110,7 @@ pub(crate) async fn update_environment(
native_tls: bool,
cache: &Cache,
printer: Printer,
extra_dist_info: bool,
) -> anyhow::Result<EnvironmentUpdate> {
warn_on_requirements_txt_setting(&spec, settings.as_ref().into());

Expand Down Expand Up @@ -1310,6 +1313,7 @@ pub(crate) async fn update_environment(
install,
dry_run,
printer,
extra_dist_info,
)
.await?;

Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/project/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub(crate) async fn remove(
native_tls: bool,
cache: &Cache,
printer: Printer,
extra_dist_info: bool,
) -> Result<ExitStatus> {
let target = if let Some(script) = script {
// If we found a PEP 723 script and the user provided a project-only setting, warn.
Expand Down Expand Up @@ -264,6 +265,7 @@ pub(crate) async fn remove(
native_tls,
cache,
printer,
extra_dist_info,
)
.await?;

Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/commands/project/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub(crate) async fn run(
printer: Printer,
env_file: Vec<PathBuf>,
no_env_file: bool,
extra_dist_info: bool,
) -> anyhow::Result<ExitStatus> {
// These cases seem quite complex because (in theory) they should change the "current package".
// Let's ban them entirely for now.
Expand Down Expand Up @@ -317,6 +318,7 @@ pub(crate) async fn run(
native_tls,
cache,
printer,
extra_dist_info,
)
.await;

Expand Down Expand Up @@ -709,6 +711,7 @@ pub(crate) async fn run(
native_tls,
cache,
printer,
extra_dist_info,
)
.await?;

Expand Down Expand Up @@ -836,6 +839,7 @@ pub(crate) async fn run(
native_tls,
cache,
printer,
extra_dist_info,
)
.await;

Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/commands/project/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub(crate) async fn sync(
native_tls: bool,
cache: &Cache,
printer: Printer,
extra_dist_info: bool,
) -> Result<ExitStatus> {
// Identify the project.
let project = if frozen {
Expand Down Expand Up @@ -211,6 +212,7 @@ pub(crate) async fn sync(
native_tls,
cache,
printer,
extra_dist_info,
)
.await?;

Expand All @@ -234,6 +236,7 @@ pub(super) async fn do_sync(
native_tls: bool,
cache: &Cache,
printer: Printer,
extra_dist_info: bool,
) -> Result<(), ProjectError> {
// Use isolated state for universal resolution. When resolving, we don't enforce that the
// prioritized distributions match the current platform. So if we lock here, then try to
Expand Down Expand Up @@ -421,6 +424,7 @@ pub(super) async fn do_sync(
logger,
dry_run,
printer,
extra_dist_info,
)
.await?;

Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/commands/tool/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use crate::printer::Printer;
use crate::settings::ResolverInstallerSettings;

/// Install a tool.
#[allow(clippy::fn_params_excessive_bools)]
pub(crate) async fn install(
package: String,
editable: bool,
Expand All @@ -51,6 +52,7 @@ pub(crate) async fn install(
native_tls: bool,
cache: Cache,
printer: Printer,
extra_dist_info: bool,
) -> Result<ExitStatus> {
let client_builder = BaseClientBuilder::new()
.connectivity(connectivity)
Expand Down Expand Up @@ -354,6 +356,7 @@ pub(crate) async fn install(
native_tls,
&cache,
printer,
extra_dist_info,
)
.await?
.into_environment();
Expand Down Expand Up @@ -402,6 +405,7 @@ pub(crate) async fn install(
native_tls,
&cache,
printer,
extra_dist_info,
)
.await
.inspect_err(|_| {
Expand Down
Loading

0 comments on commit aaa8644

Please sign in to comment.