From 2decc1850ea0057a673009b601013c852888ad1d Mon Sep 17 00:00:00 2001 From: Emerentius Date: Mon, 11 Aug 2025 18:34:31 +0200 Subject: [PATCH 1/7] improve error handling * remove some unwraps() * replace most remaining unwraps() with expect() There are some iterator impls that aren't yet converted. --- src/internal_store.rs | 26 ++++++++++++++------- src/main.rs | 7 +++--- src/prelude.rs | 10 ++++---- src/python.rs | 49 ++++++++++++++++++++++++--------------- src/python/detection.rs | 15 ++++++------ src/venv.rs | 51 +++++++++++++++++++++++------------------ 6 files changed, 94 insertions(+), 64 deletions(-) diff --git a/src/internal_store.rs b/src/internal_store.rs index 6b68ba7..73ee0fc 100644 --- a/src/internal_store.rs +++ b/src/internal_store.rs @@ -189,8 +189,12 @@ fn all_virtpy_backings( .read_dir() .wrap_err("failed to read virtpy dir")? .filter_map(|virtpy| { - let virtpy = virtpy.unwrap(); - if !(virtpy.file_type().unwrap().is_dir()) { + let virtpy = virtpy.expect("failed to read virtpy dir"); + if !(virtpy + .file_type() + .expect("file type of virtpy dir should be readable") + .is_dir()) + { return None; } let path = virtpy.utf8_path(); @@ -497,7 +501,11 @@ pub(crate) fn stored_distribution_of_installed_dist( fn _stored_distribution_of_installed_dist(dist_info_path: &Path) -> Result { let hash_path = dist_info_path.join(crate::DIST_HASH_FILE); let hash = fs_err::read_to_string(hash_path).wrap_err("failed to get distribution hash")?; - let (name, version) = package_info_from_dist_info_dirname(dist_info_path.file_name().unwrap()); + let (name, version) = package_info_from_dist_info_dirname( + dist_info_path + .file_name() + .expect("dist_info_path should have a dirname"), + ); Ok(StoredDistribution { distribution: Distribution { @@ -598,7 +606,7 @@ impl StoredDistribution { // but it's only called once per package when installing it into // a new virtpy right now, so it doesn't matter. let path_in_record = PathBuf::from(self.distribution.dist_info_name()).join(file); - let record = WheelRecord::from_file(record_path).unwrap(); + let record = WheelRecord::from_file(record_path).expect("wheel record should be readable"); record .files .into_iter() @@ -606,8 +614,11 @@ impl StoredDistribution { .map(|entry| ctx.proj_dirs.package_file(&entry.hash)) } - pub(crate) fn entrypoints(&self, ctx: &Ctx) -> Option> { - crate::python::entrypoints(&self.dist_info_file(ctx, "entry_points.txt")?) + pub(crate) fn entrypoints(&self, ctx: &Ctx) -> Result> { + self.dist_info_file(ctx, "entry_points.txt") + .map_or(Ok(vec![]), |entry_points| { + crate::python::entrypoints(&entry_points) + }) } // Returns the directory where the RECORD of this distribution is stored. @@ -633,8 +644,7 @@ impl StoredDistribution { // for the legacy pip installed distributions it is just the entrypoints. pub(crate) fn executable_names(&self, ctx: &Ctx) -> eyre::Result> { let entrypoint_exes = self - .entrypoints(ctx) - .unwrap_or_default() + .entrypoints(ctx)? .into_iter() .map(|ep| ep.name) .collect::>(); diff --git a/src/main.rs b/src/main.rs index 1405422..946504b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -597,10 +597,11 @@ fn main() -> Result<()> { .proj_dirs .virtpys() .read_dir()? - .map(|entry| entry.unwrap()) + .map(|entry| entry.expect("virtpy dir should be readable")) .filter(|entry| entry.path().join(CENTRAL_METADATA).exists()) .map(|entry| entry.path().join(CENTRAL_METADATA).join(LINK_LOCATION)) - .map(|path| fs_err::read_to_string(path).unwrap()) + // CHECKME: Is this guaranteed by construction + .map(|path| fs_err::read_to_string(path).expect("link location should exist")) .sorted() .collect_vec(); for path in link_locations { @@ -805,7 +806,7 @@ fn python_path(virtpy: &Path) -> PathBuf { } fn dist_info_matches_package(dist_info: &Path, package: &str) -> bool { - let entry_name = dist_info.file_name().unwrap(); + let entry_name = dist_info.file_name().expect("should be a dir path"); let (distrib_name, _version) = package_info_from_dist_info_dirname(entry_name); distrib_name == package } diff --git a/src/prelude.rs b/src/prelude.rs index f9ecbc2..96dd52c 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -13,7 +13,7 @@ pub trait ToUtf8Path<'a> { impl<'a> ToUtf8Path<'a> for &'a std::path::Path { fn to_utf8_path(self) -> &'a Utf8Path { - self.try_to_utf8_path().unwrap() + self.try_to_utf8_path().expect("path should be utf8") } fn try_to_utf8_path(self) -> eyre::Result<&'a Utf8Path> { @@ -32,7 +32,7 @@ impl IntoUtf8Pathbuf for std::path::PathBuf { } fn into_utf8_pathbuf(self) -> Utf8PathBuf { - self.try_into_utf8_pathbuf().unwrap() + self.try_into_utf8_pathbuf().expect("path should be utf8") } } @@ -44,7 +44,7 @@ pub trait DirEntryExt { impl DirEntryExt for fs_err::DirEntry { fn utf8_path(&self) -> Utf8PathBuf { - self.try_utf8_path().unwrap() + self.try_utf8_path().expect("path should be utf8") } fn try_utf8_path(&self) -> eyre::Result { @@ -58,7 +58,7 @@ impl DirEntryExt for fs_err::DirEntry { impl DirEntryExt for std::fs::DirEntry { fn utf8_path(&self) -> Utf8PathBuf { - self.try_utf8_path().unwrap() + self.try_utf8_path().expect("path should be utf8") } fn try_utf8_path(&self) -> eyre::Result { @@ -77,7 +77,7 @@ pub trait TempDirExt<'a> { impl<'a> TempDirExt<'a> for &'a tempdir::TempDir { fn utf8_path(self) -> &'a Utf8Path { - self.try_utf8_path().unwrap() + self.try_utf8_path().expect("path should be utf8") } fn try_utf8_path(self) -> eyre::Result<&'a Utf8Path> { diff --git a/src/python.rs b/src/python.rs index f6e774d..e903592 100644 --- a/src/python.rs +++ b/src/python.rs @@ -80,7 +80,11 @@ impl FileHash { // files in the repository are named after their hash, so we can just use the filename pub(crate) fn from_filename(path: &Path) -> Self { - Self(path.file_name().unwrap().to_owned()) + Self( + path.file_name() + .expect("path should have filename") + .to_owned(), + ) } pub(crate) fn from_reader(reader: impl std::io::Read) -> Self { @@ -138,16 +142,25 @@ pub(crate) struct EntryPoint { impl EntryPoint { // construct from entry_points ini entry - pub(crate) fn new(key: &str, value: &str) -> Self { + // Example of typical console scripts from + // https://packaging.python.org/en/latest/specifications/entry-points/#file-format + // + // [console_scripts] + // foo = foomod:main + // # One which depends on extras: + // foobar = foomod:main_bar [bar,baz] + pub(crate) fn new(key: &str, value: &str) -> Result { + // TODO: allow spaces in positions allowed by spec + // TODO: support extras let mut it = value.split(':'); let module = it.next().unwrap().to_owned(); let qualname = it.next().unwrap().to_owned(); - EntryPoint { + Ok(EntryPoint { name: key.to_owned(), module, qualname, - } + }) } // without shebang @@ -321,24 +334,24 @@ impl Distribution { } } -pub(crate) fn entrypoints(path: &Path) -> Option> { +pub(crate) fn entrypoints(path: &Path) -> Result> { let ini = ini::Ini::load_from_file(path); match ini { - Err(ini::Error::Io(err)) if is_not_found(&err) => return None, + Err(ini::Error::Io(err)) if is_not_found(&err) => return Ok(vec![]), _ => (), }; - let ini = ini.unwrap(); - - let entrypoints = ini - .section(Some("console_scripts")) - .map_or(vec![], |console_scripts| { - console_scripts - .iter() - .map(|(key, val)| EntryPoint::new(key, val)) - .collect() - }); - Some(entrypoints) + let ini = ini?; + + let entrypoints = + ini.section(Some("console_scripts")) + .map_or(Ok(vec![]), |console_scripts| { + console_scripts + .iter() + .map(|(key, val)| EntryPoint::new(key, val)) + .collect() + })?; + Ok(entrypoints) } fn hash_of_file_sha256_base64(path: &Path) -> Result { @@ -369,7 +382,7 @@ fn _hash_of_file_sha256(path: &Path) -> Result> { fn _hash_of_reader_sha256(mut reader: impl std::io::Read) -> impl AsRef<[u8]> { use sha2::Digest; let mut hasher = sha2::Sha256::new(); - std::io::copy(&mut reader, &mut hasher).unwrap(); + std::io::copy(&mut reader, &mut hasher).expect("hashing can't fail"); hasher.finalize() } diff --git a/src/python/detection.rs b/src/python/detection.rs index 05c9fd4..b55af6e 100644 --- a/src/python/detection.rs +++ b/src/python/detection.rs @@ -1,4 +1,4 @@ -use eyre::{bail, eyre, WrapErr}; +use eyre::{ensure, eyre, WrapErr}; use itertools::Itertools; use std::path::PathBuf as StdPathBuf; @@ -12,17 +12,16 @@ pub(crate) fn detect(python: &str) -> Result { // If `python` is definitely a path, use it, if it exists. // For a path like 'foo/bar', .ancestors() returns "foo/bar", "foo", "" if path.is_absolute() || path.ancestors().take(3).count() == 3 { - if path.exists() { - return Ok(path.to_owned()); - } else { - bail!("python not found at {path}"); - } + ensure!(path.exists(), "python not found at {path}"); + return Ok(path.to_owned()); } let version_pattern = lazy_regex::regex!(r"^(\d)(\.(\d+))?$"); if let Some(captures) = version_pattern.captures(python) { - let major = captures[1].parse().unwrap(); - let minor = captures.get(3).map(|n| n.as_str().parse().unwrap()); + let major = captures[1].parse().expect("major version parse failure"); + let minor = captures + .get(3) + .map(|n| n.as_str().parse().expect("minor version parse failure")); return find_python_by_version(major, minor); } diff --git a/src/venv.rs b/src/venv.rs index 584bcc5..26c01ed 100644 --- a/src/venv.rs +++ b/src/venv.rs @@ -271,8 +271,12 @@ impl Virtpy { use_pep517: bool, ) -> Result<()> { let file_hash = DistributionHash::from_file(file)?; - let distribution = - Distribution::from_package_name(file.file_name().unwrap(), file_hash).unwrap(); + let distribution = Distribution::from_package_name( + file.file_name() + .ok_or_else(|| eyre!("path has no file name: {file}"))?, + file_hash, + ) + .wrap_err("failed to build Distribution from package name")?; if !wheel_is_already_registered(ctx, &distribution)? { install_and_register_distribution_from_file( @@ -510,7 +514,7 @@ pub(crate) enum VirtpyError { fn virtpy_link_status(virtpy_link_path: &Path) -> Result { let supposed_location = virtpy_link_supposed_location(virtpy_link_path) .wrap_err("failed to read original location of virtpy")?; - if !paths_match(virtpy_link_path.as_ref(), supposed_location.as_ref()).unwrap() { + if !paths_match(virtpy_link_path.as_ref(), supposed_location.as_ref())? { return Err(VirtpyError::WrongLocation { should: supposed_location, actual: virtpy_link_path.to_owned(), @@ -628,7 +632,7 @@ fn link_file_into_virtpy( filehash: &FileHash, dest: PathBuf, distribution: &Distribution, -) { +) -> Result<()> { let src = ctx.proj_dirs.package_file(filehash); fs_err::hard_link(&src, &dest) .or_else(|err| { @@ -646,7 +650,6 @@ fn link_file_into_virtpy( } }) .wrap_err_with(|| eyre!("distribution {}", distribution.name_and_version())) - .unwrap(); } fn link_files_from_record_into_virtpy( @@ -665,26 +668,29 @@ fn link_files_from_record_into_virtpy( // => use backing let paths = virtpy.virtpy_backing().install_paths()?; - let ensure_dir_exists = |dest: &Path| { - let dir = dest.parent().unwrap(); + let ensure_dir_exists = |dest: &Path| -> Result<()> { + let dir = dest + .parent() + .ok_or_else(|| eyre!("path has no parent: {dest}"))?; // TODO: assert we're still in the virtpy - fs_err::create_dir_all(dir).unwrap(); + fs_err::create_dir_all(dir)?; + Ok(()) }; for record in &mut record.files { match record.path.strip_prefix(&data_dir) { Ok(data_dir_subpath) => { let mut iter = data_dir_subpath.iter(); - let subdir = iter.next().unwrap(); + let subdir = iter.next().expect("path must have base dir"); let subpath = iter.as_path(); let base_path = &paths.0[subdir]; let dest = base_path.join(subpath); - ensure_dir_exists(&dest); + ensure_dir_exists(&dest)?; let is_executable = subdir == "scripts"; record.path = relative_path(site_packages, &dest)?; if !is_executable { - link_file_into_virtpy(ctx, &record.hash, dest, distribution); + link_file_into_virtpy(ctx, &record.hash, dest, distribution)?; } else { let src = ctx.proj_dirs.package_file(&record.hash); @@ -720,14 +726,14 @@ fn link_files_from_record_into_virtpy( &virtpy.site_packages(), )?; } else { - link_file_into_virtpy(ctx, &record.hash, dest, distribution); + link_file_into_virtpy(ctx, &record.hash, dest, distribution)?; } } } Err(_) => { let dest = site_packages.join(&record.path); - ensure_dir_exists(&dest); - link_file_into_virtpy(ctx, &record.hash, dest, distribution); + ensure_dir_exists(&dest)?; + link_file_into_virtpy(ctx, &record.hash, dest, distribution)?; } }; } @@ -840,7 +846,7 @@ fn install_executables( virtpy: &Virtpy, wheel_record: &mut WheelRecord, ) -> Result<(), color_eyre::Report> { - let entrypoints = stored_distrib.entrypoints(ctx).unwrap_or_default(); + let entrypoints = stored_distrib.entrypoints(ctx)?; for entrypoint in entrypoints { let executables_path = virtpy.executables(); let err = || eyre!("failed to install executable {}", entrypoint.name); @@ -950,7 +956,7 @@ pub(crate) fn virtpy_status(virtpy_path: &Path) -> Result Result Result<()> { let tmp_dir = tempdir::TempDir::new_in(ctx.proj_dirs.tmp(), "virtpy_wheel")?; - let (distrib_path, _wheel_tmp_dir) = match distrib_path.extension().unwrap() { - "whl" => (distrib_path.to_owned(), None), - _ => { + let (distrib_path, _wheel_tmp_dir) = match distrib_path.extension() { + Some("whl") => (distrib_path.to_owned(), None), + Some(_) => { if ctx.options.verbose >= 2 { println!("converting to wheel: {distrib_path}"); } @@ -1124,8 +1130,9 @@ fn install_and_register_distribution_from_file( (wheel_path, Some(tmp_dir)) } + None => bail!("distribution path has no file extension: {distrib_path}"), }; - assert!(distrib_path.extension().unwrap() == "whl"); + assert_eq!(distrib_path.extension(), Some("whl")); crate::python::wheel::unpack_wheel(&distrib_path, tmp_dir.path())?; let install_folder = tmp_dir.utf8_path(); @@ -1196,7 +1203,7 @@ fn generate_pkg_resources_wheel( let tmp_dir_path = tmp_dir.try_utf8_path()?; let wheel_path = find_wheel(tmp_dir_path)?.ok_or_else(|| eyre!("no pkg_resources wheel generated"))?; - let wheel_name = wheel_path.file_name().unwrap(); + let wheel_name = wheel_path.file_name().expect("wheel should have file name"); let target = wheel_dir.join(wheel_name); From f920c3d2d73ca7985c03675de2f30f069529cffa Mon Sep 17 00:00:00 2001 From: Emerentius Date: Tue, 12 Aug 2025 18:45:29 +0200 Subject: [PATCH 2/7] check dir files eagerly for better error handling --- src/internal_store.rs | 16 +++++++++------- src/main.rs | 30 +++++++++++++++--------------- src/venv.rs | 35 ++++++++++++++++++----------------- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/internal_store.rs b/src/internal_store.rs index 73ee0fc..8bc09d0 100644 --- a/src/internal_store.rs +++ b/src/internal_store.rs @@ -264,7 +264,8 @@ impl StoreDependencies { let mut virtpy_dists = VirtpyDists::new(); let mut dist_virtpys: DistVirtpys = ctx .proj_dirs - .installed_distributions() + .installed_distributions()? + .into_iter() .map(|dist| (dist, <_>::default())) .collect(); let mut dist_files = DistFiles::new(); @@ -292,13 +293,14 @@ impl StoreDependencies { continue; }; let distributions: HashSet<_> = distributions_used(&backing) - .collect::>() .wrap_err_with(|| { format!( "can't read packages used by {}", virtpy_link_location(&virtpy_path).unwrap_or(virtpy_path) ) - })?; + })? + .into_iter() + .collect(); for dist in &distributions { dist_virtpys .entry(dist.clone()) @@ -455,11 +457,10 @@ pub(crate) fn print_stats( Ok(()) } -fn distributions_used( - virtpy_dirs: &VirtpyBacking, -) -> impl Iterator> { +fn distributions_used(virtpy_dirs: &VirtpyBacking) -> Result> { virtpy_dirs - .dist_infos() + .dist_infos()? + .into_iter() .filter(|dist_info_path| { // The intention is that only we ourselves install packages into // our venvs but some other tools may just see the venv structure @@ -490,6 +491,7 @@ fn distributions_used( // .map_or(true, |installer| installer.trim() == "virtpy") }) .map(stored_distribution_of_installed_dist) + .collect() } pub(crate) fn stored_distribution_of_installed_dist( diff --git a/src/main.rs b/src/main.rs index 946504b..ae82ce2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -319,22 +319,22 @@ impl ProjectDirs { self.installations().join(format!("{package}.virtpy")) } - fn installed_distributions(&self) -> impl Iterator + '_ { + fn installed_distributions(&self) -> Result> { self.records() - .read_dir() - .into_iter() - .flatten() - .map(|e| e.unwrap()) - .map(|dist_info_entry| StoredDistribution { - distribution: python::Distribution::from_store_name( - dist_info_entry - .path() - .file_name() - .unwrap() - .to_str() - .unwrap(), - ), + .read_dir()? + .map(|dist_info_entry| { + Ok(StoredDistribution { + distribution: python::Distribution::from_store_name( + dist_info_entry? + .path() + .file_name() + .expect("record file must have file name") + .to_str() + .expect("record path must be utf8"), + ), + }) }) + .collect() } // Using a directory in our data directory for temporary files ensures @@ -540,7 +540,7 @@ fn main() -> Result<()> { println!("{}", Virtpy::from_existing(&virtpy)?.global_python()?); } Command::InternalUseOnly(InternalUseOnly::ListPackages { virtpy }) => { - let packages = Virtpy::from_existing(&virtpy)?.installed_distributions_metadata(); + let packages = Virtpy::from_existing(&virtpy)?.installed_distributions_metadata()?; let (successes, _failures): (Vec<_>, Vec<_>) = packages.into_iter().partition_result(); // Print table of package name and version. diff --git a/src/venv.rs b/src/venv.rs index 26c01ed..68ea81a 100644 --- a/src/venv.rs +++ b/src/venv.rs @@ -80,24 +80,23 @@ pub(crate) trait VirtpyPaths { fn dist_info(&self, package: &str) -> Result { let package = &normalized_distribution_name_for_wheel(package); - self.dist_infos() + self.dist_infos()? + .into_iter() .find(|path| dist_info_matches_package(path, package)) .ok_or_else(|| eyre!("failed to find dist-info for {package}")) } - fn dist_infos(&self) -> Box> { - Box::new( - self.site_packages() - .read_dir() - .unwrap() - .map(Result::unwrap) - .map(|dir_entry| dir_entry.path()) - .map(<_>::into_utf8_pathbuf) - .filter(|path| { - path.file_name() - .is_some_and(|fn_| fn_.ends_with(".dist-info")) - }), - ) + fn dist_infos(&self) -> Result> { + self.site_packages() + .read_dir()? + .map(|dir_entry| Ok(dir_entry?.path())) + .map(|path| path.map(|p| p.into_utf8_pathbuf())) + .filter_ok(|path| { + path.file_name() + .expect("site package entries must have file name") + .ends_with(".dist-info") + }) + .collect() } fn site_packages(&self) -> PathBuf { @@ -121,13 +120,15 @@ pub(crate) trait VirtpyPaths { }) } - fn installed_distributions_metadata(&self) -> Vec> { - self.dist_infos() + fn installed_distributions_metadata(&self) -> Result>> { + Ok(self + .dist_infos()? + .into_iter() .map(|dist_info| { let metadata = fs_err::read_to_string(dist_info.join("METADATA"))?; DistributionMetadata::from_str(&metadata) }) - .collect() + .collect()) } } From 572603579e0ae390947296cef93f6e321735e771 Mon Sep 17 00:00:00 2001 From: Emerentius Date: Tue, 12 Aug 2025 18:46:11 +0200 Subject: [PATCH 3/7] better error handling in parsers --- src/python.rs | 13 +++++++------ src/venv.rs | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/python.rs b/src/python.rs index e903592..ac70d24 100644 --- a/src/python.rs +++ b/src/python.rs @@ -150,16 +150,17 @@ impl EntryPoint { // # One which depends on extras: // foobar = foomod:main_bar [bar,baz] pub(crate) fn new(key: &str, value: &str) -> Result { - // TODO: allow spaces in positions allowed by spec // TODO: support extras - let mut it = value.split(':'); - let module = it.next().unwrap().to_owned(); - let qualname = it.next().unwrap().to_owned(); + let (_, module, qualname, _extras) = lazy_regex::regex_captures!( + r"([^:\s]+)\s*:\s*([^\s]+)(?: \[\s*([^\]]*)\s*\]\s*)?", + value + ) + .ok_or_else(|| eyre!("console script for {key} couldn't be parsed: {value}"))?; Ok(EntryPoint { name: key.to_owned(), - module, - qualname, + module: module.to_owned(), + qualname: qualname.to_owned(), }) } diff --git a/src/venv.rs b/src/venv.rs index 68ea81a..ddcc8c9 100644 --- a/src/venv.rs +++ b/src/venv.rs @@ -329,7 +329,7 @@ impl Virtpy { } dist_infos.retain(|name| { - let dist = name.split('-').next().unwrap(); + let dist = name.split('-').next().expect("first part always exists"); // It should already be in normalized form as far as I know, // but of course that's not always the case. let dist = normalized_distribution_name_for_wheel(dist); From dbabf6626213bb66c52a0a867f7576bd41382398 Mon Sep 17 00:00:00 2001 From: Emerentius Date: Tue, 12 Aug 2025 18:46:22 +0200 Subject: [PATCH 4/7] forbid unwrap() --- src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.rs b/src/main.rs index ae82ce2..85bd199 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +#![cfg_attr(not(test), deny(clippy::unwrap_used))] use camino::{Utf8Path, Utf8PathBuf}; use clap::{ArgAction, Parser, Subcommand}; use eyre::bail; From 0e1911ec4fe2d32b5ec166ac63a1609ffba9cabd Mon Sep 17 00:00:00 2001 From: Emerentius Date: Tue, 12 Aug 2025 18:46:37 +0200 Subject: [PATCH 5/7] poetry: activate package mode --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 5a5d919..86617b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,6 +3,7 @@ name = "virtpy" version = "0.1.0" description = "" authors = ["Emerentius "] +package-mode = false [tool.poetry.dependencies] python = "^3.9" From 475894c71820abe55d8cf54cbda60088df442ad4 Mon Sep 17 00:00:00 2001 From: Emerentius Date: Sat, 22 Nov 2025 23:34:53 +0100 Subject: [PATCH 6/7] add additional info to some unwraps --- src/main.rs | 2 +- src/python.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 85bd199..1378b3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -355,7 +355,7 @@ fn package_info_from_dist_info_dirname(dirname: &str) -> (&str, &str) { r"^([a-zA-Z_\.][a-zA-Z0-9_\.]*)-(\d*!.*|\d*\..*)\.dist-info$", dirname ) - .unwrap(); + .unwrap_or_else(|| panic!("directory name doesn't match expected pattern: {}", dirname)); (distrib_name, version) } diff --git a/src/python.rs b/src/python.rs index ac70d24..45976bc 100644 --- a/src/python.rs +++ b/src/python.rs @@ -229,7 +229,7 @@ fn _generate_windows_executable( static LAUNCHER_CODE: &[u8] = include_bytes!("../windows_exe_wrappers/t64.exe"); let mut zip_writer = zip::ZipWriter::new(std::io::Cursor::new(Vec::::new())); zip_writer.start_file("__main__.py", zip::write::FileOptions::default())?; - write!(&mut zip_writer, "{code}").unwrap(); + write!(&mut zip_writer, "{code}").expect("failed to zip code for executable"); let mut wrapper = LAUNCHER_CODE.to_vec(); wrapper.extend(shebang.as_bytes()); wrapper.extend(b".exe"); @@ -280,7 +280,8 @@ pub(crate) struct Distribution { impl Distribution { pub(crate) fn from_store_name(store_name: &str) -> Self { let (_, name, version, hash) = - lazy_regex::regex_captures!(r"([^,]+),([^,]+),([^,]+)", store_name).unwrap(); + lazy_regex::regex_captures!(r"([^,]+),([^,]+),([^,]+)", store_name) + .expect("failed to get Distribution data from internal store file name"); Self { name: name.to_owned(), From 2c742b0f3481462c72a06e209ae14d4956e5ed2a Mon Sep 17 00:00:00 2001 From: Emerentius Date: Sun, 23 Nov 2025 01:23:20 +0100 Subject: [PATCH 7/7] fix clippy lints --- src/main.rs | 2 +- src/venv.rs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1378b3f..36a2004 100644 --- a/src/main.rs +++ b/src/main.rs @@ -365,7 +365,7 @@ fn path_to_virtpy(path_override: &Option) -> &Path { .unwrap_or_else(|| DEFAULT_VIRTPY_PATH.as_ref()) } -fn shim_info(ctx: &Ctx) -> Result { +fn shim_info(ctx: &Ctx) -> Result> { Ok(ShimInfo { proj_dirs: &ctx.proj_dirs, virtpy_exe: PathBuf::try_from( diff --git a/src/venv.rs b/src/venv.rs index ddcc8c9..c3c96d7 100644 --- a/src/venv.rs +++ b/src/venv.rs @@ -978,9 +978,7 @@ pub(crate) fn virtpy_status(virtpy_path: &Path) -> Result