From 24d6ef13065bdcefbd23e2bfd35c7fce80dfdbe7 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Fri, 22 Nov 2024 19:31:35 -0500 Subject: [PATCH] Show an interpreter-focused message for --target and --prefix --- crates/uv/src/commands/pip/install.rs | 43 ++++++++++------- crates/uv/src/commands/pip/operations.rs | 61 +++++++++++++++++++++++- crates/uv/src/commands/pip/sync.rs | 43 ++++++++++------- crates/uv/src/commands/venv.rs | 54 +++++++-------------- crates/uv/src/lib.rs | 2 + crates/uv/tests/it/export.rs | 2 +- crates/uv/tests/it/pip_install.rs | 32 ++++++------- crates/uv/tests/it/pip_sync.rs | 23 +++++---- 8 files changed, 165 insertions(+), 95 deletions(-) diff --git a/crates/uv/src/commands/pip/install.rs b/crates/uv/src/commands/pip/install.rs index 15529b4fde8dd..020af2c62afde 100644 --- a/crates/uv/src/commands/pip/install.rs +++ b/crates/uv/src/commands/pip/install.rs @@ -22,7 +22,8 @@ use uv_installer::{SatisfiesResult, SitePackages}; use uv_pep508::PackageName; use uv_pypi_types::{Conflicts, Requirement}; use uv_python::{ - EnvironmentPreference, Prefix, PythonEnvironment, PythonRequest, PythonVersion, Target, + EnvironmentPreference, Prefix, PythonEnvironment, PythonInstallation, + PythonPreference, PythonRequest, PythonVersion, Target, }; use uv_requirements::{RequirementsSource, RequirementsSpecification}; use uv_resolver::{ @@ -32,8 +33,8 @@ use uv_resolver::{ use uv_types::{BuildIsolation, HashStrategy}; use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger, InstallLogger}; -use crate::commands::pip::operations::report_target_environment; use crate::commands::pip::operations::Modifications; +use crate::commands::pip::operations::{report_target_environment, report_target_interpreter}; use crate::commands::pip::{operations, resolution_markers, resolution_tags}; use crate::commands::{diagnostics, ExitStatus, SharedState}; use crate::printer::Printer; @@ -76,6 +77,7 @@ pub(crate) async fn pip_install( break_system_packages: bool, target: Option, prefix: Option, + python_preference: PythonPreference, concurrency: Concurrency, native_tls: bool, allow_insecure_host: &[TrustedHost], @@ -138,22 +140,31 @@ pub(crate) async fn pip_install( ) .collect(); - // Determine whether we're modifying the discovered environment, or a separate target. - let mutable = !(target.is_some() || prefix.is_some()); - // Detect the current Python interpreter. - let environment = PythonEnvironment::find( - &python - .as_deref() - .map(PythonRequest::parse) - .unwrap_or_default(), - EnvironmentPreference::from_system_flag(system, mutable), - &cache, - )?; - - if mutable { + let environment = if target.is_some() || prefix.is_some() { + let installation = PythonInstallation::find( + &python + .as_deref() + .map(PythonRequest::parse) + .unwrap_or_default(), + EnvironmentPreference::from_system_flag(system, false), + python_preference, + &cache, + )?; + report_target_interpreter(&installation, true, printer)?; + PythonEnvironment::from_installation(installation) + } else { + let environment = PythonEnvironment::find( + &python + .as_deref() + .map(PythonRequest::parse) + .unwrap_or_default(), + EnvironmentPreference::from_system_flag(system, true), + &cache, + )?; report_target_environment(&environment, &cache, printer)?; - } + environment + }; // Apply any `--target` or `--prefix` directories. let environment = if let Some(target) = target { diff --git a/crates/uv/src/commands/pip/operations.rs b/crates/uv/src/commands/pip/operations.rs index e5bd768ebebba..6d0adce91675c 100644 --- a/crates/uv/src/commands/pip/operations.rs +++ b/crates/uv/src/commands/pip/operations.rs @@ -30,7 +30,7 @@ use uv_installer::{Plan, Planner, Preparer, SitePackages}; use uv_normalize::{GroupName, PackageName}; use uv_platform_tags::Tags; use uv_pypi_types::{Conflicts, ResolverMarkerEnvironment}; -use uv_python::PythonEnvironment; +use uv_python::{PythonEnvironment, PythonInstallation}; use uv_requirements::{ LookaheadResolver, NamedRequirementsResolver, RequirementsSource, RequirementsSpecification, SourceTreeResolver, @@ -566,6 +566,63 @@ pub(crate) async fn install( Ok(changelog) } +/// Display a message about the target environment for the operation. +pub(crate) fn report_target_interpreter( + python: &PythonInstallation, + dimmed: bool, + printer: Printer, +) -> Result<(), Error> { + let managed = python.source().is_managed(); + let implementation = python.implementation(); + let interpreter = python.interpreter(); + + if dimmed { + if managed { + writeln!( + printer.stderr(), + "{}", + format!( + "Using {} {}", + implementation.pretty(), + interpreter.python_version() + ) + .dimmed() + )?; + } else { + writeln!( + printer.stderr(), + "{}", + format!( + "Using {} {} interpreter at: {}", + implementation.pretty(), + interpreter.python_version(), + interpreter.sys_executable().user_display() + ) + .dimmed() + )?; + } + } else { + if managed { + writeln!( + printer.stderr(), + "Using {} {}", + implementation.pretty(), + interpreter.python_version().cyan() + )?; + } else { + writeln!( + printer.stderr(), + "Using {} {} interpreter at: {}", + implementation.pretty(), + interpreter.python_version(), + interpreter.sys_executable().user_display().cyan() + )?; + } + } + + Ok(()) +} + /// Display a message about the target environment for the operation. pub(crate) fn report_target_environment( env: &PythonEnvironment, @@ -573,7 +630,7 @@ pub(crate) fn report_target_environment( printer: Printer, ) -> Result<(), Error> { let message = format!( - "Using Python {} environment at {}", + "Using Python {} environment at: {}", env.interpreter().python_version(), env.root().user_display() ); diff --git a/crates/uv/src/commands/pip/sync.rs b/crates/uv/src/commands/pip/sync.rs index 08ffb1181a267..0ae71832c1dae 100644 --- a/crates/uv/src/commands/pip/sync.rs +++ b/crates/uv/src/commands/pip/sync.rs @@ -19,7 +19,8 @@ use uv_installer::SitePackages; use uv_pep508::PackageName; use uv_pypi_types::Conflicts; use uv_python::{ - EnvironmentPreference, Prefix, PythonEnvironment, PythonRequest, PythonVersion, Target, + EnvironmentPreference, Prefix, PythonEnvironment, PythonInstallation, PythonPreference, + PythonRequest, PythonVersion, Target, }; use uv_requirements::{RequirementsSource, RequirementsSpecification}; use uv_resolver::{ @@ -29,8 +30,8 @@ use uv_resolver::{ use uv_types::{BuildIsolation, HashStrategy}; use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger}; -use crate::commands::pip::operations::report_target_environment; use crate::commands::pip::operations::Modifications; +use crate::commands::pip::operations::{report_target_environment, report_target_interpreter}; use crate::commands::pip::{operations, resolution_markers, resolution_tags}; use crate::commands::{diagnostics, ExitStatus, SharedState}; use crate::printer::Printer; @@ -65,6 +66,7 @@ pub(crate) async fn pip_sync( target: Option, prefix: Option, sources: SourceStrategy, + python_preference: PythonPreference, concurrency: Concurrency, native_tls: bool, allow_insecure_host: &[TrustedHost], @@ -122,22 +124,31 @@ pub(crate) async fn pip_sync( } } - // Determine whether we're modifying the discovered environment, or a separate target. - let mutable = !(target.is_some() || prefix.is_some()); - // Detect the current Python interpreter. - let environment = PythonEnvironment::find( - &python - .as_deref() - .map(PythonRequest::parse) - .unwrap_or_default(), - EnvironmentPreference::from_system_flag(system, mutable), - &cache, - )?; - - if mutable { + let environment = if target.is_some() || prefix.is_some() { + let installation = PythonInstallation::find( + &python + .as_deref() + .map(PythonRequest::parse) + .unwrap_or_default(), + EnvironmentPreference::from_system_flag(system, false), + python_preference, + &cache, + )?; + report_target_interpreter(&installation, true, printer)?; + PythonEnvironment::from_installation(installation) + } else { + let environment = PythonEnvironment::find( + &python + .as_deref() + .map(PythonRequest::parse) + .unwrap_or_default(), + EnvironmentPreference::from_system_flag(system, true), + &cache, + )?; report_target_environment(&environment, &cache, printer)?; - } + environment + }; // Apply any `--target` or `--prefix` directories. let environment = if let Some(target) = target { diff --git a/crates/uv/src/commands/venv.rs b/crates/uv/src/commands/venv.rs index 93cb6af415ae2..ea985c8e4677c 100644 --- a/crates/uv/src/commands/venv.rs +++ b/crates/uv/src/commands/venv.rs @@ -31,7 +31,7 @@ use uv_warnings::{warn_user, warn_user_once}; use uv_workspace::{DiscoveryOptions, VirtualProject, WorkspaceError}; use crate::commands::pip::loggers::{DefaultInstallLogger, InstallLogger}; -use crate::commands::pip::operations::Changelog; +use crate::commands::pip::operations::{report_target_interpreter, Changelog}; use crate::commands::project::{validate_requires_python, WorkspacePython}; use crate::commands::reporters::PythonDownloadReporter; use crate::commands::{ExitStatus, SharedState}; @@ -201,23 +201,23 @@ async fn venv_impl( .into_diagnostic()?; // Locate the Python interpreter to use in the environment - let python = PythonInstallation::find_or_download( - python_request.as_ref(), - EnvironmentPreference::OnlySystem, - python_preference, - python_downloads, - &client_builder, - cache, - Some(&reporter), - install_mirrors.python_install_mirror.as_deref(), - install_mirrors.pypy_install_mirror.as_deref(), - ) - .await - .into_diagnostic()?; - - let managed = python.source().is_managed(); - let implementation = python.implementation(); - let interpreter = python.into_interpreter(); + let interpreter = { + let python = PythonInstallation::find_or_download( + python_request.as_ref(), + EnvironmentPreference::OnlySystem, + python_preference, + python_downloads, + &client_builder, + cache, + Some(&reporter), + install_mirrors.python_install_mirror.as_deref(), + install_mirrors.pypy_install_mirror.as_deref(), + ) + .await + .into_diagnostic()?; + report_target_interpreter(&python, false, printer).into_diagnostic()?; + python.into_interpreter() + }; // Add all authenticated sources to the cache. for index in index_locations.allowed_indexes() { @@ -226,24 +226,6 @@ async fn venv_impl( } } - if managed { - writeln!( - printer.stderr(), - "Using {} {}", - implementation.pretty(), - interpreter.python_version().cyan() - ) - .into_diagnostic()?; - } else { - writeln!( - printer.stderr(), - "Using {} {} interpreter at: {}", - implementation.pretty(), - interpreter.python_version(), - interpreter.sys_executable().user_display().cyan() - ) - .into_diagnostic()?; - } // Check if the discovered Python version is incompatible with the current workspace if let Some(requires_python) = requires_python { diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index f095ce86d380b..c4befdad6115c 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -438,6 +438,7 @@ async fn run(mut cli: Cli) -> Result { args.settings.target, args.settings.prefix, args.settings.sources, + globals.python_preference, globals.concurrency, globals.native_tls, &globals.allow_insecure_host, @@ -526,6 +527,7 @@ async fn run(mut cli: Cli) -> Result { args.settings.break_system_packages, args.settings.target, args.settings.prefix, + globals.python_preference, globals.concurrency, globals.native_tls, &globals.allow_insecure_host, diff --git a/crates/uv/tests/it/export.rs b/crates/uv/tests/it/export.rs index 200d29f6177d5..12c108967d208 100644 --- a/crates/uv/tests/it/export.rs +++ b/crates/uv/tests/it/export.rs @@ -759,7 +759,7 @@ fn relative_path() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 3 packages in [TIME] Prepared 3 packages in [TIME] Installed 3 packages in [TIME] diff --git a/crates/uv/tests/it/pip_install.rs b/crates/uv/tests/it/pip_install.rs index d1f8b8d1065a8..7fda54c6e5173 100644 --- a/crates/uv/tests/it/pip_install.rs +++ b/crates/uv/tests/it/pip_install.rs @@ -1266,7 +1266,7 @@ fn install_editable_bare_cli() { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME] @@ -1293,7 +1293,7 @@ fn install_editable_bare_requirements_txt() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME] @@ -3445,7 +3445,7 @@ requires-python = ">=3.8" ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 4 packages in [TIME] Installed 4 packages in [TIME] @@ -3465,7 +3465,7 @@ requires-python = ">=3.8" ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Audited 1 package in [TIME] "### ); @@ -3491,7 +3491,7 @@ requires-python = ">=3.8" ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 2 packages in [TIME] Uninstalled 2 packages in [TIME] @@ -3539,7 +3539,7 @@ fn invalidate_path_on_cache_key() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 4 packages in [TIME] Installed 4 packages in [TIME] @@ -3559,7 +3559,7 @@ fn invalidate_path_on_cache_key() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Audited 1 package in [TIME] "### ); @@ -3576,7 +3576,7 @@ fn invalidate_path_on_cache_key() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 1 package in [TIME] Uninstalled 1 package in [TIME] @@ -3597,7 +3597,7 @@ fn invalidate_path_on_cache_key() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 1 package in [TIME] Uninstalled 1 package in [TIME] @@ -3628,7 +3628,7 @@ fn invalidate_path_on_cache_key() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Audited 1 package in [TIME] "### ); @@ -3661,7 +3661,7 @@ fn invalidate_path_on_cache_key() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 1 package in [TIME] Uninstalled 1 package in [TIME] @@ -3682,7 +3682,7 @@ fn invalidate_path_on_cache_key() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 1 package in [TIME] Uninstalled 1 package in [TIME] @@ -3738,7 +3738,7 @@ fn invalidate_path_on_commit() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 4 packages in [TIME] Installed 4 packages in [TIME] @@ -3758,7 +3758,7 @@ fn invalidate_path_on_commit() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Audited 1 package in [TIME] "### ); @@ -3781,7 +3781,7 @@ fn invalidate_path_on_commit() -> Result<()> { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 4 packages in [TIME] Prepared 1 package in [TIME] Uninstalled 1 package in [TIME] @@ -4881,7 +4881,7 @@ fn deptry_gitignore() { ----- stdout ----- ----- stderr ----- - Using Python 3.12.[X] environment at [VENV]/ + Using Python 3.12.[X] environment at: [VENV]/ Resolved 3 packages in [TIME] Prepared 3 packages in [TIME] Installed 3 packages in [TIME] diff --git a/crates/uv/tests/it/pip_sync.rs b/crates/uv/tests/it/pip_sync.rs index dee1a6b01e5fe..7ab8dad156f82 100644 --- a/crates/uv/tests/it/pip_sync.rs +++ b/crates/uv/tests/it/pip_sync.rs @@ -5163,7 +5163,7 @@ fn target_built_distribution() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("iniconfig==2.0.0")?; - uv_snapshot!(context.pip_sync() + uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in") .arg("--target") .arg("target"), @r###" @@ -5172,6 +5172,7 @@ fn target_built_distribution() -> Result<()> { ----- stdout ----- ----- stderr ----- + Using CPython 3.12.[X] interpreter at: .venv/bin/python3 Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME] @@ -5198,7 +5199,7 @@ fn target_built_distribution() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("iniconfig==1.1.1")?; - uv_snapshot!(context.pip_sync() + uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in") .arg("--target") .arg("target"), @r###" @@ -5207,6 +5208,7 @@ fn target_built_distribution() -> Result<()> { ----- stdout ----- ----- stderr ----- + Using CPython 3.12.[X] interpreter at: .venv/bin/python3 Resolved 1 package in [TIME] Prepared 1 package in [TIME] Uninstalled 1 package in [TIME] @@ -5219,7 +5221,7 @@ fn target_built_distribution() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("flask")?; - uv_snapshot!(context.pip_sync() + uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in") .arg("--target") .arg("target"), @r###" @@ -5228,6 +5230,7 @@ fn target_built_distribution() -> Result<()> { ----- stdout ----- ----- stderr ----- + Using CPython 3.12.[X] interpreter at: .venv/bin/python3 Resolved 1 package in [TIME] Prepared 1 package in [TIME] Uninstalled 1 package in [TIME] @@ -5255,7 +5258,7 @@ fn target_source_distribution() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("iniconfig==2.0.0")?; - uv_snapshot!(context.pip_sync() + uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in") .arg("--no-binary") .arg("iniconfig") @@ -5266,6 +5269,7 @@ fn target_source_distribution() -> Result<()> { ----- stdout ----- ----- stderr ----- + Using CPython 3.12.[X] interpreter at: .venv/bin/python3 Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME] @@ -5304,7 +5308,7 @@ fn target_no_build_isolation() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("flit_core")?; - uv_snapshot!(context.pip_sync() + uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in"), @r###" success: true exit_code: 0 @@ -5321,7 +5325,7 @@ fn target_no_build_isolation() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("wheel")?; - uv_snapshot!(context.pip_sync() + uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in") .arg("--no-build-isolation") .arg("--no-binary") @@ -5333,6 +5337,7 @@ fn target_no_build_isolation() -> Result<()> { ----- stdout ----- ----- stderr ----- + Using CPython 3.12.[X] interpreter at: .venv/bin/python3 Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME] @@ -5379,6 +5384,7 @@ fn target_system() -> Result<()> { ----- stdout ----- ----- stderr ----- + Using CPython 3.12.[X] interpreter at: [PYTHON-3.12] Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME] @@ -5402,7 +5408,7 @@ fn prefix() -> Result<()> { let prefix = context.temp_dir.child("prefix"); - uv_snapshot!(context.pip_sync() + uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in") .arg("--prefix") .arg(prefix.path()), @r###" @@ -5411,6 +5417,7 @@ fn prefix() -> Result<()> { ----- stdout ----- ----- stderr ----- + Using CPython 3.12.6 interpreter at: .venv/bin/python3 Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME] @@ -5437,7 +5444,7 @@ fn prefix() -> Result<()> { let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("iniconfig==1.1.1")?; - uv_snapshot!(context.pip_sync() + uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in") .arg("--prefix") .arg(prefix.path()), @r###"