mirror of
				https://github.com/astral-sh/uv.git
				synced 2025-11-03 21:23:54 +00:00 
			
		
		
		
	Add a common abstraction to discover PEP 723 script interpreters (#10132)
## Summary This logic is already repeated twice, and I'm on the verge of adding a third. (No behavioral changes.)
This commit is contained in:
		
							parent
							
								
									6ed7302432
								
							
						
					
					
						commit
						9279a125e9
					
				
					 10 changed files with 133 additions and 114 deletions
				
			
		| 
						 | 
					@ -229,6 +229,7 @@ impl PythonInstallation {
 | 
				
			||||||
        &self.interpreter
 | 
					        &self.interpreter
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Consume the [`PythonInstallation`] and return the [`Interpreter`].
 | 
				
			||||||
    pub fn into_interpreter(self) -> Interpreter {
 | 
					    pub fn into_interpreter(self) -> Interpreter {
 | 
				
			||||||
        self.interpreter
 | 
					        self.interpreter
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,10 +26,7 @@ use uv_git::{GitReference, GIT_STORE};
 | 
				
			||||||
use uv_normalize::{PackageName, DEV_DEPENDENCIES};
 | 
					use uv_normalize::{PackageName, DEV_DEPENDENCIES};
 | 
				
			||||||
use uv_pep508::{ExtraName, Requirement, UnnamedRequirement, VersionOrUrl};
 | 
					use uv_pep508::{ExtraName, Requirement, UnnamedRequirement, VersionOrUrl};
 | 
				
			||||||
use uv_pypi_types::{redact_credentials, ParsedUrl, RequirementSource, VerbatimParsedUrl};
 | 
					use uv_pypi_types::{redact_credentials, ParsedUrl, RequirementSource, VerbatimParsedUrl};
 | 
				
			||||||
use uv_python::{
 | 
					use uv_python::{Interpreter, PythonDownloads, PythonEnvironment, PythonPreference, PythonRequest};
 | 
				
			||||||
    EnvironmentPreference, Interpreter, PythonDownloads, PythonEnvironment, PythonInstallation,
 | 
					 | 
				
			||||||
    PythonPreference, PythonRequest,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
use uv_requirements::{NamedRequirementsResolver, RequirementsSource, RequirementsSpecification};
 | 
					use uv_requirements::{NamedRequirementsResolver, RequirementsSource, RequirementsSpecification};
 | 
				
			||||||
use uv_resolver::{FlatIndex, InstallTarget};
 | 
					use uv_resolver::{FlatIndex, InstallTarget};
 | 
				
			||||||
use uv_scripts::{Pep723Item, Pep723Script};
 | 
					use uv_scripts::{Pep723Item, Pep723Script};
 | 
				
			||||||
| 
						 | 
					@ -46,8 +43,7 @@ use crate::commands::pip::loggers::{
 | 
				
			||||||
use crate::commands::pip::operations::Modifications;
 | 
					use crate::commands::pip::operations::Modifications;
 | 
				
			||||||
use crate::commands::project::lock::LockMode;
 | 
					use crate::commands::project::lock::LockMode;
 | 
				
			||||||
use crate::commands::project::{
 | 
					use crate::commands::project::{
 | 
				
			||||||
    init_script_python_requirement, lock, validate_script_requires_python, ProjectError,
 | 
					    init_script_python_requirement, lock, ProjectError, ProjectInterpreter, ScriptInterpreter,
 | 
				
			||||||
    ProjectInterpreter, ScriptPython,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
 | 
					use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
 | 
				
			||||||
use crate::commands::{diagnostics, project, ExitStatus};
 | 
					use crate::commands::{diagnostics, project, ExitStatus};
 | 
				
			||||||
| 
						 | 
					@ -144,7 +140,7 @@ pub(crate) async fn add(
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            let requires_python = init_script_python_requirement(
 | 
					            let requires_python = init_script_python_requirement(
 | 
				
			||||||
                python.as_deref(),
 | 
					                python.as_deref(),
 | 
				
			||||||
                install_mirrors.clone(),
 | 
					                &install_mirrors,
 | 
				
			||||||
                project_dir,
 | 
					                project_dir,
 | 
				
			||||||
                false,
 | 
					                false,
 | 
				
			||||||
                python_preference,
 | 
					                python_preference,
 | 
				
			||||||
| 
						 | 
					@ -158,42 +154,23 @@ pub(crate) async fn add(
 | 
				
			||||||
            Pep723Script::init(&script, requires_python.specifiers()).await?
 | 
					            Pep723Script::init(&script, requires_python.specifiers()).await?
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let ScriptPython {
 | 
					        // Discover the interpreter.
 | 
				
			||||||
            source,
 | 
					        let interpreter = ScriptInterpreter::discover(
 | 
				
			||||||
            python_request,
 | 
					 | 
				
			||||||
            requires_python,
 | 
					 | 
				
			||||||
        } = ScriptPython::from_request(
 | 
					 | 
				
			||||||
            python.as_deref().map(PythonRequest::parse),
 | 
					 | 
				
			||||||
            None,
 | 
					 | 
				
			||||||
            &Pep723Item::Script(script.clone()),
 | 
					            &Pep723Item::Script(script.clone()),
 | 
				
			||||||
            no_config,
 | 
					            python.as_deref().map(PythonRequest::parse),
 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .await?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let interpreter = PythonInstallation::find_or_download(
 | 
					 | 
				
			||||||
            python_request.as_ref(),
 | 
					 | 
				
			||||||
            EnvironmentPreference::Any,
 | 
					 | 
				
			||||||
            python_preference,
 | 
					            python_preference,
 | 
				
			||||||
            python_downloads,
 | 
					            python_downloads,
 | 
				
			||||||
            &client_builder,
 | 
					            connectivity,
 | 
				
			||||||
 | 
					            native_tls,
 | 
				
			||||||
 | 
					            allow_insecure_host,
 | 
				
			||||||
 | 
					            &install_mirrors,
 | 
				
			||||||
 | 
					            no_config,
 | 
				
			||||||
            cache,
 | 
					            cache,
 | 
				
			||||||
            Some(&reporter),
 | 
					            printer,
 | 
				
			||||||
            install_mirrors.python_install_mirror.as_deref(),
 | 
					 | 
				
			||||||
            install_mirrors.pypy_install_mirror.as_deref(),
 | 
					 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .await?
 | 
					        .await?
 | 
				
			||||||
        .into_interpreter();
 | 
					        .into_interpreter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some((requires_python, requires_python_source)) = requires_python {
 | 
					 | 
				
			||||||
            validate_script_requires_python(
 | 
					 | 
				
			||||||
                &interpreter,
 | 
					 | 
				
			||||||
                None,
 | 
					 | 
				
			||||||
                &requires_python,
 | 
					 | 
				
			||||||
                &requires_python_source,
 | 
					 | 
				
			||||||
                &source,
 | 
					 | 
				
			||||||
            )?;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Target::Script(script, Box::new(interpreter))
 | 
					        Target::Script(script, Box::new(interpreter))
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        // Find the project in the workspace.
 | 
					        // Find the project in the workspace.
 | 
				
			||||||
| 
						 | 
					@ -234,7 +211,7 @@ pub(crate) async fn add(
 | 
				
			||||||
                connectivity,
 | 
					                connectivity,
 | 
				
			||||||
                native_tls,
 | 
					                native_tls,
 | 
				
			||||||
                allow_insecure_host,
 | 
					                allow_insecure_host,
 | 
				
			||||||
                install_mirrors.clone(),
 | 
					                &install_mirrors,
 | 
				
			||||||
                no_config,
 | 
					                no_config,
 | 
				
			||||||
                cache,
 | 
					                cache,
 | 
				
			||||||
                printer,
 | 
					                printer,
 | 
				
			||||||
| 
						 | 
					@ -248,7 +225,7 @@ pub(crate) async fn add(
 | 
				
			||||||
            let venv = project::get_or_init_environment(
 | 
					            let venv = project::get_or_init_environment(
 | 
				
			||||||
                project.workspace(),
 | 
					                project.workspace(),
 | 
				
			||||||
                python.as_deref().map(PythonRequest::parse),
 | 
					                python.as_deref().map(PythonRequest::parse),
 | 
				
			||||||
                install_mirrors.clone(),
 | 
					                &install_mirrors,
 | 
				
			||||||
                python_preference,
 | 
					                python_preference,
 | 
				
			||||||
                python_downloads,
 | 
					                python_downloads,
 | 
				
			||||||
                connectivity,
 | 
					                connectivity,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,7 @@ pub(crate) async fn export(
 | 
				
			||||||
            connectivity,
 | 
					            connectivity,
 | 
				
			||||||
            native_tls,
 | 
					            native_tls,
 | 
				
			||||||
            allow_insecure_host,
 | 
					            allow_insecure_host,
 | 
				
			||||||
            install_mirrors,
 | 
					            &install_mirrors,
 | 
				
			||||||
            no_config,
 | 
					            no_config,
 | 
				
			||||||
            cache,
 | 
					            cache,
 | 
				
			||||||
            printer,
 | 
					            printer,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,7 +242,7 @@ async fn init_script(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let requires_python = init_script_python_requirement(
 | 
					    let requires_python = init_script_python_requirement(
 | 
				
			||||||
        python.as_deref(),
 | 
					        python.as_deref(),
 | 
				
			||||||
        install_mirrors,
 | 
					        &install_mirrors,
 | 
				
			||||||
        &CWD,
 | 
					        &CWD,
 | 
				
			||||||
        no_pin_python,
 | 
					        no_pin_python,
 | 
				
			||||||
        python_preference,
 | 
					        python_preference,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,7 +109,7 @@ pub(crate) async fn lock(
 | 
				
			||||||
            connectivity,
 | 
					            connectivity,
 | 
				
			||||||
            native_tls,
 | 
					            native_tls,
 | 
				
			||||||
            allow_insecure_host,
 | 
					            allow_insecure_host,
 | 
				
			||||||
            install_mirrors,
 | 
					            &install_mirrors,
 | 
				
			||||||
            no_config,
 | 
					            no_config,
 | 
				
			||||||
            cache,
 | 
					            cache,
 | 
				
			||||||
            printer,
 | 
					            printer,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -397,7 +397,7 @@ pub(crate) fn validate_requires_python(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Returns an error if the [`Interpreter`] does not satisfy script or workspace `requires-python`.
 | 
					/// Returns an error if the [`Interpreter`] does not satisfy script or workspace `requires-python`.
 | 
				
			||||||
#[allow(clippy::result_large_err)]
 | 
					#[allow(clippy::result_large_err)]
 | 
				
			||||||
pub(crate) fn validate_script_requires_python(
 | 
					fn validate_script_requires_python(
 | 
				
			||||||
    interpreter: &Interpreter,
 | 
					    interpreter: &Interpreter,
 | 
				
			||||||
    workspace: Option<&Workspace>,
 | 
					    workspace: Option<&Workspace>,
 | 
				
			||||||
    requires_python: &RequiresPython,
 | 
					    requires_python: &RequiresPython,
 | 
				
			||||||
| 
						 | 
					@ -406,35 +406,105 @@ pub(crate) fn validate_script_requires_python(
 | 
				
			||||||
) -> Result<(), ProjectError> {
 | 
					) -> Result<(), ProjectError> {
 | 
				
			||||||
    match requires_python_source {
 | 
					    match requires_python_source {
 | 
				
			||||||
        RequiresPythonSource::Project => {
 | 
					        RequiresPythonSource::Project => {
 | 
				
			||||||
            validate_requires_python(interpreter, workspace, requires_python, request_source)?;
 | 
					            validate_requires_python(interpreter, workspace, requires_python, request_source)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        RequiresPythonSource::Script => {}
 | 
					        RequiresPythonSource::Script => {
 | 
				
			||||||
    };
 | 
					            if requires_python.contains(interpreter.python_version()) {
 | 
				
			||||||
 | 
					                return Ok(());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if requires_python.contains(interpreter.python_version()) {
 | 
					            match request_source {
 | 
				
			||||||
        return Ok(());
 | 
					                PythonRequestSource::UserRequest => {
 | 
				
			||||||
 | 
					                    Err(ProjectError::RequestedPythonScriptIncompatibility(
 | 
				
			||||||
 | 
					                        interpreter.python_version().clone(),
 | 
				
			||||||
 | 
					                        requires_python.clone(),
 | 
				
			||||||
 | 
					                    ))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                PythonRequestSource::DotPythonVersion(file) => {
 | 
				
			||||||
 | 
					                    Err(ProjectError::DotPythonVersionScriptIncompatibility(
 | 
				
			||||||
 | 
					                        file.file_name().to_string(),
 | 
				
			||||||
 | 
					                        interpreter.python_version().clone(),
 | 
				
			||||||
 | 
					                        requires_python.clone(),
 | 
				
			||||||
 | 
					                    ))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                PythonRequestSource::RequiresPython => {
 | 
				
			||||||
 | 
					                    Err(ProjectError::RequiresPythonScriptIncompatibility(
 | 
				
			||||||
 | 
					                        interpreter.python_version().clone(),
 | 
				
			||||||
 | 
					                        requires_python.clone(),
 | 
				
			||||||
 | 
					                    ))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// An interpreter suitable for a PEP 723 script.
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub(crate) struct ScriptInterpreter(Interpreter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ScriptInterpreter {
 | 
				
			||||||
 | 
					    /// Discover the interpreter to use for the current [`Pep723Item`].
 | 
				
			||||||
 | 
					    pub(crate) async fn discover(
 | 
				
			||||||
 | 
					        script: &Pep723Item,
 | 
				
			||||||
 | 
					        python_request: Option<PythonRequest>,
 | 
				
			||||||
 | 
					        python_preference: PythonPreference,
 | 
				
			||||||
 | 
					        python_downloads: PythonDownloads,
 | 
				
			||||||
 | 
					        connectivity: Connectivity,
 | 
				
			||||||
 | 
					        native_tls: bool,
 | 
				
			||||||
 | 
					        allow_insecure_host: &[TrustedHost],
 | 
				
			||||||
 | 
					        install_mirrors: &PythonInstallMirrors,
 | 
				
			||||||
 | 
					        no_config: bool,
 | 
				
			||||||
 | 
					        cache: &Cache,
 | 
				
			||||||
 | 
					        printer: Printer,
 | 
				
			||||||
 | 
					    ) -> Result<Self, ProjectError> {
 | 
				
			||||||
 | 
					        // For now, we assume that scripts are never evaluated in the context of a workspace.
 | 
				
			||||||
 | 
					        let workspace = None;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let ScriptPython {
 | 
				
			||||||
 | 
					            source,
 | 
				
			||||||
 | 
					            python_request,
 | 
				
			||||||
 | 
					            requires_python,
 | 
				
			||||||
 | 
					        } = ScriptPython::from_request(python_request, workspace, script, no_config).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let client_builder = BaseClientBuilder::new()
 | 
				
			||||||
 | 
					            .connectivity(connectivity)
 | 
				
			||||||
 | 
					            .native_tls(native_tls)
 | 
				
			||||||
 | 
					            .allow_insecure_host(allow_insecure_host.to_vec());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let reporter = PythonDownloadReporter::single(printer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let interpreter = PythonInstallation::find_or_download(
 | 
				
			||||||
 | 
					            python_request.as_ref(),
 | 
				
			||||||
 | 
					            EnvironmentPreference::Any,
 | 
				
			||||||
 | 
					            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_interpreter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let Some((requires_python, requires_python_source)) = requires_python {
 | 
				
			||||||
 | 
					            if let Err(err) = validate_script_requires_python(
 | 
				
			||||||
 | 
					                &interpreter,
 | 
				
			||||||
 | 
					                workspace,
 | 
				
			||||||
 | 
					                &requires_python,
 | 
				
			||||||
 | 
					                &requires_python_source,
 | 
				
			||||||
 | 
					                &source,
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                warn_user!("{err}");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(Self(interpreter))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    match request_source {
 | 
					    /// Consume the [`PythonInstallation`] and return the [`Interpreter`].
 | 
				
			||||||
        PythonRequestSource::UserRequest => {
 | 
					    pub(crate) fn into_interpreter(self) -> Interpreter {
 | 
				
			||||||
            Err(ProjectError::RequestedPythonScriptIncompatibility(
 | 
					        self.0
 | 
				
			||||||
                interpreter.python_version().clone(),
 | 
					 | 
				
			||||||
                requires_python.clone(),
 | 
					 | 
				
			||||||
            ))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        PythonRequestSource::DotPythonVersion(file) => {
 | 
					 | 
				
			||||||
            Err(ProjectError::DotPythonVersionScriptIncompatibility(
 | 
					 | 
				
			||||||
                file.file_name().to_string(),
 | 
					 | 
				
			||||||
                interpreter.python_version().clone(),
 | 
					 | 
				
			||||||
                requires_python.clone(),
 | 
					 | 
				
			||||||
            ))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        PythonRequestSource::RequiresPython => {
 | 
					 | 
				
			||||||
            Err(ProjectError::RequiresPythonScriptIncompatibility(
 | 
					 | 
				
			||||||
                interpreter.python_version().clone(),
 | 
					 | 
				
			||||||
                requires_python.clone(),
 | 
					 | 
				
			||||||
            ))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -459,7 +529,7 @@ impl ProjectInterpreter {
 | 
				
			||||||
        connectivity: Connectivity,
 | 
					        connectivity: Connectivity,
 | 
				
			||||||
        native_tls: bool,
 | 
					        native_tls: bool,
 | 
				
			||||||
        allow_insecure_host: &[TrustedHost],
 | 
					        allow_insecure_host: &[TrustedHost],
 | 
				
			||||||
        install_mirrors: PythonInstallMirrors,
 | 
					        install_mirrors: &PythonInstallMirrors,
 | 
				
			||||||
        no_config: bool,
 | 
					        no_config: bool,
 | 
				
			||||||
        cache: &Cache,
 | 
					        cache: &Cache,
 | 
				
			||||||
        printer: Printer,
 | 
					        printer: Printer,
 | 
				
			||||||
| 
						 | 
					@ -547,7 +617,7 @@ impl ProjectInterpreter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let reporter = PythonDownloadReporter::single(printer);
 | 
					        let reporter = PythonDownloadReporter::single(printer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Locate the Python interpreter to use in the environment
 | 
					        // Locate the Python interpreter to use in the environment.
 | 
				
			||||||
        let python = PythonInstallation::find_or_download(
 | 
					        let python = PythonInstallation::find_or_download(
 | 
				
			||||||
            python_request.as_ref(),
 | 
					            python_request.as_ref(),
 | 
				
			||||||
            EnvironmentPreference::OnlySystem,
 | 
					            EnvironmentPreference::OnlySystem,
 | 
				
			||||||
| 
						 | 
					@ -771,7 +841,7 @@ impl ScriptPython {
 | 
				
			||||||
pub(crate) async fn get_or_init_environment(
 | 
					pub(crate) async fn get_or_init_environment(
 | 
				
			||||||
    workspace: &Workspace,
 | 
					    workspace: &Workspace,
 | 
				
			||||||
    python: Option<PythonRequest>,
 | 
					    python: Option<PythonRequest>,
 | 
				
			||||||
    install_mirrors: PythonInstallMirrors,
 | 
					    install_mirrors: &PythonInstallMirrors,
 | 
				
			||||||
    python_preference: PythonPreference,
 | 
					    python_preference: PythonPreference,
 | 
				
			||||||
    python_downloads: PythonDownloads,
 | 
					    python_downloads: PythonDownloads,
 | 
				
			||||||
    connectivity: Connectivity,
 | 
					    connectivity: Connectivity,
 | 
				
			||||||
| 
						 | 
					@ -1598,7 +1668,7 @@ pub(crate) async fn update_environment(
 | 
				
			||||||
/// Determine the [`RequiresPython`] requirement for a new PEP 723 script.
 | 
					/// Determine the [`RequiresPython`] requirement for a new PEP 723 script.
 | 
				
			||||||
pub(crate) async fn init_script_python_requirement(
 | 
					pub(crate) async fn init_script_python_requirement(
 | 
				
			||||||
    python: Option<&str>,
 | 
					    python: Option<&str>,
 | 
				
			||||||
    install_mirrors: PythonInstallMirrors,
 | 
					    install_mirrors: &PythonInstallMirrors,
 | 
				
			||||||
    directory: &Path,
 | 
					    directory: &Path,
 | 
				
			||||||
    no_pin_python: bool,
 | 
					    no_pin_python: bool,
 | 
				
			||||||
    python_preference: PythonPreference,
 | 
					    python_preference: PythonPreference,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -194,7 +194,7 @@ pub(crate) async fn remove(
 | 
				
			||||||
    let venv = project::get_or_init_environment(
 | 
					    let venv = project::get_or_init_environment(
 | 
				
			||||||
        project.workspace(),
 | 
					        project.workspace(),
 | 
				
			||||||
        python.as_deref().map(PythonRequest::parse),
 | 
					        python.as_deref().map(PythonRequest::parse),
 | 
				
			||||||
        install_mirrors,
 | 
					        &install_mirrors,
 | 
				
			||||||
        python_preference,
 | 
					        python_preference,
 | 
				
			||||||
        python_downloads,
 | 
					        python_downloads,
 | 
				
			||||||
        connectivity,
 | 
					        connectivity,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,8 +45,8 @@ use crate::commands::pip::operations::Modifications;
 | 
				
			||||||
use crate::commands::project::environment::CachedEnvironment;
 | 
					use crate::commands::project::environment::CachedEnvironment;
 | 
				
			||||||
use crate::commands::project::lock::LockMode;
 | 
					use crate::commands::project::lock::LockMode;
 | 
				
			||||||
use crate::commands::project::{
 | 
					use crate::commands::project::{
 | 
				
			||||||
    default_dependency_groups, validate_requires_python, validate_script_requires_python,
 | 
					    default_dependency_groups, validate_requires_python, DependencyGroupsTarget,
 | 
				
			||||||
    DependencyGroupsTarget, EnvironmentSpecification, ProjectError, ScriptPython, WorkspacePython,
 | 
					    EnvironmentSpecification, ProjectError, ScriptInterpreter, WorkspacePython,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::commands::reporters::PythonDownloadReporter;
 | 
					use crate::commands::reporters::PythonDownloadReporter;
 | 
				
			||||||
use crate::commands::{diagnostics, project, ExitStatus};
 | 
					use crate::commands::{diagnostics, project, ExitStatus};
 | 
				
			||||||
| 
						 | 
					@ -181,52 +181,23 @@ pub(crate) async fn run(
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let ScriptPython {
 | 
					        // Discover the interpreter for the script.
 | 
				
			||||||
            source,
 | 
					        let interpreter = ScriptInterpreter::discover(
 | 
				
			||||||
            python_request,
 | 
					 | 
				
			||||||
            requires_python,
 | 
					 | 
				
			||||||
        } = ScriptPython::from_request(
 | 
					 | 
				
			||||||
            python.as_deref().map(PythonRequest::parse),
 | 
					 | 
				
			||||||
            None,
 | 
					 | 
				
			||||||
            &script,
 | 
					            &script,
 | 
				
			||||||
            no_config,
 | 
					            python.as_deref().map(PythonRequest::parse),
 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .await?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let client_builder = BaseClientBuilder::new()
 | 
					 | 
				
			||||||
            .connectivity(connectivity)
 | 
					 | 
				
			||||||
            .native_tls(native_tls)
 | 
					 | 
				
			||||||
            .allow_insecure_host(allow_insecure_host.to_vec());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let interpreter = PythonInstallation::find_or_download(
 | 
					 | 
				
			||||||
            python_request.as_ref(),
 | 
					 | 
				
			||||||
            EnvironmentPreference::Any,
 | 
					 | 
				
			||||||
            python_preference,
 | 
					            python_preference,
 | 
				
			||||||
            python_downloads,
 | 
					            python_downloads,
 | 
				
			||||||
            &client_builder,
 | 
					            connectivity,
 | 
				
			||||||
 | 
					            native_tls,
 | 
				
			||||||
 | 
					            allow_insecure_host,
 | 
				
			||||||
 | 
					            &install_mirrors,
 | 
				
			||||||
 | 
					            no_config,
 | 
				
			||||||
            cache,
 | 
					            cache,
 | 
				
			||||||
            Some(&download_reporter),
 | 
					            printer,
 | 
				
			||||||
            install_mirrors.python_install_mirror.as_deref(),
 | 
					 | 
				
			||||||
            install_mirrors.pypy_install_mirror.as_deref(),
 | 
					 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .await?
 | 
					        .await?
 | 
				
			||||||
        .into_interpreter();
 | 
					        .into_interpreter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some((requires_python, requires_python_source)) = requires_python {
 | 
					 | 
				
			||||||
            match validate_script_requires_python(
 | 
					 | 
				
			||||||
                &interpreter,
 | 
					 | 
				
			||||||
                None,
 | 
					 | 
				
			||||||
                &requires_python,
 | 
					 | 
				
			||||||
                &requires_python_source,
 | 
					 | 
				
			||||||
                &source,
 | 
					 | 
				
			||||||
            ) {
 | 
					 | 
				
			||||||
                Ok(()) => {}
 | 
					 | 
				
			||||||
                Err(err) => {
 | 
					 | 
				
			||||||
                    warn_user!("{err}");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Determine the working directory for the script.
 | 
					        // Determine the working directory for the script.
 | 
				
			||||||
        let script_dir = match &script {
 | 
					        let script_dir = match &script {
 | 
				
			||||||
            Pep723Item::Script(script) => std::path::absolute(&script.path)?
 | 
					            Pep723Item::Script(script) => std::path::absolute(&script.path)?
 | 
				
			||||||
| 
						 | 
					@ -592,7 +563,7 @@ pub(crate) async fn run(
 | 
				
			||||||
                project::get_or_init_environment(
 | 
					                project::get_or_init_environment(
 | 
				
			||||||
                    project.workspace(),
 | 
					                    project.workspace(),
 | 
				
			||||||
                    python.as_deref().map(PythonRequest::parse),
 | 
					                    python.as_deref().map(PythonRequest::parse),
 | 
				
			||||||
                    install_mirrors,
 | 
					                    &install_mirrors,
 | 
				
			||||||
                    python_preference,
 | 
					                    python_preference,
 | 
				
			||||||
                    python_downloads,
 | 
					                    python_downloads,
 | 
				
			||||||
                    connectivity,
 | 
					                    connectivity,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,7 +120,7 @@ pub(crate) async fn sync(
 | 
				
			||||||
    let venv = project::get_or_init_environment(
 | 
					    let venv = project::get_or_init_environment(
 | 
				
			||||||
        project.workspace(),
 | 
					        project.workspace(),
 | 
				
			||||||
        python.as_deref().map(PythonRequest::parse),
 | 
					        python.as_deref().map(PythonRequest::parse),
 | 
				
			||||||
        install_mirrors,
 | 
					        &install_mirrors,
 | 
				
			||||||
        python_preference,
 | 
					        python_preference,
 | 
				
			||||||
        python_downloads,
 | 
					        python_downloads,
 | 
				
			||||||
        connectivity,
 | 
					        connectivity,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,7 @@ pub(crate) async fn tree(
 | 
				
			||||||
                connectivity,
 | 
					                connectivity,
 | 
				
			||||||
                native_tls,
 | 
					                native_tls,
 | 
				
			||||||
                allow_insecure_host,
 | 
					                allow_insecure_host,
 | 
				
			||||||
                install_mirrors,
 | 
					                &install_mirrors,
 | 
				
			||||||
                no_config,
 | 
					                no_config,
 | 
				
			||||||
                cache,
 | 
					                cache,
 | 
				
			||||||
                printer,
 | 
					                printer,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue