Skip to content

Commit

Permalink
fix: consist renaming of unpacking to installing
Browse files Browse the repository at this point in the history
  • Loading branch information
baszalmstra committed Feb 18, 2024
1 parent 887e73b commit b02323c
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 51 deletions.
84 changes: 43 additions & 41 deletions crates/rattler_installs_packages/src/install/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub use install_paths::InstallPaths;

#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum UnpackError {
pub enum InstallError {
#[error(transparent)]
FailedToParseWheelVitals(#[from] WheelVitalsError),

Expand Down Expand Up @@ -68,7 +68,7 @@ pub enum UnpackError {
FailedToWriteDirectUrlJson(#[from] serde_json::Error),
}

impl UnpackError {
impl InstallError {
pub(crate) fn from_zip_error(file: String, error: ZipError) -> Self {
match error {
ZipError::Io(err) => Self::IoError(file, err),
Expand All @@ -77,11 +77,11 @@ impl UnpackError {
}
}

/// Additional optional settings to pass to [`Wheel::unpack`].
/// Additional optional settings to pass to [`install_wheel`].
///
/// Not all options in this struct are relevant. Typically you will default a number of fields.
/// Not all options in this struct are relevant. Typically, you will default a number of fields.
#[derive(Default)]
pub struct UnpackWheelOptions<'i> {
pub struct InstallWheelOptions<'i> {
/// When specified an INSTALLER file is written to the dist-info folder of the package.
/// INSTALLER files are used to track the installer of a package. See [PEP 376](https://peps.python.org/pep-0376/) for more information.
pub installer: Option<String>,
Expand Down Expand Up @@ -109,7 +109,7 @@ pub struct UnpackWheelOptions<'i> {

#[derive(Debug)]
/// Information about a wheel that has been unpacked into the destination directory.
pub struct UnpackedWheel {
pub struct InstalledWheel {
/// The path to the *.dist-info directory of the unpacked wheel.
pub dist_info: PathBuf,
}
Expand All @@ -122,8 +122,8 @@ pub fn install_wheel(
dest: &Path,
paths: &InstallPaths,
python_executable: &Path,
options: &UnpackWheelOptions,
) -> Result<UnpackedWheel, UnpackError> {
options: &InstallWheelOptions,
) -> Result<InstalledWheel, InstallError> {
let mut archive = wheel.archive.lock();

// Locate the dist-info folder
Expand All @@ -135,15 +135,15 @@ pub fn install_wheel(
// Read the WHEEL from the archive.
let wheel_path = format!("{dist_info_prefix}.dist-info/WHEEL");
let wheel_metadata = read_entry_to_end(&mut archive, &wheel_path)
.map_err(|err| UnpackError::ZipError(wheel_path, err))?;
.map_err(|err| InstallError::ZipError(wheel_path, err))?;

// Parse the contents of the wheel and verify its version.
let mut parsed = parse_format_metadata_and_check_version(&wheel_metadata, "Wheel-Version")?;

// Find the value for Root-Is-Purelib
let root_is_purelib = parse_root_is_purelib(&mut parsed)
.map_err(WheelVitalsError::InvalidMetadata)
.map_err(UnpackError::FailedToParseWheelVitals)?;
.map_err(InstallError::FailedToParseWheelVitals)?;

// Construct a path transformer, this is used to move files into the right location.
let transformer = WheelPathTransformer {
Expand Down Expand Up @@ -184,7 +184,7 @@ pub fn install_wheel(
for index in 0..archive.len() {
let mut zip_entry = archive
.by_index(index)
.map_err(|e| UnpackError::from_zip_error(format!("<index {index}>"), e))?;
.map_err(|e| InstallError::from_zip_error(format!("<index {index}>"), e))?;
let Some(relative_path) = zip_entry.enclosed_name().map(ToOwned::to_owned) else {
// Skip invalid paths
continue;
Expand Down Expand Up @@ -213,7 +213,7 @@ pub fn install_wheel(
// If the entry refers to a directory we simply create it.
if zip_entry.is_dir() {
fs::create_dir_all(&destination)
.map_err(|err| UnpackError::IoError(destination.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(destination.display().to_string(), err))?;
continue;
}

Expand All @@ -234,7 +234,7 @@ pub fn install_wheel(
let mut buf_reader = BufReader::new(zip_entry);
let script_start = buf_reader
.fill_buf()
.map_err(|err| UnpackError::IoError(destination.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(destination.display().to_string(), err))?;

// Check if the script is a python script or a native binary
if script_start.starts_with(b"#!python") {
Expand All @@ -248,13 +248,13 @@ pub fn install_wheel(
// Read the shebang line from the script
buf_reader
.read_line(&mut String::new())
.map_err(|err| UnpackError::IoError(destination.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(destination.display().to_string(), err))?;

// Read the rest of the script
let mut script = Vec::new();
buf_reader
.read_to_end(&mut script)
.map_err(|err| UnpackError::IoError(destination.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(destination.display().to_string(), err))?;

// Generate the launcher
let trampoline = trampoline_maker.make_trampoline(launcher_type, &script)?;
Expand Down Expand Up @@ -287,7 +287,7 @@ pub fn install_wheel(
let _ = pyc_tx.send((cloned_destination, result));
})
.map_err(|err| {
UnpackError::ByteCodeCompilationFailed(
InstallError::ByteCodeCompilationFailed(
destination.display().to_string(),
err,
)
Expand All @@ -309,7 +309,7 @@ pub fn install_wheel(
})
.and_then(|entry| entry.hash.as_ref())
.ok_or_else(|| {
UnpackError::RecordFile(format!(
InstallError::RecordFile(format!(
"missing hash for {} (expected {})",
relative_path.display(),
encoded_hash
Expand All @@ -318,7 +318,7 @@ pub fn install_wheel(

// Ensure that the hashes match
if &encoded_hash != recorded_hash {
return Err(UnpackError::RecordFile(format!(
return Err(InstallError::RecordFile(format!(
"hash mismatch for {}. Recorded: {}, Actual: {}",
relative_path.display(),
recorded_hash,
Expand Down Expand Up @@ -403,7 +403,7 @@ pub fn install_wheel(
continue;
}
Err(err @ CompilationError::HostQuit) => {
return Err(UnpackError::ByteCodeCompilationFailed(
return Err(InstallError::ByteCodeCompilationFailed(
source.display().to_string(),
err,
));
Expand All @@ -423,7 +423,7 @@ pub fn install_wheel(
Record::from_iter(resulting_records)
.write_to_path(&site_packages.join(record_relative_path))?;

Ok(UnpackedWheel {
Ok(InstalledWheel {
dist_info: site_packages.join(format!("{dist_info_prefix}.dist-info")),
})
}
Expand Down Expand Up @@ -481,11 +481,11 @@ fn write_script_entrypoint(
trampoline_maker: &TrampolineMaker,
launcher_type: LauncherType,
records: &mut Vec<RecordEntry>,
) -> Result<(), UnpackError> {
) -> Result<(), InstallError> {
// Make sure the script directory exists
let scripts_dir = dest.join(install_paths.scripts());
fs::create_dir_all(&scripts_dir)
.map_err(|err| UnpackError::IoError(scripts_dir.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(scripts_dir.display().to_string(), err))?;

for entry_point in entry_points {
// Determine the name of the script
Expand Down Expand Up @@ -546,15 +546,15 @@ impl TrampolineMaker {
&self,
launcher_type: LauncherType,
script: &[u8],
) -> Result<Vec<u8>, UnpackError> {
) -> Result<Vec<u8>, InstallError> {
let shebang = get_shebang(&self.python_executable);
match self.kind {
TrampolineMakerKind::Windows { arch } => {
let arch = match arch {
Some(windows_launcher_arch) => windows_launcher_arch,
None => match WindowsLauncherArch::current() {
Some(arch) => arch,
None => return Err(UnpackError::UnsupportedWindowsArchitecture),
None => return Err(InstallError::UnsupportedWindowsArchitecture),
},
};

Expand Down Expand Up @@ -594,13 +594,13 @@ impl Scripts {
archive: &mut ZipArchive<Box<dyn ReadAndSeek + Send>>,
dist_info_prefix: &str,
extras: Option<&HashSet<Extra>>,
) -> Result<Self, UnpackError> {
) -> Result<Self, InstallError> {
// Read the `entry_points.txt` file from the archive
let entry_points_path = format!("{dist_info_prefix}.dist-info/entry_points.txt");
let mut entry_points_file = match archive.by_name(&entry_points_path) {
Err(ZipError::FileNotFound) => return Ok(Default::default()),
Ok(file) => file,
Err(err) => return Err(UnpackError::from_zip_error(entry_points_path, err)),
Err(err) => return Err(InstallError::from_zip_error(entry_points_path, err)),
};

// Parse the `entry_points.txt` file as an ini file.
Expand All @@ -609,13 +609,13 @@ impl Scripts {
entry_points_file
.read_to_string(&mut ini_contents)
.map_err(|err| {
UnpackError::EntryPointsInvalid(format!(
InstallError::EntryPointsInvalid(format!(
"failed to read entry_points.txt contents: {}",
err
))
})?;
Ini::new_cs().read(ini_contents).map_err(|err| {
UnpackError::EntryPointsInvalid(format!(
InstallError::EntryPointsInvalid(format!(
"failed to parse entry_points.txt contents: {}",
err
))
Expand Down Expand Up @@ -671,17 +671,17 @@ impl Scripts {
fn parse_entry_points_from_ini_section(
entry_points: HashMap<String, Option<String>>,
extras: Option<&HashSet<Extra>>,
) -> Result<Vec<EntryPoint>, UnpackError> {
) -> Result<Vec<EntryPoint>, InstallError> {
let mut result = Vec::new();
for (script_name, entry_point) in entry_points {
let entry_point = entry_point.ok_or_else(|| {
UnpackError::EntryPointsInvalid(format!("missing entry point for {}", script_name))
InstallError::EntryPointsInvalid(format!("missing entry point for {}", script_name))
})?;
match EntryPoint::parse(script_name.clone(), &entry_point, extras) {
Ok(None) => {}
Ok(Some(entry_point)) => result.push(entry_point),
Err(err) => {
return Err(UnpackError::EntryPointsInvalid(format!(
return Err(InstallError::EntryPointsInvalid(format!(
"failed to parse entry point for {}: {}",
script_name, err
)));
Expand All @@ -696,7 +696,7 @@ fn write_generated_file(
site_packages: &Path,
content: impl AsRef<[u8]>,
_executable: bool,
) -> Result<RecordEntry, UnpackError> {
) -> Result<RecordEntry, InstallError> {
let mut options = fs::OpenOptions::new();
options.write(true).create(true).truncate(true);

Expand All @@ -719,7 +719,7 @@ fn write_generated_file(
let (_, digest) = file.finalize();
Ok((content.len(), digest))
})
.map_err(|err| UnpackError::IoError(relative_path.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(relative_path.display().to_string(), err))?;

Ok(RecordEntry {
path: relative_path.display().to_string().replace('\\', "/"),
Expand All @@ -733,7 +733,7 @@ fn write_wheel_file(
mut reader: &mut impl Read,
destination: &Path,
_executable: bool,
) -> Result<(Option<u64>, Option<String>), UnpackError> {
) -> Result<(Option<u64>, Option<String>), InstallError> {
let mut reader = rattler_digest::HashingReader::<_, Sha256>::new(&mut reader);

let mut options = fs::OpenOptions::new();
Expand All @@ -749,13 +749,13 @@ fn write_wheel_file(
}
if let Some(parent) = destination.parent() {
fs::create_dir_all(parent)
.map_err(|err| UnpackError::IoError(parent.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(parent.display().to_string(), err))?;
}
let mut file = options
.open(destination)
.map_err(|err| UnpackError::IoError(destination.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(destination.display().to_string(), err))?;
let size = std::io::copy(&mut reader, &mut file)
.map_err(|err| UnpackError::IoError(destination.display().to_string(), err))?;
.map_err(|err| InstallError::IoError(destination.display().to_string(), err))?;
let (_, digest) = reader.finalize();
Ok((
Some(size),
Expand Down Expand Up @@ -785,7 +785,7 @@ impl<'a> WheelPathTransformer<'a> {
/// Given a path from a wheel zip, analyze the path and determine its final destination path.
///
/// Returns `None` if the path should be ignored.
fn analyze_path(&self, path: &Path) -> Result<Option<(PathBuf, bool)>, UnpackError> {
fn analyze_path(&self, path: &Path) -> Result<Option<(PathBuf, bool)>, InstallError> {
let (category, rest_of_path) = if let Ok(data_path) = path.strip_prefix(&self.data) {
let mut components = data_path.components();
if let Some(category) = components.next() {
Expand All @@ -809,7 +809,9 @@ impl<'a> WheelPathTransformer<'a> {

match self.paths.match_category(category.as_ref(), self.name) {
Some(basepath) => Ok(Some((basepath.join(rest_of_path), category == "scripts"))),
None => Err(UnpackError::UnsupportedDataDirectory(category.into_owned())),
None => Err(InstallError::UnsupportedDataDirectory(
category.into_owned(),
)),
}
}
}
Expand Down Expand Up @@ -887,7 +889,7 @@ mod test {
tmpdir.path(),
&install_paths,
Path::new("/invalid"),
&UnpackWheelOptions {
&InstallWheelOptions {
installer: Some(String::from(INSTALLER)),
byte_code_compiler,
..Default::default()
Expand Down Expand Up @@ -996,7 +998,7 @@ mod test {
let wheel = venv
.install_wheel(
&wheel,
&UnpackWheelOptions {
&InstallWheelOptions {
direct_url_json: Some(direct_url),
..Default::default()
},
Expand Down
8 changes: 5 additions & 3 deletions crates/rattler_installs_packages/src/python_env/venv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
//! Later on we can look into actually creating the environment by linking to the python library,
//! and creating the necessary files. See: [VEnv](https://packaging.python.org/en/latest/specifications/virtual-environments/#declaring-installation-environments-as-python-virtual-environments)
use crate::artifacts::wheel::Wheel;
use crate::install::{install_wheel, InstallPaths, UnpackError, UnpackWheelOptions, UnpackedWheel};
use crate::install::{
install_wheel, InstallError, InstallPaths, InstallWheelOptions, InstalledWheel,
};
use crate::python_env::{
system_python_executable, FindPythonError, ParsePythonInterpreterVersionError,
PythonInterpreterVersion,
Expand Down Expand Up @@ -93,8 +95,8 @@ impl VEnv {
pub fn install_wheel(
&self,
wheel: &Wheel,
options: &UnpackWheelOptions,
) -> Result<UnpackedWheel, UnpackError> {
options: &InstallWheelOptions,
) -> Result<InstalledWheel, InstallError> {
install_wheel(
wheel,
&self.location,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::install::UnpackWheelOptions;
use crate::install::InstallWheelOptions;
use crate::types::ArtifactFromSource;

use crate::python_env::{PythonLocation, VEnv};
Expand Down Expand Up @@ -279,7 +279,7 @@ impl BuildEnvironment {
Ok((wheel, direct_url_json)) => {
self.venv.install_wheel(
&wheel,
&UnpackWheelOptions {
&InstallWheelOptions {
direct_url_json,
..Default::default()
},
Expand Down Expand Up @@ -451,7 +451,7 @@ impl BuildEnvironment {

venv.install_wheel(
&artifact,
&UnpackWheelOptions {
&InstallWheelOptions {
installer: None,
..Default::default()
},
Expand Down
4 changes: 2 additions & 2 deletions crates/rattler_installs_packages/src/wheel_builder/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::install::UnpackError;
use crate::install::InstallError;
use crate::python_env::VEnvError;
use crate::types::{ParseArtifactNameError, WheelCoreMetaDataError};
use crate::wheel_builder::wheel_cache;
Expand All @@ -13,7 +13,7 @@ pub enum WheelBuildError {
Error(String),

#[error("could not install artifact in virtual environment: {0}")]
UnpackError(#[from] UnpackError),
UnpackError(#[from] InstallError),

#[error("could not build wheel: {0}")]
IoError(#[from] std::io::Error),
Expand Down
Loading

0 comments on commit b02323c

Please sign in to comment.