diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 6c475650..835f1e82 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -8,8 +8,8 @@ on: - release* jobs: - unit-tests: - name: Unit Tests + tests: + name: Tests runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -45,7 +45,7 @@ jobs: targets: ${{ matrix.target }} - name: Cargo Fetch - run: cargo fetch + run: cargo fetch - name: Run Tests run: cargo test --frozen --all-features diff --git a/crates/pet-conda/src/conda_rc.rs b/crates/pet-conda/src/conda_rc.rs index 4e7f6689..bac53b35 100644 --- a/crates/pet-conda/src/conda_rc.rs +++ b/crates/pet-conda/src/conda_rc.rs @@ -24,7 +24,7 @@ fn get_conda_rc_search_paths(environment: &CondaEnvironmentVariables) -> Vec Vec Vec { - let mut search_paths: Vec = vec![ + let mut search_paths: Vec = [ "/etc/conda/.condarc", "/etc/conda/condarc", "/etc/conda/condarc.d", @@ -70,13 +70,13 @@ fn get_conda_rc_search_paths(environment: &CondaEnvironmentVariables) -> Vec Option { continue; } if start_consuming_values { - if line.trim().starts_with("-") { - if let Some(env_dir) = line.splitn(2, '-').nth(1) { + if line.trim().starts_with('-') { + if let Some(env_dir) = line.split_once('-').map(|x| x.1) { // Directories in conda-rc are where `envs` are stored. env_dirs.push(PathBuf::from(env_dir.trim()).join("envs")); } @@ -158,5 +158,5 @@ fn parse_conda_rc(conda_rc: &PathBuf) -> Option { } } } - return Some(Condarc { env_dirs }); + Some(Condarc { env_dirs }) } diff --git a/crates/pet-conda/src/environment_locations.rs b/crates/pet-conda/src/environment_locations.rs index 46859615..85dd823f 100644 --- a/crates/pet-conda/src/environment_locations.rs +++ b/crates/pet-conda/src/environment_locations.rs @@ -15,7 +15,7 @@ use std::{ pub fn get_conda_environment_paths(environment: &CondaEnvironmentVariables) -> Vec { let mut env_paths = get_conda_envs_from_environment_txt(environment) .iter() - .map(|e| PathBuf::from(e)) + .map(PathBuf::from) .collect::>(); let mut env_paths_from_conda_rc = get_conda_environment_paths_from_conda_rc(environment); @@ -83,7 +83,7 @@ pub fn get_conda_environment_paths_from_known_paths( if let Ok(entries) = fs::read_dir(full_path) { for entry in entries.filter_map(Result::ok) { let path = entry.path(); - if let Some(meta) = fs::metadata(&path).ok() { + if let Ok(meta) = fs::metadata(&path) { if meta.is_dir() { env_paths.push(path); } @@ -92,7 +92,7 @@ pub fn get_conda_environment_paths_from_known_paths( } } } - return env_paths; + env_paths } pub fn get_environments(conda_dir: &Path) -> Vec { @@ -179,10 +179,10 @@ pub fn get_known_conda_install_locations(environment: &CondaEnvironmentVariables PathBuf::from("/miniforge3"), ]; if let Some(ref home) = environment.home { - known_paths.push(PathBuf::from(home.clone()).join("anaconda3")); - known_paths.push(PathBuf::from(home.clone()).join("miniconda3")); - known_paths.push(PathBuf::from(home.clone()).join("miniforge3")); - known_paths.push(PathBuf::from(home).join(".conda")); + known_paths.push(home.clone().join("anaconda3")); + known_paths.push(home.clone().join("miniconda3")); + known_paths.push(home.clone().join("miniforge3")); + known_paths.push(home.join(".conda")); } known_paths.append(get_known_conda_locations(environment).as_mut()); known_paths.dedup(); @@ -224,8 +224,8 @@ pub fn get_known_conda_locations(environment: &CondaEnvironmentVariables) -> Vec PathBuf::from("/miniconda3/bin"), ]; if let Some(ref home) = environment.home { - known_paths.push(PathBuf::from(home.clone()).join("anaconda3/bin")); - known_paths.push(PathBuf::from(home).join("miniconda3/bin")); + known_paths.push(home.clone().join("anaconda3/bin")); + known_paths.push(home.join("miniconda3/bin")); } known_paths.append(&mut environment.known_global_search_locations.clone()); known_paths diff --git a/crates/pet-conda/src/environments.rs b/crates/pet-conda/src/environments.rs index b4291e10..ebd1a079 100644 --- a/crates/pet-conda/src/environments.rs +++ b/crates/pet-conda/src/environments.rs @@ -25,7 +25,7 @@ pub struct CondaEnvironment { impl CondaEnvironment { pub fn from(path: &Path, manager: &Option) -> Option { - get_conda_environment_info(&path.into(), manager) + get_conda_environment_info(path, manager) } pub fn to_python_environment( @@ -38,15 +38,15 @@ impl CondaEnvironment { if is_conda_install(&self.prefix) { name = Some("base".to_string()); } else { - name = match self.prefix.file_name() { - Some(name) => Some(name.to_str().unwrap_or_default().to_string()), - None => None, - }; + name = self + .prefix + .file_name() + .map(|name| name.to_str().unwrap_or_default().to_string()); } // if the conda install folder is parent of the env folder, then we can use named activation. // E.g. conda env is = /envs/ // Then we can use `/bin/conda activate -n ` - if !self.prefix.starts_with(&conda_dir) { + if !self.prefix.starts_with(conda_dir) { name = None; } // This is a root env. @@ -62,7 +62,7 @@ impl CondaEnvironment { } } fn get_conda_environment_info( - env_path: &PathBuf, + env_path: &Path, manager: &Option, ) -> Option { if !is_conda_env(env_path) { @@ -74,35 +74,34 @@ fn get_conda_environment_info( Some(manager) => Some(manager.conda_dir.clone()), None => get_conda_installation_used_to_create_conda_env(env_path), }; - let env_path = env_path.clone(); - if let Some(python_binary) = find_executable(&env_path) { - if let Some(package_info) = CondaPackageInfo::from(&env_path, &Package::Python) { - return Some(CondaEnvironment { - prefix: env_path, + if let Some(python_binary) = find_executable(env_path) { + if let Some(package_info) = CondaPackageInfo::from(env_path, &Package::Python) { + Some(CondaEnvironment { + prefix: env_path.into(), executable: Some(python_binary), version: Some(package_info.version), conda_dir: conda_install_folder, arch: package_info.arch, - }); + }) } else { // No python in this environment. - return Some(CondaEnvironment { - prefix: env_path, + Some(CondaEnvironment { + prefix: env_path.into(), executable: Some(python_binary), version: None, conda_dir: conda_install_folder, arch: None, - }); + }) } } else { // No python in this environment. - return Some(CondaEnvironment { - prefix: env_path, + Some(CondaEnvironment { + prefix: env_path.into(), executable: None, version: None, conda_dir: conda_install_folder, arch: None, - }); + }) } } @@ -114,7 +113,7 @@ fn get_conda_environment_info( * Sometimes the cmd line contains the fully qualified path to the conda install folder. * This function returns the path to the conda installation that was used to create the environment. */ -pub fn get_conda_installation_used_to_create_conda_env(env_path: &PathBuf) -> Option { +pub fn get_conda_installation_used_to_create_conda_env(env_path: &Path) -> Option { // Possible the env_path is the root conda install folder. if is_conda_install(env_path) { return Some(env_path.to_path_buf()); @@ -162,9 +161,6 @@ pub fn get_activation_command( manager: &EnvManager, name: Option, ) -> Option> { - if env.executable.is_none() { - return None; - } let conda_exe = manager.executable.to_str().unwrap_or_default().to_string(); if let Some(name) = name { Some(vec![ diff --git a/crates/pet-conda/src/manager.rs b/crates/pet-conda/src/manager.rs index 5078cf95..25d33e1e 100644 --- a/crates/pet-conda/src/manager.rs +++ b/crates/pet-conda/src/manager.rs @@ -68,7 +68,7 @@ fn find_conda_binary_in_known_locations( for location in known_locations { for bin in &conda_bin_names { let conda_path = location.join(bin); - if let Some(metadata) = std::fs::metadata(&conda_path).ok() { + if let Ok(metadata) = std::fs::metadata(&conda_path) { if metadata.is_file() || metadata.is_symlink() { return Some(conda_path); } diff --git a/crates/pet-conda/src/mod.rs b/crates/pet-conda/src/mod.rs index 939946ef..e83731be 100644 --- a/crates/pet-conda/src/mod.rs +++ b/crates/pet-conda/src/mod.rs @@ -52,9 +52,7 @@ fn get_conda_manager_from_env(env_path: &Path) -> Option { // We've been given an env thats been created using the -p flag. // Get the conda install folder from the history file. - if let Some(conda_install_folder) = - get_conda_installation_used_to_create_conda_env(&env_path.to_path_buf()) - { + if let Some(conda_install_folder) = get_conda_installation_used_to_create_conda_env(env_path) { return get_conda_manager(&conda_install_folder); } None @@ -159,7 +157,10 @@ impl Locator for Conda<'_> { return Some(env); } } else { - error!("Unable to find conda Install folder conda install folder env: {:?}", env); + error!( + "Unable to find conda Install folder conda install folder env: {:?}", + env + ); } } } diff --git a/crates/pet-conda/src/package.rs b/crates/pet-conda/src/package.rs index 2feaba86..8eb8166a 100644 --- a/crates/pet-conda/src/package.rs +++ b/crates/pet-conda/src/package.rs @@ -79,7 +79,7 @@ fn get_conda_package_info(path: &Path, name: &Package) -> Option Option Option(&contents).ok() + if let Ok(contents) = read_to_string(&package_path) { + if let Ok(js) = + serde_json::from_str::(&contents) { if let Some(channel) = js.channel { if channel.ends_with("64") { @@ -147,7 +147,7 @@ fn get_conda_package_info(path: &Path, name: &Package) -> Option Option(&contents).ok() + if let Ok(contents) = read_to_string(&path) { + if let Ok(js) = + serde_json::from_str::(&contents) { if let Some(channel) = js.channel { if channel.ends_with("64") { diff --git a/crates/pet-conda/src/utils.rs b/crates/pet-conda/src/utils.rs index 471d08db..28e45c8c 100644 --- a/crates/pet-conda/src/utils.rs +++ b/crates/pet-conda/src/utils.rs @@ -14,7 +14,7 @@ pub fn is_conda_install(path: &Path) -> bool { // conda-meta must exist as this contains a mandatory `history` file. // The root conda installation folder is also a conda environment (its the base environment). pub fn is_conda_env(path: &Path) -> bool { - if let Some(metadata) = fs::metadata(path.join("conda-meta")).ok() { + if let Ok(metadata) = fs::metadata(path.join("conda-meta")) { metadata.is_dir() } else { false diff --git a/crates/pet-conda/tests/unix/anaconda3-2023.03-without-history/envs/.conda_envs_dir_test b/crates/pet-conda/tests/unix/anaconda3-2023.03-without-history/envs/.conda_envs_dir_test new file mode 100644 index 00000000..e69de29b diff --git a/crates/pet-core/src/os_environment.rs b/crates/pet-core/src/os_environment.rs index 56d45bf5..ed5a36ea 100644 --- a/crates/pet-core/src/os_environment.rs +++ b/crates/pet-core/src/os_environment.rs @@ -20,6 +20,11 @@ impl EnvironmentApi { EnvironmentApi {} } } +impl Default for EnvironmentApi { + fn default() -> Self { + Self::new() + } +} #[cfg(windows)] impl Environment for EnvironmentApi { diff --git a/crates/pet-utils/src/executable.rs b/crates/pet-utils/src/executable.rs index a43f3348..ad822575 100644 --- a/crates/pet-utils/src/executable.rs +++ b/crates/pet-utils/src/executable.rs @@ -17,38 +17,26 @@ lazy_static! { #[cfg(windows)] pub fn find_executable(env_path: &Path) -> Option { - for path in vec![ + [ env_path.join("Scripts").join("python.exe"), env_path.join("Scripts").join("python3.exe"), env_path.join("python.exe"), env_path.join("python3.exe"), - ] { - // Should parallelize this - // This is legacy logic, need to see where and why this is used before changing it. - if fs::metadata(&path).is_ok() { - return Some(path); - } - } - None + ] + .into_iter() + .find(|path| fs::metadata(path).is_ok()) } #[cfg(unix)] pub fn find_executable(env_path: &Path) -> Option { - use std::fs; - - for path in vec![ + [ env_path.join("bin").join("python"), env_path.join("bin").join("python3"), env_path.join("python"), env_path.join("python3"), - ] { - // Should parallelize this - // This is legacy logic, need to see where and why this is used before changing it. - if fs::metadata(&path).is_ok() { - return Some(path); - } - } - None + ] + .into_iter() + .find(|path| fs::metadata(path).is_ok()) } pub fn find_executables(env_path: &Path) -> Vec { @@ -81,8 +69,8 @@ pub fn find_executables(env_path: &Path) -> Vec { if let Ok(entries) = fs::read_dir(env_path) { for entry in entries.filter_map(Result::ok) { let file = entry.path(); - if let Some(metadata) = fs::metadata(&file).ok() { - if is_python_executable_name(&file) && metadata.is_file() { + if let Ok(metadata) = fs::metadata(&file) { + if is_python_executable_name(&entry.path()) && metadata.is_file() { python_executables.push(file); } } @@ -122,7 +110,7 @@ pub fn resolve_symlink(exe: &Path) -> Option { // If the file == symlink, then it is not a symlink. // We already have the resolved file, no need to return that again. - if let Some(real_file) = fs::read_link(&exe).ok() { + if let Ok(real_file) = fs::read_link(exe) { if real_file == exe { None } else { diff --git a/crates/pet-utils/src/headers.rs b/crates/pet-utils/src/headers.rs index 54dcc732..a771fd4b 100644 --- a/crates/pet-utils/src/headers.rs +++ b/crates/pet-utils/src/headers.rs @@ -3,10 +3,7 @@ use lazy_static::lazy_static; use regex::Regex; -use std::{ - fs, - path::{Path, PathBuf}, -}; +use std::{fs, path::Path}; lazy_static! { static ref VERSION: Regex = Regex::new(r#"#define\s+PY_VERSION\s+"((\d+\.?)*)"#) @@ -20,7 +17,7 @@ pub struct Headers { impl Headers { pub fn get_version(path: &Path) -> Option { - get_version(&path.to_path_buf()) + get_version(path) } } @@ -30,15 +27,15 @@ impl Headers { // /* Version as a string */ // #define PY_VERSION "3.10.2" // /*--end constants--*/ -pub fn get_version(path: &PathBuf) -> Option { - let mut path = path.clone(); +pub fn get_version(path: &Path) -> Option { + let mut path = path.to_path_buf(); let bin = if cfg!(windows) { "Scripts" } else { "bin" }; if path.ends_with(bin) { path.pop(); } let headers_path = if cfg!(windows) { "Headers" } else { "include" }; let patchlevel_h = path.join(headers_path).join("patchlevel.h"); - let contents = fs::read_to_string(&patchlevel_h).ok()?; + let contents = fs::read_to_string(patchlevel_h).ok()?; for line in contents.lines() { if let Some(captures) = VERSION.captures(line) { if let Some(value) = captures.get(1) { diff --git a/crates/pet-utils/src/pyvenv_cfg.rs b/crates/pet-utils/src/pyvenv_cfg.rs index f5135a3f..7db33595 100644 --- a/crates/pet-utils/src/pyvenv_cfg.rs +++ b/crates/pet-utils/src/pyvenv_cfg.rs @@ -27,15 +27,15 @@ impl PyEnvCfg { Self { version } } pub fn find(path: &Path) -> Option { - if let Some(file) = find(&path.to_path_buf()) { - parse(&file) + if let Some(ref file) = find(path) { + parse(file) } else { None } } } -fn find(path: &PathBuf) -> Option { +fn find(path: &Path) -> Option { // env // |__ pyvenv.cfg <--- check if this file exists // |__ bin or Scripts @@ -72,7 +72,7 @@ fn find(path: &PathBuf) -> Option { } fn parse(file: &Path) -> Option { - let contents = fs::read_to_string(&file).ok()?; + let contents = fs::read_to_string(file).ok()?; for line in contents.lines() { if !line.contains("version") { continue; diff --git a/crates/pet-utils/tests/executable_test.rs b/crates/pet-utils/tests/executable_test.rs index 6a771a86..7b51dcad 100644 --- a/crates/pet-utils/tests/executable_test.rs +++ b/crates/pet-utils/tests/executable_test.rs @@ -7,6 +7,7 @@ use std::path::PathBuf; use common::resolve_test_path; +#[cfg(unix)] #[test] fn find_executables() { // .venv diff --git a/crates/pet-utils/tests/sys_prefix_test.rs b/crates/pet-utils/tests/sys_prefix_test.rs index 183e939c..64b917dc 100644 --- a/crates/pet-utils/tests/sys_prefix_test.rs +++ b/crates/pet-utils/tests/sys_prefix_test.rs @@ -7,6 +7,7 @@ use std::path::PathBuf; use common::resolve_test_path; +#[cfg(unix)] #[test] fn version_from_sys_prefix() { let path: PathBuf = resolve_test_path(&["unix", "pyvenv_cfg", ".venv"]).into(); @@ -18,6 +19,7 @@ fn version_from_sys_prefix() { assert_eq!(version, "3.12.1"); } +#[cfg(unix)] #[test] fn version_from_sys_prefix_using_version_info_format() { let path: PathBuf = resolve_test_path(&["unix", "pyvenv_cfg", "hatch_env"]).into(); @@ -29,6 +31,7 @@ fn version_from_sys_prefix_using_version_info_format() { assert_eq!(version, "3.9.6.final.0"); } +#[cfg(unix)] #[test] fn no_version_without_pyvenv_cfg_and_without_headers() { let path: PathBuf = @@ -53,6 +56,7 @@ fn no_version_without_pyvenv_cfg_and_without_headers() { assert!(version.is_none()); } +#[cfg(unix)] #[test] fn no_version_for_invalid_paths() { let path: PathBuf = resolve_test_path(&["unix_1234"]).into(); @@ -60,6 +64,7 @@ fn no_version_for_invalid_paths() { assert!(version.is_none()); } +#[cfg(unix)] #[test] fn version_from_header_files() { let path: PathBuf = resolve_test_path(&["unix", "headers", "python3.9.9"]).into(); diff --git a/crates/pet/src/lib.rs b/crates/pet/src/lib.rs index e69de29b..fc36ab24 100644 --- a/crates/pet/src/lib.rs +++ b/crates/pet/src/lib.rs @@ -0,0 +1,2 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License.