Skip to content

Commit

Permalink
Generalize install paths
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Feb 27, 2024
1 parent 3aed158 commit 210ac9d
Show file tree
Hide file tree
Showing 15 changed files with 235 additions and 188 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ miette = { version = "6.0.0" }
nanoid = { version = "0.4.0" }
once_cell = { version = "1.19.0" }
owo-colors = { version = "4.0.0" }
pathdiff = { version = "0.2.1" }
petgraph = { version = "0.6.4" }
platform-info = { version = "2.0.2" }
plist = { version = "1.6.0" }
Expand Down
3 changes: 2 additions & 1 deletion crates/install-wheel-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ data-encoding = { workspace = true }
fs-err = { workspace = true }
mailparse = { workspace = true }
once_cell = { workspace = true }
pathdiff = { workspace = true }
platform-info = { workspace = true }
plist = { workspace = true }
reflink-copy = { workspace = true }
Expand All @@ -51,4 +52,4 @@ walkdir = { workspace = true }
zip = { workspace = true }

[dev-dependencies]
indoc = {version = "2.0.4"}
indoc = { version = "2.0.4" }
41 changes: 0 additions & 41 deletions crates/install-wheel-rs/src/install_location.rs

This file was deleted.

4 changes: 2 additions & 2 deletions crates/install-wheel-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ use zip::result::ZipError;
use zip::ZipArchive;

use distribution_filename::WheelFilename;
pub use install_location::InstallLocation;
use pep440_rs::Version;
use platform_host::{Arch, Os};
pub use target::Target;
pub use uninstall::{uninstall_wheel, Uninstall};
use uv_fs::Normalized;
use uv_normalize::PackageName;

mod install_location;
pub mod linker;
mod record;
mod script;
mod target;
mod uninstall;
mod wheel;

Expand Down
69 changes: 34 additions & 35 deletions crates/install-wheel-rs/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@ use reflink_copy as reflink;
use tempfile::tempdir_in;
use tracing::{debug, instrument};

use crate::Error;
use distribution_filename::WheelFilename;
use pep440_rs::Version;
use pypi_types::DirectUrl;
use uv_normalize::PackageName;

use crate::install_location::InstallLocation;
use crate::script::{scripts_from_ini, Script};
use crate::wheel::{
extra_dist_info, install_data, parse_metadata, parse_wheel_version, read_record_file,
write_script_entrypoints,
extra_dist_info, install_data, parse_metadata, parse_wheel_file, read_record_file,
write_script_entrypoints, LibKind,
};
use crate::{Error, Target};

