fix(pip3): prefer python when available (#471)

This commit is contained in:
SteveLauC
2023-06-23 17:02:58 +08:00
committed by GitHub
parent d7709490ce
commit 57546a07fc
2 changed files with 50 additions and 5 deletions

View File

@@ -15,7 +15,7 @@ use crate::command::{CommandExt, Utf8Output};
use crate::execution_context::ExecutionContext;
use crate::executor::ExecutorOutput;
use crate::terminal::{print_separator, shell};
use crate::utils::{self, require, require_option, which, PathExt, REQUIRE_SUDO};
use crate::utils::{self, check_is_python_2_or_shim, require, require_option, which, PathExt, REQUIRE_SUDO};
use crate::Step;
use crate::HOME_DIR;
use crate::{
@@ -368,7 +368,18 @@ pub fn run_mamba_update(ctx: &ExecutionContext) -> Result<()> {
}
pub fn run_pip3_update(ctx: &ExecutionContext) -> Result<()> {
let python3 = require("python3")?;
let py = require("python").and_then(check_is_python_2_or_shim);
let py3 = require("python3").and_then(check_is_python_2_or_shim);
let python3 = match (py, py3) {
// prefer `python` if it is available and is a valid Python 3.
(Ok(py), _) => py,
(Err(_), Ok(py3)) => py3,
(Err(py_err), Err(py3_err)) => {
return Err(SkipStep(format!("Skip due to following reasons: {} {}", py_err, py3_err)).into());
}
};
Command::new(&python3)
.args(["-m", "pip"])
.output_checked_utf8()

View File

@@ -2,10 +2,12 @@ use std::env;
use std::ffi::OsStr;
use std::fmt::Debug;
use std::path::{Path, PathBuf};
use std::process::Command;
use color_eyre::eyre::Result;
use tracing::{debug, error};
use crate::command::CommandExt;
use crate::error::SkipStep;
pub trait PathExt
@@ -152,9 +154,6 @@ pub fn hostname() -> Result<String> {
#[cfg(target_family = "windows")]
pub fn hostname() -> Result<String> {
use crate::command::CommandExt;
use std::process::Command;
Command::new("hostname")
.output_checked_utf8()
.map_err(|err| SkipStep(format!("Failed to get hostname: {err}")).into())
@@ -217,3 +216,38 @@ pub mod merge_strategies {
// Skip causes
// TODO: Put them in a better place when we have more of them
pub const REQUIRE_SUDO: &str = "Require sudo or counterpart but not found, skip";
/// Return `Err(SkipStep)` if `python` is a Python 2 or shim.
///
/// # Shim
/// On Windows, if you install `python` through `winget`, an actual `python`
/// is installed as well as a `python3` shim. Shim is invokable, but when you
/// execute it, the Microsoft App Store will be launched instead of a Python
/// shell.
///
/// We do this check through `python -V`, a shim will just give `Python` with
/// no version number.
pub fn check_is_python_2_or_shim(python: PathBuf) -> Result<PathBuf> {
let output = Command::new(&python).arg("-V").output_checked_utf8()?;
// "Python x.x.x\n"
let stdout = output.stdout;
// ["Python"] or ["Python", "x.x.x"], the newline char is trimmed.
let mut split = stdout.split_whitespace();
if let Some(version) = split.nth(1) {
let major_version = version
.split('.')
.next()
.expect("Should have a major version number")
.parse::<u32>()
.expect("Major version should be a valid number");
if major_version == 2 {
return Err(SkipStep(format!("{} is a Python 2, skip.", python.display())).into());
}
} else {
// No version number, is a shim
return Err(SkipStep(format!("{} is a Python shim, skip.", python.display())).into());
}
Ok(python)
}