Remove all unwrap calls from the resolver (#5426)

This commit is contained in:
Charlie Marsh 2023-06-28 14:06:17 -04:00 committed by GitHub
parent 4d90a5a9bc
commit 864f50a3a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 50 deletions

View file

@ -55,14 +55,7 @@ pub(crate) fn find(dir_path: &Path, exclusions: &[&Path]) -> BTreeMap<String, Im
let file_stem = path.file_stem().and_then(OsStr::to_str); let file_stem = path.file_stem().and_then(OsStr::to_str);
let is_native_lib = false; let is_native_lib = false;
(file_stem, is_native_lib) (file_stem, is_native_lib)
} else if native_module::is_native_module_file_extension(extension) } else if native_module::is_native_module_file_extension(extension) {
&& !path
.with_extension(format!("{}.py", extension.to_str().unwrap()))
.exists()
&& !path
.with_extension(format!("{}.pyi", extension.to_str().unwrap()))
.exists()
{
// E.g., `foo.abi3.so` becomes `foo`. // E.g., `foo.abi3.so` becomes `foo`.
let file_stem = native_module::native_module_name(&path); let file_stem = native_module::native_module_name(&path);
let is_native_lib = true; let is_native_lib = true;

View file

@ -1,7 +1,7 @@
//! Support for native Python extension modules. //! Support for native Python extension modules.
use std::ffi::OsStr; use std::ffi::OsStr;
use std::path::Path; use std::path::{Path, PathBuf};
/// Returns `true` if the given file extension is that of a native module. /// Returns `true` if the given file extension is that of a native module.
pub(crate) fn is_native_module_file_extension(file_extension: &OsStr) -> bool { pub(crate) fn is_native_module_file_extension(file_extension: &OsStr) -> bool {
@ -36,6 +36,18 @@ pub(crate) fn is_native_module_file_name(module_name: &str, file_name: &Path) ->
native_module_name(file_name) == Some(module_name) native_module_name(file_name) == Some(module_name)
} }
/// Find the native module within the namespace package at the given path.
pub(crate) fn find_native_module(dir_path: &Path) -> Option<PathBuf> {
let module_name = dir_path.file_name()?.to_str()?;
dir_path
.read_dir()
.ok()?
.flatten()
.filter(|entry| entry.file_type().map_or(false, |ft| ft.is_file()))
.map(|entry| entry.path())
.find(|path| is_native_module_file_name(module_name, path))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::path::PathBuf; use std::path::PathBuf;

View file

@ -1,7 +1,6 @@
//! Resolves Python imports to their corresponding files on disk. //! Resolves Python imports to their corresponding files on disk.
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ffi::OsStr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use log::debug; use log::debug;
@ -139,21 +138,10 @@ fn resolve_module_descriptor(
} else { } else {
if allow_native_lib && dir_path.is_dir() { if allow_native_lib && dir_path.is_dir() {
// We couldn't find a `.py[i]` file; search for a native library. // We couldn't find a `.py[i]` file; search for a native library.
if let Some(module_name) = dir_path.file_name().and_then(OsStr::to_str) { if let Some(native_lib_path) = native_module::find_native_module(&dir_path) {
if let Some(native_lib_path) = dir_path debug!("Resolved import with file: {native_lib_path:?}");
.read_dir() is_native_lib = true;
.unwrap() resolved_paths.push(native_lib_path);
.flatten()
.filter(|entry| entry.file_type().map_or(false, |ft| ft.is_file()))
.map(|entry| entry.path())
.find(|path| {
native_module::is_native_module_file_name(module_name, path)
})
{
debug!("Resolved import with file: {native_lib_path:?}");
is_native_lib = true;
resolved_paths.push(native_lib_path);
}
} }
} }

View file

@ -2,8 +2,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::{fs, io};
use log::debug; use log::debug;
@ -94,9 +94,9 @@ fn find_site_packages_path(
Some(default_dir.join(SITE_PACKAGES)) Some(default_dir.join(SITE_PACKAGES))
} }
fn find_paths_from_pth_files(parent_dir: &Path) -> Vec<PathBuf> { fn find_paths_from_pth_files(parent_dir: &Path) -> io::Result<impl Iterator<Item = PathBuf> + '_> {
fs::read_dir(parent_dir) Ok(parent_dir
.unwrap() .read_dir()?
.flatten() .flatten()
.filter(|entry| { .filter(|entry| {
// Collect all *.pth files. // Collect all *.pth files.
@ -130,8 +130,7 @@ fn find_paths_from_pth_files(parent_dir: &Path) -> Vec<PathBuf> {
} }
} }
None None
}) }))
.collect()
} }
/// Find the Python search paths for the given virtual environment. /// Find the Python search paths for the given virtual environment.
@ -144,7 +143,9 @@ fn find_python_search_paths<Host: host::Host>(config: &Config, host: &Host) -> V
let lib_path = venv_path.join(venv).join(lib_name); let lib_path = venv_path.join(venv).join(lib_name);
if let Some(site_packages_path) = find_site_packages_path(&lib_path, None) { if let Some(site_packages_path) = find_site_packages_path(&lib_path, None) {
// Add paths from any `.pth` files in each of the `site-packages` directories. // Add paths from any `.pth` files in each of the `site-packages` directories.
found_paths.extend(find_paths_from_pth_files(&site_packages_path)); if let Ok(pth_paths) = find_paths_from_pth_files(&site_packages_path) {
found_paths.extend(pth_paths);
}
// Add the `site-packages` directory to the search path. // Add the `site-packages` directory to the search path.
found_paths.push(site_packages_path); found_paths.push(site_packages_path);
@ -212,45 +213,48 @@ fn typeshed_subdirectory<Host: host::Host>(
/// Generate a map from PyPI-registered package name to a list of paths /// Generate a map from PyPI-registered package name to a list of paths
/// containing the package's stubs. /// containing the package's stubs.
fn build_typeshed_third_party_package_map(third_party_dir: &Path) -> HashMap<String, Vec<PathBuf>> { fn build_typeshed_third_party_package_map(
third_party_dir: &Path,
) -> io::Result<HashMap<String, Vec<PathBuf>>> {
let mut package_map = HashMap::new(); let mut package_map = HashMap::new();
// Iterate over every directory. // Iterate over every directory.
for outer_entry in fs::read_dir(third_party_dir).unwrap() { for outer_entry in fs::read_dir(third_party_dir)? {
let outer_entry = outer_entry.unwrap(); let outer_entry = outer_entry?;
if outer_entry.file_type().unwrap().is_dir() { if outer_entry.file_type()?.is_dir() {
// Iterate over any subdirectory children. // Iterate over any subdirectory children.
for inner_entry in fs::read_dir(outer_entry.path()).unwrap() { for inner_entry in fs::read_dir(outer_entry.path())? {
let inner_entry = inner_entry.unwrap(); let inner_entry = inner_entry?;
if inner_entry.file_type().unwrap().is_dir() { if inner_entry.file_type()?.is_dir() {
package_map package_map
.entry(inner_entry.file_name().to_string_lossy().to_string()) .entry(inner_entry.file_name().to_string_lossy().to_string())
.or_insert_with(Vec::new) .or_insert_with(Vec::new)
.push(outer_entry.path()); .push(outer_entry.path());
} else if inner_entry.file_type().unwrap().is_file() { } else if inner_entry.file_type()?.is_file() {
if inner_entry if inner_entry
.path() .path()
.extension() .extension()
.map_or(false, |extension| extension == "pyi") .map_or(false, |extension| extension == "pyi")
{ {
let stripped_file_name = inner_entry if let Some(stripped_file_name) = inner_entry
.path() .path()
.file_stem() .file_stem()
.unwrap() .and_then(std::ffi::OsStr::to_str)
.to_string_lossy() .map(std::string::ToString::to_string)
.to_string(); {
package_map package_map
.entry(stripped_file_name) .entry(stripped_file_name)
.or_insert_with(Vec::new) .or_insert_with(Vec::new)
.push(outer_entry.path()); .push(outer_entry.path());
}
} }
} }
} }
} }
} }
package_map Ok(package_map)
} }
/// Determine the current `typeshed` subdirectory for a third-party package. /// Determine the current `typeshed` subdirectory for a third-party package.
@ -260,7 +264,7 @@ pub(crate) fn third_party_typeshed_package_paths<Host: host::Host>(
host: &Host, host: &Host,
) -> Option<Vec<PathBuf>> { ) -> Option<Vec<PathBuf>> {
let typeshed_path = typeshed_subdirectory(false, config, host)?; let typeshed_path = typeshed_subdirectory(false, config, host)?;
let package_paths = build_typeshed_third_party_package_map(&typeshed_path); let package_paths = build_typeshed_third_party_package_map(&typeshed_path).ok()?;
let first_name_part = module_descriptor.name_parts.first().map(String::as_str)?; let first_name_part = module_descriptor.name_parts.first().map(String::as_str)?;
package_paths.get(first_name_part).cloned() package_paths.get(first_name_part).cloned()
} }