From 0a01527d8367a1ddad30643ce8545375d6ee5dca Mon Sep 17 00:00:00 2001 From: Daniel Gafni Date: Fri, 4 Oct 2024 12:48:35 +0200 Subject: [PATCH 1/6] :wrench: add `--install-dir` arg to `uv python` commands --- crates/uv-cli/src/lib.rs | 10 +++++++++ crates/uv-python/src/managed.rs | 2 +- crates/uv/src/commands/python/install.rs | 8 ++++++- crates/uv/src/commands/python/uninstall.rs | 9 +++++++- crates/uv/src/lib.rs | 4 +++- crates/uv/src/settings.rs | 26 ++++++++++++++++++---- docs/reference/cli.md | 6 +++++ 7 files changed, 57 insertions(+), 8 deletions(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 0177af3e7597..539d49efca98 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -3734,6 +3734,11 @@ pub struct PythonListArgs { #[derive(Args)] #[allow(clippy::struct_excessive_bools)] pub struct PythonInstallArgs { + /// The directory where Python will be installed. + /// + #[arg(long, short, env = "UV_PYTHON_INSTALL_DIR")] + pub install_dir: Option, + /// The Python version(s) to install. /// /// If not provided, the requested Python version(s) will be read from the @@ -3755,6 +3760,11 @@ pub struct PythonInstallArgs { #[derive(Args)] #[allow(clippy::struct_excessive_bools)] pub struct PythonUninstallArgs { + /// The directory where Python is installed. + /// + #[arg(long, short, env = "UV_PYTHON_INSTALL_DIR")] + pub install_dir: Option, + /// The Python version(s) to uninstall. /// /// See `uv help python` to view supported request formats. diff --git a/crates/uv-python/src/managed.rs b/crates/uv-python/src/managed.rs index 5c077079d5ec..2a9f8b4c4eba 100644 --- a/crates/uv-python/src/managed.rs +++ b/crates/uv-python/src/managed.rs @@ -66,7 +66,7 @@ pub struct ManagedPythonInstallations { impl ManagedPythonInstallations { /// A directory for Python installations at `root`. - fn from_path(root: impl Into) -> Self { + pub fn from_path(root: impl Into) -> Self { Self { root: root.into() } } diff --git a/crates/uv/src/commands/python/install.rs b/crates/uv/src/commands/python/install.rs index b6df4af36a2e..0934fa029840 100644 --- a/crates/uv/src/commands/python/install.rs +++ b/crates/uv/src/commands/python/install.rs @@ -22,6 +22,7 @@ use crate::printer::Printer; /// Download and install Python versions. pub(crate) async fn install( project_dir: &Path, + install_dir: Option<&Path>, targets: Vec, reinstall: bool, python_downloads: PythonDownloads, @@ -32,7 +33,12 @@ pub(crate) async fn install( ) -> Result { let start = std::time::Instant::now(); - let installations = ManagedPythonInstallations::from_settings()?.init()?; + let installations = if let Some(install_dir) = install_dir { + ManagedPythonInstallations::from_path(install_dir) + } else { + ManagedPythonInstallations::from_settings()? + } + .init()?; let installations_dir = installations.root(); let cache_dir = installations.cache(); let _lock = installations.lock().await?; diff --git a/crates/uv/src/commands/python/uninstall.rs b/crates/uv/src/commands/python/uninstall.rs index 11cd6602c520..2d961d1f52d3 100644 --- a/crates/uv/src/commands/python/uninstall.rs +++ b/crates/uv/src/commands/python/uninstall.rs @@ -14,15 +14,22 @@ use uv_python::PythonRequest; use crate::commands::python::{ChangeEvent, ChangeEventKind}; use crate::commands::{elapsed, ExitStatus}; use crate::printer::Printer; +use std::path::Path; /// Uninstall managed Python versions. pub(crate) async fn uninstall( + install_dir: Option<&Path>, targets: Vec, all: bool, printer: Printer, ) -> Result { - let installations = ManagedPythonInstallations::from_settings()?.init()?; + let installations = if let Some(install_dir) = install_dir { + ManagedPythonInstallations::from_path(install_dir) + } else { + ManagedPythonInstallations::from_settings()?.init()? + }; + let _lock = installations.lock().await?; // Perform the uninstallation. diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index 2392b273fc52..3dcdae1e848d 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -1036,6 +1036,7 @@ async fn run(mut cli: Cli) -> Result { commands::python_install( &project_dir, + args.install_dir.as_deref(), args.targets, args.reinstall, globals.python_downloads, @@ -1053,7 +1054,8 @@ async fn run(mut cli: Cli) -> Result { let args = settings::PythonUninstallSettings::resolve(args, filesystem); show_settings!(args); - commands::python_uninstall(args.targets, args.all, printer).await + commands::python_uninstall(args.install_dir.as_deref(), args.targets, args.all, printer) + .await } Commands::Python(PythonNamespace { command: PythonCommand::Find(args), diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index 829173f26663..fb3dd490c633 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -592,6 +592,7 @@ impl PythonListSettings { #[allow(clippy::struct_excessive_bools)] #[derive(Debug, Clone)] pub(crate) struct PythonInstallSettings { + pub(crate) install_dir: Option, pub(crate) targets: Vec, pub(crate) reinstall: bool, } @@ -600,9 +601,17 @@ impl PythonInstallSettings { /// Resolve the [`PythonInstallSettings`] from the CLI and filesystem configuration. #[allow(clippy::needless_pass_by_value)] pub(crate) fn resolve(args: PythonInstallArgs, _filesystem: Option) -> Self { - let PythonInstallArgs { targets, reinstall } = args; + let PythonInstallArgs { + install_dir, + targets, + reinstall, + } = args; - Self { targets, reinstall } + Self { + install_dir, + targets, + reinstall, + } } } @@ -610,6 +619,7 @@ impl PythonInstallSettings { #[allow(clippy::struct_excessive_bools)] #[derive(Debug, Clone)] pub(crate) struct PythonUninstallSettings { + pub(crate) install_dir: Option, pub(crate) targets: Vec, pub(crate) all: bool, } @@ -621,9 +631,17 @@ impl PythonUninstallSettings { args: PythonUninstallArgs, _filesystem: Option, ) -> Self { - let PythonUninstallArgs { targets, all } = args; + let PythonUninstallArgs { + install_dir, + targets, + all, + } = args; - Self { targets, all } + Self { + install_dir, + targets, + all, + } } } diff --git a/docs/reference/cli.md b/docs/reference/cli.md index b4f4bc5f4870..449d0607f104 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -4200,6 +4200,9 @@ uv python install [OPTIONS] [TARGETS]...
--help, -h

Display the concise help for this command

+
--install-dir, -i install-dir

The directory where Python will be installed

+ +

May also be set with the UV_PYTHON_INSTALL_DIR environment variable.

--native-tls

Whether to load TLS certificates from the platform’s native certificate store.

By default, uv loads certificates from the bundled webpki-roots crate. The webpki-roots are a reliable set of trust roots from Mozilla, and including them in uv improves portability and performance (especially on macOS).

@@ -4677,6 +4680,9 @@ uv python uninstall [OPTIONS] ...
--help, -h

Display the concise help for this command

+
--install-dir, -i install-dir

The directory where Python is installed

+ +

May also be set with the UV_PYTHON_INSTALL_DIR environment variable.

--native-tls

Whether to load TLS certificates from the platform’s native certificate store.

By default, uv loads certificates from the bundled webpki-roots crate. The webpki-roots are a reliable set of trust roots from Mozilla, and including them in uv improves portability and performance (especially on macOS).

From d3e20f6957ee5230153ddfe2bc794dc5299085a0 Mon Sep 17 00:00:00 2001 From: Daniel Gafni Date: Thu, 17 Oct 2024 00:29:17 +0200 Subject: [PATCH 2/6] add install_dir argument to ManagedPythonInstallations::from_settings --- crates/uv-cli/src/lib.rs | 3 +-- crates/uv-python/src/discovery.rs | 2 +- crates/uv-python/src/installation.rs | 2 +- crates/uv-python/src/managed.rs | 17 ++++++++++------- crates/uv/src/commands/python/dir.rs | 2 +- crates/uv/src/commands/python/install.rs | 8 ++------ crates/uv/src/commands/python/uninstall.rs | 8 +++----- crates/uv/tests/it/common/mod.rs | 2 +- crates/uv/tests/it/help.rs | 13 ++++++++++--- crates/uv/tests/it/pip_sync.rs | 14 +++++++++----- 10 files changed, 39 insertions(+), 32 deletions(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 539d49efca98..be9ebc57f537 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -3734,8 +3734,7 @@ pub struct PythonListArgs { #[derive(Args)] #[allow(clippy::struct_excessive_bools)] pub struct PythonInstallArgs { - /// The directory where Python will be installed. - /// + /// The directory to store the Python installation in. #[arg(long, short, env = "UV_PYTHON_INSTALL_DIR")] pub install_dir: Option, diff --git a/crates/uv-python/src/discovery.rs b/crates/uv-python/src/discovery.rs index 549eb3808f86..7772e9f1ddd0 100644 --- a/crates/uv-python/src/discovery.rs +++ b/crates/uv-python/src/discovery.rs @@ -294,7 +294,7 @@ fn python_executables_from_installed<'a>( preference: PythonPreference, ) -> Box> + 'a> { let from_managed_installations = std::iter::once_with(move || { - ManagedPythonInstallations::from_settings() + ManagedPythonInstallations::from_settings(None) .map_err(Error::from) .and_then(|installed_installations| { debug!( diff --git a/crates/uv-python/src/installation.rs b/crates/uv-python/src/installation.rs index 8aec1fc7f994..56ec438e494e 100644 --- a/crates/uv-python/src/installation.rs +++ b/crates/uv-python/src/installation.rs @@ -122,7 +122,7 @@ impl PythonInstallation { cache: &Cache, reporter: Option<&dyn Reporter>, ) -> Result { - let installations = ManagedPythonInstallations::from_settings()?.init()?; + let installations = ManagedPythonInstallations::from_settings(None)?.init()?; let installations_dir = installations.root(); let cache_dir = installations.cache(); let _lock = installations.lock().await?; diff --git a/crates/uv-python/src/managed.rs b/crates/uv-python/src/managed.rs index 2a9f8b4c4eba..561075c76ec7 100644 --- a/crates/uv-python/src/managed.rs +++ b/crates/uv-python/src/managed.rs @@ -66,7 +66,7 @@ pub struct ManagedPythonInstallations { impl ManagedPythonInstallations { /// A directory for Python installations at `root`. - pub fn from_path(root: impl Into) -> Self { + fn from_path(root: impl Into) -> Self { Self { root: root.into() } } @@ -77,11 +77,14 @@ impl ManagedPythonInstallations { } /// Prefer, in order: - /// 1. The specific Python directory specified by the user, i.e., `UV_PYTHON_INSTALL_DIR` - /// 2. A directory in the system-appropriate user-level data directory, e.g., `~/.local/uv/python` - /// 3. A directory in the local data directory, e.g., `./.uv/python` - pub fn from_settings() -> Result { - if let Some(install_dir) = std::env::var_os(EnvVars::UV_PYTHON_INSTALL_DIR) { + /// 1. The specific Python directory directly passed to the `install_dir` argument + /// 2. The specific Python directory specified with the `UV_PYTHON_INSTALL_DIR` environment variable + /// 3. A directory in the system-appropriate user-level data directory, e.g., `~/.local/uv/python` + /// 4. A directory in the local data directory, e.g., `./.uv/python` + pub fn from_settings(install_dir: Option) -> Result { + if install_dir.is_some() { + Ok(Self::from_path(install_dir.unwrap())) + } else if let Some(install_dir) = std::env::var_os(EnvVars::UV_PYTHON_INSTALL_DIR) { Ok(Self::from_path(install_dir)) } else { Ok(Self::from_path( @@ -197,7 +200,7 @@ impl ManagedPythonInstallations { ) -> Result, Error> { let platform_key = platform_key_from_env()?; - let iter = ManagedPythonInstallations::from_settings()? + let iter = ManagedPythonInstallations::from_settings(None)? .find_all()? .filter(move |installation| { installation diff --git a/crates/uv/src/commands/python/dir.rs b/crates/uv/src/commands/python/dir.rs index d83668fe1a03..75711cf3299f 100644 --- a/crates/uv/src/commands/python/dir.rs +++ b/crates/uv/src/commands/python/dir.rs @@ -7,7 +7,7 @@ use uv_python::managed::ManagedPythonInstallations; /// Show the toolchain directory. pub(crate) fn dir() -> anyhow::Result<()> { - let installed_toolchains = ManagedPythonInstallations::from_settings() + let installed_toolchains = ManagedPythonInstallations::from_settings(None) .context("Failed to initialize toolchain settings")?; println!( "{}", diff --git a/crates/uv/src/commands/python/install.rs b/crates/uv/src/commands/python/install.rs index 0934fa029840..1a8f42bf9f47 100644 --- a/crates/uv/src/commands/python/install.rs +++ b/crates/uv/src/commands/python/install.rs @@ -33,12 +33,8 @@ pub(crate) async fn install( ) -> Result { let start = std::time::Instant::now(); - let installations = if let Some(install_dir) = install_dir { - ManagedPythonInstallations::from_path(install_dir) - } else { - ManagedPythonInstallations::from_settings()? - } - .init()?; + let installations = + ManagedPythonInstallations::from_settings(install_dir.map(|p| p.to_path_buf()))?.init()?; let installations_dir = installations.root(); let cache_dir = installations.cache(); let _lock = installations.lock().await?; diff --git a/crates/uv/src/commands/python/uninstall.rs b/crates/uv/src/commands/python/uninstall.rs index 2d961d1f52d3..89dac92d64bf 100644 --- a/crates/uv/src/commands/python/uninstall.rs +++ b/crates/uv/src/commands/python/uninstall.rs @@ -24,11 +24,9 @@ pub(crate) async fn uninstall( printer: Printer, ) -> Result { - let installations = if let Some(install_dir) = install_dir { - ManagedPythonInstallations::from_path(install_dir) - } else { - ManagedPythonInstallations::from_settings()?.init()? - }; + // need to convert install_dir to Option to match the function signature + let installations = + ManagedPythonInstallations::from_settings(install_dir.map(|p| p.to_path_buf()))?.init()?; let _lock = installations.lock().await?; diff --git a/crates/uv/tests/it/common/mod.rs b/crates/uv/tests/it/common/mod.rs index 2d83f2cae9e8..0e5298b2dd0e 100644 --- a/crates/uv/tests/it/common/mod.rs +++ b/crates/uv/tests/it/common/mod.rs @@ -990,7 +990,7 @@ pub fn venv_to_interpreter(venv: &Path) -> PathBuf { /// Get the path to the python interpreter for a specific python version. pub fn get_python(version: &PythonVersion) -> PathBuf { - ManagedPythonInstallations::from_settings() + ManagedPythonInstallations::from_settings(None) .map(|installed_pythons| { installed_pythons .find_version(version) diff --git a/crates/uv/tests/it/help.rs b/crates/uv/tests/it/help.rs index ea6811bfce99..cb3b6e578409 100644 --- a/crates/uv/tests/it/help.rs +++ b/crates/uv/tests/it/help.rs @@ -427,6 +427,11 @@ fn help_subsubcommand() { See `uv help python` to view supported request formats. Options: + -i, --install-dir + The directory where Python will be installed + + [env: UV_PYTHON_INSTALL_DIR=] + -r, --reinstall Reinstall the requested Python version, if it's already installed. @@ -620,7 +625,7 @@ fn help_flag_subcommand() { fn help_flag_subsubcommand() { let context = TestContext::new_with_versions(&[]); - uv_snapshot!(context.filters(), context.command().arg("python").arg("install").arg("--help"), @r###" + uv_snapshot!(context.filters(), context.command().arg("python").arg("install").arg("--help"), @r#" success: true exit_code: 0 ----- stdout ----- @@ -632,7 +637,9 @@ fn help_flag_subsubcommand() { [TARGETS]... The Python version(s) to install Options: - -r, --reinstall Reinstall the requested Python version, if it's already installed + -i, --install-dir The directory where Python will be installed [env: + UV_PYTHON_INSTALL_DIR=] + -r, --reinstall Reinstall the requested Python version, if it's already installed Cache options: -n, --no-cache Avoid reading from or writing to the cache, instead using a temporary @@ -665,7 +672,7 @@ fn help_flag_subsubcommand() { -V, --version Display the uv version ----- stderr ----- - "###); + "#); } #[test] diff --git a/crates/uv/tests/it/pip_sync.rs b/crates/uv/tests/it/pip_sync.rs index 32c01d0f5939..9e640cede661 100644 --- a/crates/uv/tests/it/pip_sync.rs +++ b/crates/uv/tests/it/pip_sync.rs @@ -57,14 +57,18 @@ fn missing_venv() -> Result<()> { requirements.write_str("anyio")?; fs::remove_dir_all(&context.venv)?; - uv_snapshot!(context.filters(), context.pip_sync().arg("requirements.txt"), @r###" - success: false - exit_code: 2 + uv_snapshot!(context.filters(), context.pip_sync().arg("requirements.txt"), @r#" + success: true + exit_code: 0 ----- stdout ----- ----- stderr ----- - error: No virtual environment found; run `uv venv` to create an environment, or pass `--system` to install into a non-virtual environment - "###); + Using Python 3.12.[X] environment at /home/dan/.venv + Resolved 1 package in [TIME] + Prepared 1 package in [TIME] + Installed 1 package in [TIME] + + anyio==4.3.0 + "#); assert!(predicates::path::missing().eval(&context.venv)); From 1601aa01f3f1d592ccf55557b4d871791836b356 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Tue, 10 Dec 2024 09:14:40 -0600 Subject: [PATCH 3/6] Fixups --- crates/uv-python/src/managed.rs | 13 +++++++------ crates/uv/src/commands/python/dir.rs | 2 +- crates/uv/src/commands/python/uninstall.rs | 3 ++- crates/uv/tests/it/help.rs | 13 +++++++------ crates/uv/tests/it/pip_sync.rs | 14 +++++--------- 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/crates/uv-python/src/managed.rs b/crates/uv-python/src/managed.rs index 6e340d887da2..a282cbda6a1e 100644 --- a/crates/uv-python/src/managed.rs +++ b/crates/uv-python/src/managed.rs @@ -107,13 +107,14 @@ impl ManagedPythonInstallations { } /// Prefer, in order: - /// 1. The specific Python directory directly passed to the `install_dir` argument - /// 2. The specific Python directory specified with the `UV_PYTHON_INSTALL_DIR` environment variable - /// 3. A directory in the system-appropriate user-level data directory, e.g., `~/.local/uv/python` - /// 4. A directory in the local data directory, e.g., `./.uv/python` + /// + /// 1. The specific Python directory passed via the `install_dir` argument. + /// 2. The specific Python directory specified with the `UV_PYTHON_INSTALL_DIR` environment variable. + /// 3. A directory in the system-appropriate user-level data directory, e.g., `~/.local/uv/python`. + /// 4. A directory in the local data directory, e.g., `./.uv/python`. pub fn from_settings(install_dir: Option) -> Result { - if install_dir.is_some() { - Ok(Self::from_path(install_dir.unwrap())) + if let Some(install_dir) = install_dir { + Ok(Self::from_path(install_dir)) } else if let Some(install_dir) = std::env::var_os(EnvVars::UV_PYTHON_INSTALL_DIR) { Ok(Self::from_path(install_dir)) } else { diff --git a/crates/uv/src/commands/python/dir.rs b/crates/uv/src/commands/python/dir.rs index 7c6a1b325726..27f469d9af68 100644 --- a/crates/uv/src/commands/python/dir.rs +++ b/crates/uv/src/commands/python/dir.rs @@ -11,7 +11,7 @@ pub(crate) fn dir(bin: bool) -> anyhow::Result<()> { let bin = python_executable_dir()?; println!("{}", bin.simplified_display().cyan()); } else { - let installed_toolchains = ManagedPythonInstallations::from_settings() + let installed_toolchains = ManagedPythonInstallations::from_settings(None) .context("Failed to initialize toolchain settings")?; println!( "{}", diff --git a/crates/uv/src/commands/python/uninstall.rs b/crates/uv/src/commands/python/uninstall.rs index beac88b85dfb..3b69a13f9e8e 100644 --- a/crates/uv/src/commands/python/uninstall.rs +++ b/crates/uv/src/commands/python/uninstall.rs @@ -31,7 +31,8 @@ pub(crate) async fn uninstall( ) -> Result { // need to convert install_dir to Option to match the function signature let installations = - ManagedPythonInstallations::from_settings(install_dir.map(|p| p.to_path_buf()))?.init()?; + ManagedPythonInstallations::from_settings(install_dir.map(std::path::Path::to_path_buf))? + .init()?; let _lock = installations.lock().await?; diff --git a/crates/uv/tests/it/help.rs b/crates/uv/tests/it/help.rs index 88d8ee9705f4..8807effae448 100644 --- a/crates/uv/tests/it/help.rs +++ b/crates/uv/tests/it/help.rs @@ -450,7 +450,7 @@ fn help_subcommand() { fn help_subsubcommand() { let context = TestContext::new_with_versions(&[]); - uv_snapshot!(context.filters(), context.help().arg("python").arg("install"), @r##" + uv_snapshot!(context.filters(), context.help().arg("python").arg("install"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -484,9 +484,10 @@ fn help_subsubcommand() { Options: -i, --install-dir - The directory where Python will be installed + The directory to store the Python installation in [env: UV_PYTHON_INSTALL_DIR=] + --mirror Set the URL to use as the source for downloading Python installations. @@ -677,7 +678,7 @@ fn help_subsubcommand() { ----- stderr ----- - "##); + "###); } #[test] @@ -751,7 +752,7 @@ fn help_flag_subcommand() { fn help_flag_subsubcommand() { let context = TestContext::new_with_versions(&[]); - uv_snapshot!(context.filters(), context.command().arg("python").arg("install").arg("--help"), @r#" + uv_snapshot!(context.filters(), context.command().arg("python").arg("install").arg("--help"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -763,7 +764,7 @@ fn help_flag_subsubcommand() { [TARGETS]... The Python version(s) to install Options: - -i, --install-dir The directory where Python will be installed [env: + -i, --install-dir The directory to store the Python installation in [env: UV_PYTHON_INSTALL_DIR=] --mirror Set the URL to use as the source for downloading Python installations [env: UV_PYTHON_INSTALL_MIRROR=] @@ -815,7 +816,7 @@ fn help_flag_subsubcommand() { Display the uv version ----- stderr ----- - "#); + "###); } #[test] diff --git a/crates/uv/tests/it/pip_sync.rs b/crates/uv/tests/it/pip_sync.rs index c97e98f8a4f3..fa0ac8a5fc4f 100644 --- a/crates/uv/tests/it/pip_sync.rs +++ b/crates/uv/tests/it/pip_sync.rs @@ -56,18 +56,14 @@ fn missing_venv() -> Result<()> { requirements.write_str("anyio")?; fs::remove_dir_all(&context.venv)?; - uv_snapshot!(context.filters(), context.pip_sync().arg("requirements.txt"), @r#" - success: true - exit_code: 0 + uv_snapshot!(context.filters(), context.pip_sync().arg("requirements.txt"), @r###" + success: false + exit_code: 2 ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at /home/dan/.venv - Resolved 1 package in [TIME] - Prepared 1 package in [TIME] - Installed 1 package in [TIME] - + anyio==4.3.0 - "#); + error: No virtual environment found; run `uv venv` to create an environment, or pass `--system` to install into a non-virtual environment + "###); assert!(predicates::path::missing().eval(&context.venv)); From 88d997189abf3ea4f59732fc880b1637b12360a8 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Tue, 10 Dec 2024 09:22:03 -0600 Subject: [PATCH 4/6] Tweak doc --- crates/uv-cli/src/lib.rs | 9 +++++++-- crates/uv/tests/it/help.rs | 8 +++++++- docs/reference/cli.md | 8 ++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 0e1e4d46f57c..658a7ad553ca 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -4251,6 +4251,12 @@ pub struct PythonDirArgs { #[allow(clippy::struct_excessive_bools)] pub struct PythonInstallArgs { /// The directory to store the Python installation in. + /// + /// If provided, `UV_PYTHON_INSTALL_DIR` will need to be set for subsequent operations for + /// uv to discover the Python installation. + /// + /// See `uv python dir` to view the current Python installation directory. Defaults to + /// `~/.local/share/uv/python`. #[arg(long, short, env = "UV_PYTHON_INSTALL_DIR")] pub install_dir: Option, @@ -4314,8 +4320,7 @@ pub struct PythonInstallArgs { #[derive(Args)] #[allow(clippy::struct_excessive_bools)] pub struct PythonUninstallArgs { - /// The directory where Python is installed. - /// + /// The directory where the Python was installed. #[arg(long, short, env = "UV_PYTHON_INSTALL_DIR")] pub install_dir: Option, diff --git a/crates/uv/tests/it/help.rs b/crates/uv/tests/it/help.rs index 8807effae448..de2ed24b0356 100644 --- a/crates/uv/tests/it/help.rs +++ b/crates/uv/tests/it/help.rs @@ -484,7 +484,13 @@ fn help_subsubcommand() { Options: -i, --install-dir - The directory to store the Python installation in + The directory to store the Python installation in. + + If provided, `UV_PYTHON_INSTALL_DIR` will need to be set for subsequent operations for uv + to discover the Python installation. + + See `uv python dir` to view the current Python installation directory. Defaults to + `~/.local/share/uv/python`. [env: UV_PYTHON_INSTALL_DIR=] diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 1b23df2a93e6..c8eca0f4f078 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -4553,7 +4553,11 @@ uv python install [OPTIONS] [TARGETS]...
--help, -h

Display the concise help for this command

-
--install-dir, -i install-dir

The directory to store the Python installation in

+
--install-dir, -i install-dir

The directory to store the Python installation in.

+ +

If provided, UV_PYTHON_INSTALL_DIR will need to be set for subsequent operations for uv to discover the Python installation.

+ +

See uv python dir to view the current Python installation directory. Defaults to ~/.local/share/uv/python.

May also be set with the UV_PYTHON_INSTALL_DIR environment variable.

--mirror mirror

Set the URL to use as the source for downloading Python installations.

@@ -5117,7 +5121,7 @@ uv python uninstall [OPTIONS] ...
--help, -h

Display the concise help for this command

-
--install-dir, -i install-dir

The directory where Python is installed

+
--install-dir, -i install-dir

The directory where the Python was installed

May also be set with the UV_PYTHON_INSTALL_DIR environment variable.

--native-tls

Whether to load TLS certificates from the platform’s native certificate store.

From d1a26940885fa5040e2db3916782259df17b7721 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Tue, 10 Dec 2024 09:23:13 -0600 Subject: [PATCH 5/6] Avoid cast --- crates/uv/src/commands/python/uninstall.rs | 7 ++----- crates/uv/src/lib.rs | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/uv/src/commands/python/uninstall.rs b/crates/uv/src/commands/python/uninstall.rs index 3b69a13f9e8e..1980025ae646 100644 --- a/crates/uv/src/commands/python/uninstall.rs +++ b/crates/uv/src/commands/python/uninstall.rs @@ -23,16 +23,13 @@ use std::path::Path; /// Uninstall managed Python versions. pub(crate) async fn uninstall( - install_dir: Option<&Path>, + install_dir: Option, targets: Vec, all: bool, printer: Printer, ) -> Result { - // need to convert install_dir to Option to match the function signature - let installations = - ManagedPythonInstallations::from_settings(install_dir.map(std::path::Path::to_path_buf))? - .init()?; + let installations = ManagedPythonInstallations::from_settings(install_dir)?.init()?; let _lock = installations.lock().await?; diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index d9a4274df5ce..5cfac3ef7fc0 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -1128,8 +1128,7 @@ async fn run(mut cli: Cli) -> Result { let args = settings::PythonUninstallSettings::resolve(args, filesystem); show_settings!(args); - commands::python_uninstall(args.install_dir.as_deref(), args.targets, args.all, printer) - .await + commands::python_uninstall(args.install_dir, args.targets, args.all, printer).await } Commands::Python(PythonNamespace { command: PythonCommand::Find(args), From f5792ef5af28250c0d73f070c4e1b4f263188b3d Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Tue, 10 Dec 2024 10:54:19 -0600 Subject: [PATCH 6/6] Fix CI --- crates/uv/src/commands/python/uninstall.rs | 1 - crates/uv/tests/it/python_install.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/uv/src/commands/python/uninstall.rs b/crates/uv/src/commands/python/uninstall.rs index 1980025ae646..12556382ec74 100644 --- a/crates/uv/src/commands/python/uninstall.rs +++ b/crates/uv/src/commands/python/uninstall.rs @@ -19,7 +19,6 @@ use crate::commands::python::install::format_executables; use crate::commands::python::{ChangeEvent, ChangeEventKind}; use crate::commands::{elapsed, ExitStatus}; use crate::printer::Printer; -use std::path::Path; /// Uninstall managed Python versions. pub(crate) async fn uninstall( diff --git a/crates/uv/tests/it/python_install.rs b/crates/uv/tests/it/python_install.rs index 5094a0b4209f..68bd0aebc472 100644 --- a/crates/uv/tests/it/python_install.rs +++ b/crates/uv/tests/it/python_install.rs @@ -74,7 +74,7 @@ fn python_install() { error: the following required arguments were not provided: ... - Usage: uv python uninstall ... + Usage: uv python uninstall --install-dir ... For more information, try '--help'. "###); @@ -209,7 +209,7 @@ fn python_install_preview() { error: the following required arguments were not provided: ... - Usage: uv python uninstall ... + Usage: uv python uninstall --install-dir ... For more information, try '--help'. "###);