Skip to content

Commit

Permalink
Avoid creating .venv in uv add --frozen and uv add --no-sync` (#8980
Browse files Browse the repository at this point in the history
)

## Summary

Closes #8977.
  • Loading branch information
charliermarsh authored Nov 10, 2024
1 parent 73ad9f9 commit a2e90b7
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 27 deletions.
94 changes: 67 additions & 27 deletions crates/uv/src/commands/project/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ use crate::commands::pip::loggers::{
use crate::commands::pip::operations::Modifications;
use crate::commands::project::lock::LockMode;
use crate::commands::project::{
init_script_python_requirement, validate_script_requires_python, ProjectError, ScriptPython,
init_script_python_requirement, validate_script_requires_python, ProjectError,
ProjectInterpreter, ScriptPython,
};
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
use crate::commands::{diagnostics, pip, project, ExitStatus, SharedState};
Expand Down Expand Up @@ -214,22 +215,43 @@ pub(crate) async fn add(
}
}

// Discover or create the virtual environment.
let venv = project::get_or_init_environment(
project.workspace(),
python.as_deref().map(PythonRequest::parse),
python_preference,
python_downloads,
connectivity,
native_tls,
allow_insecure_host,
no_config,
cache,
printer,
)
.await?;
if frozen || no_sync {
// Discover the interpreter.
let interpreter = ProjectInterpreter::discover(
project.workspace(),
project_dir,
python.as_deref().map(PythonRequest::parse),
python_preference,
python_downloads,
connectivity,
native_tls,
allow_insecure_host,
no_config,
cache,
printer,
)
.await?
.into_interpreter();

Target::Project(project, Box::new(PythonTarget::Interpreter(interpreter)))
} else {
// Discover or create the virtual environment.
let venv = project::get_or_init_environment(
project.workspace(),
python.as_deref().map(PythonRequest::parse),
python_preference,
python_downloads,
connectivity,
native_tls,
allow_insecure_host,
no_config,
cache,
printer,
)
.await?;

Target::Project(project, venv)
Target::Project(project, Box::new(PythonTarget::Environment(venv)))
}
};

let client_builder = BaseClientBuilder::new()
Expand Down Expand Up @@ -576,8 +598,8 @@ pub(crate) async fn add(
}
};

let (project, venv) = match target {
Target::Project(project, venv) => (project, venv),
let (project, environment) = match target {
Target::Project(project, environment) => (project, environment),
// If `--script`, exit early. There's no reason to lock and sync.
Target::Script(script, _) => {
writeln!(
Expand Down Expand Up @@ -627,10 +649,9 @@ pub(crate) async fn add(
project,
&mut toml,
&edits,
&venv,
&environment,
state,
locked,
no_sync,
&dependency_type,
raw_sources,
settings.as_ref(),
Expand Down Expand Up @@ -688,10 +709,9 @@ async fn lock_and_sync(
mut project: VirtualProject,
toml: &mut PyProjectTomlMut,
edits: &[DependencyEdit],
venv: &PythonEnvironment,
environment: &PythonTarget,
state: SharedState,
locked: bool,
no_sync: bool,
dependency_type: &DependencyType,
raw_sources: bool,
settings: ResolverInstallerSettingsRef<'_>,
Expand All @@ -704,9 +724,9 @@ async fn lock_and_sync(
printer: Printer,
) -> Result<(), ProjectError> {
let mode = if locked {
LockMode::Locked(venv.interpreter())
LockMode::Locked(environment.interpreter())
} else {
LockMode::Write(venv.interpreter())
LockMode::Write(environment.interpreter())
};

let mut lock = project::lock::do_safe_lock(
Expand Down Expand Up @@ -846,9 +866,10 @@ async fn lock_and_sync(
}
}

if no_sync {
let PythonTarget::Environment(venv) = environment else {
// If we're not syncing, exit early.
return Ok(());
}
};

// Sync the environment.
let (extras, dev) = match dependency_type {
Expand Down Expand Up @@ -1024,8 +1045,9 @@ fn resolve_requirement(
enum Target {
/// A PEP 723 script, with inline metadata.
Script(Pep723Script, Box<Interpreter>),

/// A project with a `pyproject.toml`.
Project(VirtualProject, PythonEnvironment),
Project(VirtualProject, Box<PythonTarget>),
}

impl Target {
Expand All @@ -1038,6 +1060,24 @@ impl Target {
}
}

/// A Python [`Interpreter`] or [`PythonEnvironment`] for a project.
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
enum PythonTarget {
Interpreter(Interpreter),
Environment(PythonEnvironment),
}

impl PythonTarget {
/// Return the [`Interpreter`] for the project.
fn interpreter(&self) -> &Interpreter {
match self {
Self::Interpreter(interpreter) => interpreter,
Self::Environment(venv) => venv.interpreter(),
}
}
}

#[derive(Debug, Clone)]
struct DependencyEdit {
dependency_type: DependencyType,
Expand Down
10 changes: 10 additions & 0 deletions crates/uv/tests/it/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3675,6 +3675,9 @@ fn add_puts_default_indentation_in_pyproject_toml_if_not_observed() -> Result<()
fn add_frozen() -> Result<()> {
let context = TestContext::new("3.12");

// Remove the virtual environment.
fs_err::remove_dir_all(&context.venv)?;

let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(indoc! {r#"
[project]
Expand All @@ -3694,6 +3697,7 @@ fn add_frozen() -> Result<()> {
----- stdout -----
----- stderr -----
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
"###);

let pyproject_toml = context.read("pyproject.toml");
Expand All @@ -3719,6 +3723,7 @@ fn add_frozen() -> Result<()> {
});

assert!(!context.temp_dir.join("uv.lock").exists());
assert!(!context.venv.exists());

Ok(())
}
Expand All @@ -3728,6 +3733,9 @@ fn add_frozen() -> Result<()> {
fn add_no_sync() -> Result<()> {
let context = TestContext::new("3.12");

// Remove the virtual environment.
fs_err::remove_dir_all(&context.venv)?;

let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(indoc! {r#"
[project]
Expand All @@ -3747,6 +3755,7 @@ fn add_no_sync() -> Result<()> {
----- stdout -----
----- stderr -----
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Resolved 4 packages in [TIME]
"###);

Expand All @@ -3773,6 +3782,7 @@ fn add_no_sync() -> Result<()> {
});

assert!(context.temp_dir.join("uv.lock").exists());
assert!(!context.venv.exists());

Ok(())
}
Expand Down

0 comments on commit a2e90b7

Please sign in to comment.