diff --git a/crates/erg_common/python_util.rs b/crates/erg_common/python_util.rs index c6b44861c..e3f93c803 100644 --- a/crates/erg_common/python_util.rs +++ b/crates/erg_common/python_util.rs @@ -608,23 +608,66 @@ fn get_poetry_virtualenv_path() -> Option { .then_some(path.trim().to_string()) } +fn get_uv_python_venv_path() -> Option { + let out = if cfg!(windows) { + Command::new("cmd") + .arg("/C") + .arg("uv") + .arg("python") + .arg("find") + .output() + .ok()? + } else { + Command::new("sh") + .arg("-c") + .arg("uv") + .arg("python") + .arg("find") + .output() + .ok()? + }; + String::from_utf8(out.stdout) + .ok() + .map(|s| s.trim().to_string()) +} + pub fn opt_which_python() -> Result { if let Some(path) = which_python_from_toml() { return Ok(path); } - if Path::new("./.venv/bin/python").is_file() { - let path = canonicalize("./.venv/bin/python").unwrap(); - return Ok(path.to_string_lossy().to_string()); - } else if let Some(path) = get_poetry_virtualenv_path() { + if let Some(path) = get_poetry_virtualenv_path() { return Ok(format!("{path}/bin/python")); + } else if let Some(path) = get_uv_python_venv_path() { + return Ok(path); } - let (cmd, python) = if cfg!(windows) { - ("where", "python") + + let path = if cfg!(windows) { + r".venv\Scripts\python.exe" } else { - ("which", "python3") + ".venv/bin/python" }; - let Ok(out) = Command::new(cmd).arg(python).output() else { - return Err(format!("{}: {python} not found", fn_name_full!())); + if Path::new(&path).is_file() { + let path = canonicalize(&path).unwrap(); + return Ok(path.to_string_lossy().to_string()); + } + let out = if cfg!(windows) { + Command::new("cmd") + .arg("/C") + .arg("where") + .arg("python") + .output() + } else { + Command::new("sh") + .arg("-c") + .arg("which") + .arg("python3") + .output() + }; + let Ok(out) = out else { + return Err(format!( + "{}: failed to commnunicate with Python", + fn_name_full!() + )); }; let Ok(res) = String::from_utf8(out.stdout) else { return Err(format!( @@ -634,7 +677,7 @@ pub fn opt_which_python() -> Result { }; let res = res.split('\n').next().unwrap_or("").replace('\r', ""); if res.is_empty() { - return Err(format!("{}: {python} not found", fn_name_full!())); + return Err(format!("{}: python not found", fn_name_full!())); } else if res.contains("pyenv") && cfg!(windows) { // because pyenv-win does not support `-c` option return Err("cannot use pyenv-win".into()); diff --git a/tests/test.rs b/tests/test.rs index 0d2fef90e..426c1b0d0 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -183,12 +183,7 @@ fn exec_fib() -> Result<(), ()> { #[test] fn exec_helloworld() -> Result<(), ()> { - // HACK: When running the test with Windows, the exit code is 1 (the cause is unknown) - if cfg!(windows) && env_python_version().unwrap().minor >= Some(8) { - expect_end_with("examples/helloworld.er", 0, 1) - } else { - expect_success("examples/helloworld.er", 0) - } + expect_success("examples/helloworld.er", 0) } #[test]