/// Install the given wheel to the given venv
///
Expand All @@ -32,30 +31,13 @@ use crate::wheel::{
/// Wheel 1.0: <https://www.python.org/dev/peps/pep-0427/>
#[instrument(skip_all, fields(wheel = % wheel.as_ref().display()))]
pub fn install_wheel(
location: &InstallLocation<impl AsRef<Path>>,
target: &Target,
wheel: impl AsRef<Path>,
filename: &WheelFilename,
direct_url: Option<&DirectUrl>,
installer: Option<&str>,
link_mode: LinkMode,
) -> Result<(), Error> {
let root = location.venv_root();

// TODO(charlie): Pass this in.
let site_packages_python = format!(
"python{}.{}",
location.python_version().0,
location.python_version().1
);
let site_packages = if cfg!(target_os = "windows") {
root.as_ref().join("Lib").join("site-packages")
} else {
root.as_ref()
.join("lib")
.join(site_packages_python)
.join("site-packages")
};

let dist_info_prefix = find_dist_info(&wheel)?;
let metadata = dist_info_metadata(&dist_info_prefix, &wheel)?;
let (name, version) = parse_metadata(&dist_info_prefix, &metadata)?;
Expand All @@ -81,13 +63,16 @@ pub fn install_wheel(
.as_ref()
.join(format!("{dist_info_prefix}.dist-info/WHEEL"));
let wheel_text = fs::read_to_string(wheel_file_path)?;
parse_wheel_version(&wheel_text)?;
let lib_kind = parse_wheel_file(&wheel_text)?;

// > 1.c If Root-Is-Purelib == ‘true’, unpack archive into purelib (site-packages).
// > 1.d Else unpack archive into platlib (site-packages).
// We always install in the same virtualenv site packages
debug!(name, "Extracting file");
let num_unpacked = link_mode.link_wheel_files(&site_packages, &wheel)?;
let site_packages = match lib_kind {
LibKind::Pure => &target.purelib,
LibKind::Plat => &target.platlib,
};
let num_unpacked = link_mode.link_wheel_files(site_packages, &wheel)?;
debug!(name, "Extracted {num_unpacked} files");

// Read the RECORD file.
Expand All @@ -100,27 +85,37 @@ pub fn install_wheel(

debug!(name, "Writing entrypoints");
let (console_scripts, gui_scripts) =
parse_scripts(&wheel, &dist_info_prefix, None, location.python_version().1)?;
parse_scripts(&wheel, &dist_info_prefix, None, target.python_version.1)?;
write_script_entrypoints(
&site_packages,
location,
&target.sys_executable,
site_packages,
&target.scripts,
&console_scripts,
&mut record,
false,
)?;
write_script_entrypoints(&site_packages, location, &gui_scripts, &mut record, true)?;
write_script_entrypoints(
&target.sys_executable,
site_packages,
&target.scripts,
&gui_scripts,
&mut record,
true,
)?;

let data_dir = site_packages.join(format!("{dist_info_prefix}.data"));
let data_dir = target.platlib.join(format!("{dist_info_prefix}.data"));
// 2.a Unpacked archive includes distribution-1.0.dist-info/ and (if there is data) distribution-1.0.data/.
// 2.b Move each subtree of distribution-1.0.data/ onto its destination path. Each subdirectory of distribution-1.0.data/ is a key into a dict of destination directories, such as distribution-1.0.data/(purelib|platlib|headers|scripts|data). The initially supported paths are taken from distutils.command.install.
if data_dir.is_dir() {
debug!(name, "Installing data");
install_data(
root.as_ref(),
&site_packages,
&target.sys_executable,
&target.data,
site_packages,
&target.scripts,
&target.include,
&data_dir,
&name,
location,
&console_scripts,
&gui_scripts,
&mut record,
Expand All @@ -135,7 +130,7 @@ pub fn install_wheel(

debug!(name, "Writing extra metadata");
extra_dist_info(
&site_packages,
site_packages,
&dist_info_prefix,
true,
direct_url,
Expand All @@ -147,7 +142,11 @@ pub fn install_wheel(
let mut record_writer = csv::WriterBuilder::new()
.has_headers(false)
.escape(b'"')
.from_path(site_packages.join(format!("{dist_info_prefix}.dist-info/RECORD")))?;
.from_path(
target
.platlib
.join(format!("{dist_info_prefix}.dist-info/RECORD")),
)?;
record.sort();
for entry in record {
record_writer.serialize(entry)?;
Expand Down
19 changes: 19 additions & 0 deletions crates/install-wheel-rs/src/target.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use std::path::PathBuf;

/// A target environment into which a wheel can be installed.
pub struct Target {
/// The Python interpreter, as returned by `sys.executable`.
pub sys_executable: PathBuf,
/// The `purelib` directory, as returned by `sysconfig.get_paths()`.
pub purelib: PathBuf,
/// The `platlib` directory, as returned by `sysconfig.get_paths()`.
pub platlib: PathBuf,
/// The `scripts` directory, as returned by `sysconfig.get_paths()`.
pub include: PathBuf,
/// The `scripts` directory, as returned by `sysconfig.get_paths()`.
pub scripts: PathBuf,
/// The `data` directory, as returned by `sysconfig.get_paths()`.
pub data: PathBuf,
/// The Python version, as returned by `sys.version_info`.
pub python_version: (u8, u8),
}
Loading

0 comments on commit 210ac9d

Please sign in to comment.