Move wheel helper function to wheel module (#11212)

No functional changes.
This commit is contained in:
konsti 2025-02-04 13:03:38 +01:00 committed by GitHub
parent 241561979f
commit 1d9db68511
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 72 additions and 70 deletions

View file

@ -4,10 +4,9 @@
use std::path::Path;
use crate::linker::{LinkMode, Locks};
use crate::script::{scripts_from_ini, Script};
use crate::wheel::{
install_data, parse_wheel_file, read_record_file, write_installer_metadata,
write_script_entrypoints, LibKind,
dist_info_metadata, find_dist_info, install_data, parse_scripts, parse_wheel_file,
read_record_file, write_installer_metadata, write_script_entrypoints, LibKind,
};
use crate::{Error, Layout};
use fs_err as fs;
@ -156,69 +155,3 @@ pub fn install_wheel(
Ok(())
}
/// Find the `dist-info` directory in an unzipped wheel.
///
/// See: <https://github.com/PyO3/python-pkginfo-rs>
///
/// See: <https://github.com/pypa/pip/blob/36823099a9cdd83261fdbc8c1d2a24fa2eea72ca/src/pip/_internal/utils/wheel.py#L38>
fn find_dist_info(path: impl AsRef<Path>) -> Result<String, Error> {
// Iterate over `path` to find the `.dist-info` directory. It should be at the top-level.
let Some(dist_info) = fs::read_dir(path.as_ref())?.find_map(|entry| {
let entry = entry.ok()?;
let file_type = entry.file_type().ok()?;
if file_type.is_dir() {
let path = entry.path();
if path.extension().is_some_and(|ext| ext == "dist-info") {
Some(path)
} else {
None
}
} else {
None
}
}) else {
return Err(Error::InvalidWheel(
"Missing .dist-info directory".to_string(),
));
};
let Some(dist_info_prefix) = dist_info.file_stem() else {
return Err(Error::InvalidWheel(
"Missing .dist-info directory".to_string(),
));
};
Ok(dist_info_prefix.to_string_lossy().to_string())
}
/// Read the `dist-info` metadata from a directory.
fn dist_info_metadata(dist_info_prefix: &str, wheel: impl AsRef<Path>) -> Result<Vec<u8>, Error> {
let metadata_file = wheel
.as_ref()
.join(format!("{dist_info_prefix}.dist-info/METADATA"));
Ok(fs::read(metadata_file)?)
}
/// Parses the `entry_points.txt` entry in the wheel for console scripts
///
/// Returns (`script_name`, module, function)
///
/// Extras are supposed to be ignored, which happens if you pass None for extras.
fn parse_scripts(
wheel: impl AsRef<Path>,
dist_info_prefix: &str,
extras: Option<&[String]>,
python_minor: u8,
) -> Result<(Vec<Script>, Vec<Script>), Error> {
let entry_points_path = wheel
.as_ref()
.join(format!("{dist_info_prefix}.dist-info/entry_points.txt"));
// Read the entry points mapping. If the file doesn't exist, we just return an empty mapping.
let Ok(ini) = fs::read_to_string(entry_points_path) else {
return Ok((Vec::new(), Vec::new()));
};
scripts_from_ini(extras, python_minor, ini)
}

View file

@ -20,7 +20,7 @@ use uv_shell::escape_posix_for_single_quotes;
use uv_trampoline_builder::windows_script_launcher;
use crate::record::RecordEntry;
use crate::script::Script;
use crate::script::{scripts_from_ini, Script};
use crate::{Error, Layout};
/// Wrapper script template function
@ -732,6 +732,75 @@ fn parse_email_message_file(
Ok(data)
}
/// Find the `dist-info` directory in an unzipped wheel.
///
/// See: <https://github.com/PyO3/python-pkginfo-rs>
///
/// See: <https://github.com/pypa/pip/blob/36823099a9cdd83261fdbc8c1d2a24fa2eea72ca/src/pip/_internal/utils/wheel.py#L38>
pub(crate) fn find_dist_info(path: impl AsRef<Path>) -> Result<String, Error> {
// Iterate over `path` to find the `.dist-info` directory. It should be at the top-level.
let Some(dist_info) = fs::read_dir(path.as_ref())?.find_map(|entry| {
let entry = entry.ok()?;
let file_type = entry.file_type().ok()?;
if file_type.is_dir() {
let path = entry.path();
if path.extension().is_some_and(|ext| ext == "dist-info") {
Some(path)
} else {
None
}
} else {
None
}
}) else {
return Err(Error::InvalidWheel(
"Missing .dist-info directory".to_string(),
));
};
let Some(dist_info_prefix) = dist_info.file_stem() else {
return Err(Error::InvalidWheel(
"Missing .dist-info directory".to_string(),
));
};
Ok(dist_info_prefix.to_string_lossy().to_string())
}
/// Read the `dist-info` metadata from a directory.
pub(crate) fn dist_info_metadata(
dist_info_prefix: &str,
wheel: impl AsRef<Path>,
) -> Result<Vec<u8>, Error> {
let metadata_file = wheel
.as_ref()
.join(format!("{dist_info_prefix}.dist-info/METADATA"));
Ok(fs::read(metadata_file)?)
}
/// Parses the `entry_points.txt` entry in the wheel for console scripts
///
/// Returns (`script_name`, module, function)
///
/// Extras are supposed to be ignored, which happens if you pass None for extras.
pub(crate) fn parse_scripts(
wheel: impl AsRef<Path>,
dist_info_prefix: &str,
extras: Option<&[String]>,
python_minor: u8,
) -> Result<(Vec<Script>, Vec<Script>), Error> {
let entry_points_path = wheel
.as_ref()
.join(format!("{dist_info_prefix}.dist-info/entry_points.txt"));
// Read the entry points mapping. If the file doesn't exist, we just return an empty mapping.
let Ok(ini) = fs::read_to_string(entry_points_path) else {
return Ok((Vec::new(), Vec::new()));
};
scripts_from_ini(extras, python_minor, ini)
}
#[cfg(test)]
mod test {
use std::io::Cursor;