From ae223707f3d73d2196c5c0a67804b1c802953987 Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Sun, 25 Feb 2024 21:23:39 +0000 Subject: [PATCH] Use Uv::venv() wherever we create venvs with uv (#768) --- rye/src/sync.rs | 59 ++++++++++++-------------------------------- rye/src/utils/mod.rs | 22 +++++++++++++++++ rye/src/uv.rs | 18 ++++++++++++-- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/rye/src/sync.rs b/rye/src/sync.rs index ec70cfebc9..f4b8cda1e4 100644 --- a/rye/src/sync.rs +++ b/rye/src/sync.rs @@ -20,7 +20,7 @@ use crate::platform::get_toolchain_python_bin; use crate::pyproject::{read_venv_marker, write_venv_marker, ExpandedSources, PyProject}; use crate::sources::py::PythonVersion; use crate::utils::{ - get_venv_python_bin, mark_path_sync_ignore, set_proxy_variables, symlink_dir, CommandOutput, + get_venv_python_bin, set_proxy_variables, symlink_dir, update_venv_sync_marker, CommandOutput, IoPathContext, }; use crate::uv::Uv; @@ -334,19 +334,14 @@ pub fn create_virtualenv( ) -> Result<(), Error> { let py_bin = get_toolchain_python_bin(py_ver)?; - let mut venv_cmd = if Config::current().use_uv() { + if Config::current().use_uv() { // try to kill the empty venv if there is one as uv can't work otherwise. fs::remove_dir(venv).ok(); - let mut venv_cmd = Uv::ensure_exists(output)?.cmd(); - venv_cmd.arg("venv"); - if output == CommandOutput::Verbose { - venv_cmd.arg("--verbose"); - } else { - venv_cmd.arg("-q"); - } - venv_cmd.arg("-p"); - venv_cmd.arg(&py_bin); - venv_cmd + let uv = Uv::ensure_exists(output.quieter())? + .venv(venv, &py_bin, py_ver) + .context("failed to initialize virtualenv")?; + uv.write_marker()?; + uv.sync_marker(); } else { // create the venv folder first so we can manipulate some flags on it. fs::create_dir_all(venv).path_context(venv, "unable to create virtualenv folder")?; @@ -364,24 +359,16 @@ pub fn create_virtualenv( venv_cmd.arg("--no-seed"); venv_cmd.arg("--prompt"); venv_cmd.arg(prompt); - venv_cmd - }; - - venv_cmd.arg("--").arg(venv); - - let status = venv_cmd - .status() - .context("unable to invoke virtualenv command")?; - if !status.success() { - bail!("failed to initialize virtualenv"); - } - - write_venv_marker(venv, py_ver)?; + venv_cmd.arg("--").arg(venv); + let status = venv_cmd + .status() + .context("unable to invoke virtualenv command")?; + if !status.success() { + bail!("failed to initialize virtualenv"); + } - // uv can only do it now - if Config::current().use_uv() { - update_venv_sync_marker(output, venv); - } + write_venv_marker(venv, py_ver)?; + }; // On UNIX systems Python is unable to find the tcl config that is placed // outside of the virtualenv. It also sometimes is entirely unable to find @@ -394,20 +381,6 @@ pub fn create_virtualenv( Ok(()) } -/// Update the cloud synchronization marker for the given path -/// based on the config flag. -fn update_venv_sync_marker(output: CommandOutput, venv_path: &Path) { - if let Err(err) = mark_path_sync_ignore(venv_path, Config::current().venv_mark_sync_ignore()) { - if output != CommandOutput::Quiet && Config::current().venv_mark_sync_ignore() { - warn!( - "unable to mark virtualenv {} ignored for cloud sync: {}", - venv_path.display(), - err - ); - } - } -} - #[cfg(unix)] fn inject_tcl_config(venv: &Path, py_bin: &Path) -> Result<(), Error> { let lib_path = match py_bin diff --git a/rye/src/utils/mod.rs b/rye/src/utils/mod.rs index 0f0e2a15ee..7a9f7fbe32 100644 --- a/rye/src/utils/mod.rs +++ b/rye/src/utils/mod.rs @@ -142,6 +142,14 @@ impl CommandOutput { CommandOutput::Normal } } + + pub fn quieter(self) -> CommandOutput { + match self { + CommandOutput::Normal => CommandOutput::Quiet, + CommandOutput::Verbose => CommandOutput::Normal, + CommandOutput::Quiet => CommandOutput::Quiet, + } + } } /// Given a path checks if that path is executable. @@ -447,6 +455,20 @@ pub struct CopyDirOptions { pub exclude: Vec, } +/// Update the cloud synchronization marker for the given path +/// based on the config flag. +pub fn update_venv_sync_marker(output: CommandOutput, venv_path: &Path) { + if let Err(err) = mark_path_sync_ignore(venv_path, Config::current().venv_mark_sync_ignore()) { + if output != CommandOutput::Quiet && Config::current().venv_mark_sync_ignore() { + warn!( + "unable to mark virtualenv {} ignored for cloud sync: {}", + venv_path.display(), + err + ); + } + } +} + #[test] fn test_quiet_exit_display() { let quiet_exit = QuietExit(0); diff --git a/rye/src/uv.rs b/rye/src/uv.rs index 1cccf0e498..64f12d8c82 100644 --- a/rye/src/uv.rs +++ b/rye/src/uv.rs @@ -4,7 +4,8 @@ use crate::pyproject::write_venv_marker; use crate::sources::py::PythonVersion; use crate::sources::uv::{UvDownload, UvRequest}; use crate::utils::{ - check_checksum, set_proxy_variables, unpack_archive, CommandOutput, IoPathContext, + check_checksum, set_proxy_variables, unpack_archive, update_venv_sync_marker, CommandOutput, + IoPathContext, }; use anyhow::{anyhow, Context, Error}; use std::fs::{self, remove_dir_all}; @@ -132,7 +133,8 @@ impl Uv { py_bin: &Path, version: &PythonVersion, ) -> Result { - self.cmd() + let status = self + .cmd() .arg("venv") .arg("--python") .arg(py_bin) @@ -147,6 +149,13 @@ impl Uv { ) })?; + if !status.success() { + return Err(anyhow!( + "Failed to create self venv using {}. uv exited with status: {}", + py_bin.display(), + status + )); + } Ok(UvWithVenv::new(self.clone(), venv_dir, version)) } } @@ -235,4 +244,9 @@ impl UvWithVenv { .path_context(&tool_version_path, "could not write tool version")?; Ok(()) } + + /// Update the cloud synchronization marker for the given path + pub fn sync_marker(&self) { + update_venv_sync_marker(self.uv.output, &self.venv_path) + } }