From 74112553bf3c1e675dddc5ce25c3f7d3b6f49656 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 26 Dec 2024 10:43:55 -0500 Subject: [PATCH] Avoid cloning script when discovering interpreter (#10172) --- crates/uv-scripts/src/lib.rs | 41 +++++++++++++++++++++++++++ crates/uv/src/commands/project/add.rs | 4 +-- crates/uv/src/commands/project/mod.rs | 6 ++-- crates/uv/src/commands/project/run.rs | 2 +- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/crates/uv-scripts/src/lib.rs b/crates/uv-scripts/src/lib.rs index e5a992e61b8a..cdcccc96e613 100644 --- a/crates/uv-scripts/src/lib.rs +++ b/crates/uv-scripts/src/lib.rs @@ -56,6 +56,47 @@ impl Pep723Item { } } +/// A reference to a PEP 723 item. +#[derive(Debug)] +pub enum Pep723ItemRef<'item> { + /// A PEP 723 script read from disk. + Script(&'item Pep723Script), + /// A PEP 723 script provided via `stdin`. + Stdin(&'item Pep723Metadata), + /// A PEP 723 script provided via a remote URL. + Remote(&'item Pep723Metadata), +} + +impl Pep723ItemRef<'_> { + /// Return the [`Pep723Metadata`] associated with the item. + pub fn metadata(&self) -> &Pep723Metadata { + match self { + Self::Script(script) => &script.metadata, + Self::Stdin(metadata) => metadata, + Self::Remote(metadata) => metadata, + } + } + + /// Return the path of the PEP 723 item, if any. + pub fn path(&self) -> Option<&Path> { + match self { + Self::Script(script) => Some(&script.path), + Self::Stdin(_) => None, + Self::Remote(_) => None, + } + } +} + +impl<'item> From<&'item Pep723Item> for Pep723ItemRef<'item> { + fn from(item: &'item Pep723Item) -> Self { + match item { + Pep723Item::Script(script) => Self::Script(script), + Pep723Item::Stdin(metadata) => Self::Stdin(metadata), + Pep723Item::Remote(metadata) => Self::Remote(metadata), + } + } +} + /// A PEP 723 script, including its [`Pep723Metadata`]. #[derive(Debug, Clone)] pub struct Pep723Script { diff --git a/crates/uv/src/commands/project/add.rs b/crates/uv/src/commands/project/add.rs index 8c7be904cd7a..1220d532dcda 100644 --- a/crates/uv/src/commands/project/add.rs +++ b/crates/uv/src/commands/project/add.rs @@ -29,7 +29,7 @@ use uv_pypi_types::{redact_credentials, ParsedUrl, RequirementSource, VerbatimPa use uv_python::{Interpreter, PythonDownloads, PythonEnvironment, PythonPreference, PythonRequest}; use uv_requirements::{NamedRequirementsResolver, RequirementsSource, RequirementsSpecification}; use uv_resolver::FlatIndex; -use uv_scripts::{Pep723Item, Pep723Script}; +use uv_scripts::{Pep723ItemRef, Pep723Script}; use uv_settings::PythonInstallMirrors; use uv_types::{BuildIsolation, HashStrategy}; use uv_warnings::warn_user_once; @@ -158,7 +158,7 @@ pub(crate) async fn add( // Discover the interpreter. let interpreter = ScriptInterpreter::discover( - &Pep723Item::Script(script.clone()), + Pep723ItemRef::Script(&script), python.as_deref().map(PythonRequest::parse), python_preference, python_downloads, diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index d3506c6164f8..d7807c29a614 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -35,7 +35,7 @@ use uv_resolver::{ FlatIndex, Lock, OptionsBuilder, PythonRequirement, RequiresPython, ResolverEnvironment, ResolverOutput, }; -use uv_scripts::Pep723Item; +use uv_scripts::Pep723ItemRef; use uv_settings::PythonInstallMirrors; use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy}; use uv_warnings::{warn_user, warn_user_once}; @@ -444,7 +444,7 @@ pub(crate) struct ScriptInterpreter(Interpreter); impl ScriptInterpreter { /// Discover the interpreter to use for the current [`Pep723Item`]. pub(crate) async fn discover( - script: &Pep723Item, + script: Pep723ItemRef<'_>, python_request: Option, python_preference: PythonPreference, python_downloads: PythonDownloads, @@ -795,7 +795,7 @@ impl ScriptPython { pub(crate) async fn from_request( python_request: Option, workspace: Option<&Workspace>, - script: &Pep723Item, + script: Pep723ItemRef<'_>, no_config: bool, ) -> Result { // First, discover a requirement from the workspace diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index 04f6cd9ac4b5..31678867b8f9 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -185,7 +185,7 @@ pub(crate) async fn run( // Discover the interpreter for the script. let interpreter = ScriptInterpreter::discover( - &script, + (&script).into(), python.as_deref().map(PythonRequest::parse), python_preference, python_downloads,