Use VenvCreationPolicy instead of clear and allow-existing bools

This commit is contained in:
John Mumm 2025-07-01 12:30:29 +02:00
parent dc2473af28
commit 6561537b50
No known key found for this signature in database
GPG key ID: 73D2271AFDC26EA8
9 changed files with 53 additions and 41 deletions

View file

@ -40,6 +40,7 @@ use uv_pypi_types::VerbatimParsedUrl;
use uv_python::{Interpreter, PythonEnvironment};
use uv_static::EnvVars;
use uv_types::{AnyErrorBuild, BuildContext, BuildIsolation, BuildStack, SourceBuildTrait};
use uv_virtualenv::VenvCreationPolicy;
use uv_warnings::warn_user_once;
use uv_workspace::WorkspaceCache;
@ -333,8 +334,7 @@ impl SourceBuild {
interpreter.clone(),
uv_virtualenv::Prompt::None,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
false,

View file

@ -5,6 +5,7 @@ use uv_configuration::PreviewMode;
use uv_dirs::user_executable_directory;
use uv_pep440::Version;
use uv_pep508::{InvalidNameError, PackageName};
use uv_virtualenv::VenvCreationPolicy;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
@ -285,8 +286,7 @@ impl InstalledTools {
interpreter,
uv_virtualenv::Prompt::None,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
false,

View file

@ -6,6 +6,8 @@ use thiserror::Error;
use uv_configuration::PreviewMode;
use uv_python::{Interpreter, PythonEnvironment};
pub use virtualenv::VenvCreationPolicy;
mod virtualenv;
#[derive(Debug, Error)]
@ -50,8 +52,7 @@ pub fn create_venv(
interpreter: Interpreter,
prompt: Prompt,
system_site_packages: bool,
allow_existing: bool,
clear: bool,
venv_creation_policy: VenvCreationPolicy,
relocatable: bool,
seed: bool,
upgradeable: bool,
@ -63,8 +64,7 @@ pub fn create_venv(
&interpreter,
prompt,
system_site_packages,
allow_existing,
clear,
venv_creation_policy,
relocatable,
seed,
upgradeable,

View file

@ -54,8 +54,7 @@ pub(crate) fn create(
interpreter: &Interpreter,
prompt: Prompt,
system_site_packages: bool,
allow_existing: bool,
clear: bool,
venv_creation_policy: VenvCreationPolicy,
relocatable: bool,
seed: bool,
upgradeable: bool,
@ -86,13 +85,15 @@ pub(crate) fn create(
format!("File exists at `{}`", location.user_display()),
)));
} else if metadata.is_dir() {
let confirmation_required = !clear && !allow_existing;
let confirmed_clear = confirmation_required && confirm_clear(location)?;
let confirmed_clear = venv_creation_policy == VenvCreationPolicy::FailIfNotEmpty
&& confirm_clear(location)?;
if allow_existing {
if venv_creation_policy == VenvCreationPolicy::OverwriteFiles {
debug!("Allowing existing directory due to `--allow-existing`");
} else if clear || confirmed_clear {
if clear {
} else if venv_creation_policy == VenvCreationPolicy::RemoveDirectory
|| confirmed_clear
{
if venv_creation_policy == VenvCreationPolicy::RemoveDirectory {
debug!("Removing existing directory due to `--clear`");
} else {
debug!("Removing existing directory");
@ -491,6 +492,17 @@ fn confirm_clear(location: &Path) -> Result<bool, io::Error> {
}
}
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
pub enum VenvCreationPolicy {
/// Do not create a virtual environment if a non-empty directory exists.
#[default]
FailIfNotEmpty,
/// Overwrite existing virtual environment files.
OverwriteFiles,
/// Remove existing directory.
RemoveDirectory,
}
#[derive(Debug, Copy, Clone)]
enum WindowsExecutable {
/// The `python.exe` executable (or `venvlauncher.exe` launcher shim).

View file

@ -8,6 +8,7 @@ use uv_configuration::{Concurrency, Constraints, PreviewMode};
use uv_distribution_types::{Name, Resolution};
use uv_fs::PythonExt;
use uv_python::{Interpreter, PythonEnvironment, canonicalize_executable};
use uv_virtualenv::VenvCreationPolicy;
use crate::commands::pip::loggers::{InstallLogger, ResolveLogger};
use crate::commands::pip::operations::Modifications;
@ -96,8 +97,7 @@ impl CachedEnvironment {
interpreter,
uv_virtualenv::Prompt::None,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
true,
false,
false,

View file

@ -43,6 +43,7 @@ use uv_scripts::Pep723ItemRef;
use uv_settings::PythonInstallMirrors;
use uv_static::EnvVars;
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy};
use uv_virtualenv::VenvCreationPolicy;
use uv_warnings::{warn_user, warn_user_once};
use uv_workspace::dependency_groups::DependencyGroupError;
use uv_workspace::pyproject::PyProjectToml;
@ -1308,8 +1309,7 @@ impl ProjectEnvironment {
interpreter,
prompt,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
upgradeable,
@ -1348,8 +1348,7 @@ impl ProjectEnvironment {
interpreter,
prompt,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
upgradeable,
@ -1487,8 +1486,7 @@ impl ScriptEnvironment {
interpreter,
prompt,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
upgradeable,
@ -1524,8 +1522,7 @@ impl ScriptEnvironment {
interpreter,
prompt,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
upgradeable,

View file

@ -37,6 +37,7 @@ use uv_scripts::Pep723Item;
use uv_settings::PythonInstallMirrors;
use uv_shell::runnable::WindowsRunnable;
use uv_static::EnvVars;
use uv_virtualenv::VenvCreationPolicy;
use uv_warnings::warn_user;
use uv_workspace::{DiscoveryOptions, VirtualProject, Workspace, WorkspaceCache, WorkspaceError};
@ -452,8 +453,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
interpreter,
uv_virtualenv::Prompt::None,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
false,
@ -657,8 +657,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
interpreter,
uv_virtualenv::Prompt::None,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
false,
@ -887,8 +886,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
interpreter,
uv_virtualenv::Prompt::None,
false,
false,
true,
VenvCreationPolicy::RemoveDirectory,
false,
false,
false,

View file

@ -29,6 +29,7 @@ use uv_resolver::{ExcludeNewer, FlatIndex};
use uv_settings::PythonInstallMirrors;
use uv_shell::{Shell, shlex_posix, shlex_windows};
use uv_types::{AnyErrorBuild, BuildContext, BuildIsolation, BuildStack, HashStrategy};
use uv_virtualenv::VenvCreationPolicy;
use uv_warnings::warn_user;
use uv_workspace::{DiscoveryOptions, VirtualProject, WorkspaceCache, WorkspaceError};
@ -60,8 +61,7 @@ pub(crate) async fn venv(
prompt: uv_virtualenv::Prompt,
system_site_packages: bool,
seed: bool,
allow_existing: bool,
clear: bool,
venv_creation_policy: VenvCreationPolicy,
exclude_newer: Option<ExcludeNewer>,
concurrency: Concurrency,
no_config: bool,
@ -87,8 +87,7 @@ pub(crate) async fn venv(
seed,
python_preference,
python_downloads,
allow_existing,
clear,
venv_creation_policy,
exclude_newer,
concurrency,
no_config,
@ -145,8 +144,7 @@ async fn venv_impl(
seed: bool,
python_preference: PythonPreference,
python_downloads: PythonDownloads,
allow_existing: bool,
clear: bool,
venv_creation_policy: VenvCreationPolicy,
exclude_newer: Option<ExcludeNewer>,
concurrency: Concurrency,
no_config: bool,
@ -291,8 +289,7 @@ async fn venv_impl(
interpreter,
prompt,
system_site_packages,
allow_existing,
clear,
venv_creation_policy,
relocatable,
seed,
upgradeable,

View file

@ -41,6 +41,7 @@ use uv_requirements_txt::RequirementsTxtRequirement;
use uv_scripts::{Pep723Error, Pep723Item, Pep723ItemRef, Pep723Metadata, Pep723Script};
use uv_settings::{Combine, FilesystemOptions, Options};
use uv_static::EnvVars;
use uv_virtualenv::VenvCreationPolicy;
use uv_warnings::{warn_user, warn_user_once};
use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceCache};
@ -1026,6 +1027,14 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
let python_request: Option<PythonRequest> =
args.settings.python.as_deref().map(PythonRequest::parse);
let venv_creation_policy = if args.allow_existing {
VenvCreationPolicy::OverwriteFiles
} else if args.clear {
VenvCreationPolicy::RemoveDirectory
} else {
VenvCreationPolicy::default()
};
commands::venv(
&project_dir,
args.path,
@ -1042,8 +1051,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
uv_virtualenv::Prompt::from_args(prompt),
args.system_site_packages,
args.seed,
args.allow_existing,
args.clear,
venv_creation_policy,
args.settings.exclude_newer,
globals.concurrency,
cli.top_level.no_config,