Require --clear to remove virtual environments (#17757)
This has been in warnings since 0.8
This commit is contained in:
Generated
-1
@@ -7194,7 +7194,6 @@ dependencies = [
|
||||
"uv-python",
|
||||
"uv-shell",
|
||||
"uv-version",
|
||||
"uv-warnings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -26,7 +26,6 @@ uv-pypi-types = { workspace = true }
|
||||
uv-python = { workspace = true }
|
||||
uv-shell = { workspace = true }
|
||||
uv-version = { workspace = true }
|
||||
uv-warnings = { workspace = true }
|
||||
|
||||
console = { workspace = true }
|
||||
fs-err = { workspace = true }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -20,6 +20,13 @@ pub enum Error {
|
||||
NotFound(String),
|
||||
#[error(transparent)]
|
||||
Python(#[from] uv_python::managed::Error),
|
||||
#[error("A {name} already exists at `{}`. Use `--clear` to replace it", path.display())]
|
||||
Exists {
|
||||
/// The type of environment (e.g., "virtual environment").
|
||||
name: &'static str,
|
||||
/// The path to the existing environment.
|
||||
path: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
/// The value to use for the shell prompt when inside a virtual environment.
|
||||
|
||||
@@ -11,6 +11,7 @@ use itertools::Itertools;
|
||||
use owo_colors::OwoColorize;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use crate::{Error, Prompt};
|
||||
use uv_fs::{CWD, Simplified, cachedir};
|
||||
use uv_platform_tags::Os;
|
||||
use uv_preview::Preview;
|
||||
@@ -19,9 +20,6 @@ use uv_python::managed::{PythonMinorVersionLink, create_link_to_executable};
|
||||
use uv_python::{Interpreter, VirtualEnvironment};
|
||||
use uv_shell::escape_posix_for_single_quotes;
|
||||
use uv_version::version;
|
||||
use uv_warnings::warn_user_once;
|
||||
|
||||
use crate::{Error, Prompt};
|
||||
|
||||
/// Activation scripts for the environment, with dependent paths templated out.
|
||||
const ACTIVATE_TEMPLATES: &[(&str, &str)] = &[
|
||||
@@ -164,13 +162,12 @@ pub(crate) fn create(
|
||||
fs_err::create_dir_all(&location)?;
|
||||
}
|
||||
Some(false) => return err,
|
||||
// When we don't have a TTY, warn that the behavior will change in the future
|
||||
// When we don't have a TTY, require `--clear` explicitly.
|
||||
None => {
|
||||
warn_user_once!(
|
||||
"A {name} already exists at `{}`. In the future, uv will require `{}` to replace it",
|
||||
location.user_display(),
|
||||
"--clear".green(),
|
||||
);
|
||||
return Err(Error::Exists {
|
||||
name,
|
||||
path: location.to_path_buf(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2161,7 +2161,7 @@ fn venv_included_in_sdist() -> Result<()> {
|
||||
.child("pyproject.toml")
|
||||
.write_str(pyproject_toml)?;
|
||||
|
||||
context.venv().assert().success();
|
||||
context.venv().arg("--clear").assert().success();
|
||||
|
||||
// context.filters()
|
||||
uv_snapshot!(context.filters(), context.build(), @"
|
||||
|
||||
@@ -13839,7 +13839,13 @@ fn build_backend_wrong_wheel_platform() -> Result<()> {
|
||||
// (compatible host, incompatible host) x (compatible target, incompatible target)
|
||||
|
||||
// A Python 3.13 host with a 3.13 implicit target works.
|
||||
context.venv().arg("-p").arg("3.13").assert().success();
|
||||
context
|
||||
.venv()
|
||||
.arg("--clear")
|
||||
.arg("-p")
|
||||
.arg("3.13")
|
||||
.assert()
|
||||
.success();
|
||||
uv_snapshot!(context.filters(), context.pip_install().arg("./child"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
@@ -13853,7 +13859,13 @@ fn build_backend_wrong_wheel_platform() -> Result<()> {
|
||||
");
|
||||
|
||||
// A Python 3.13 host with a 3.12 explicit target fails.
|
||||
context.venv().arg("-p").arg("3.13").assert().success();
|
||||
context
|
||||
.venv()
|
||||
.arg("--clear")
|
||||
.arg("-p")
|
||||
.arg("3.13")
|
||||
.assert()
|
||||
.success();
|
||||
uv_snapshot!(context.filters(), context.pip_install().arg("--python-version").arg("3.12").arg("./child"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
@@ -13866,8 +13878,14 @@ fn build_backend_wrong_wheel_platform() -> Result<()> {
|
||||
");
|
||||
|
||||
// A python 3.12 host with a 3.13 explicit target works.
|
||||
context.venv().arg("-p").arg("3.13").assert().success();
|
||||
uv_snapshot!(context.filters(), context.pip_install().arg("--python-version").arg("3.13").arg("./child"), @"
|
||||
context
|
||||
.venv()
|
||||
.arg("--clear")
|
||||
.arg("-p")
|
||||
.arg("3.13")
|
||||
.assert()
|
||||
.success();
|
||||
uv_snapshot!(context.filters(), context.pip_install().arg("--python-version").arg("3.13").arg("./child"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -13875,13 +13893,18 @@ fn build_backend_wrong_wheel_platform() -> Result<()> {
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Prepared 1 package in [TIME]
|
||||
Uninstalled 1 package in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
~ py313==0.1.0 (from file://[TEMP_DIR]/child)
|
||||
+ py313==0.1.0 (from file://[TEMP_DIR]/child)
|
||||
");
|
||||
|
||||
// A Python 3.13 host with a 3.12 explicit target fails.
|
||||
context.venv().arg("-p").arg("3.13").assert().success();
|
||||
context
|
||||
.venv()
|
||||
.arg("--clear")
|
||||
.arg("-p")
|
||||
.arg("3.13")
|
||||
.assert()
|
||||
.success();
|
||||
uv_snapshot!(context.filters(), context.pip_install().arg("--python-version").arg("3.12").arg("./child"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
@@ -13916,7 +13939,13 @@ fn build_backend_wrong_wheel_platform() -> Result<()> {
|
||||
.touch()?;
|
||||
|
||||
// A build host of 3.13 works.
|
||||
context.venv().arg("-p").arg("3.13").assert().success();
|
||||
context
|
||||
.venv()
|
||||
.arg("--clear")
|
||||
.arg("-p")
|
||||
.arg("3.13")
|
||||
.assert()
|
||||
.success();
|
||||
uv_snapshot!(context.filters(), context.pip_install().arg("--python-version").arg("3.12").arg("."), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
@@ -13930,7 +13959,13 @@ fn build_backend_wrong_wheel_platform() -> Result<()> {
|
||||
");
|
||||
|
||||
// A build host of 3.12 fails.
|
||||
context.venv().arg("-p").arg("3.12").assert().success();
|
||||
context
|
||||
.venv()
|
||||
.arg("--clear")
|
||||
.arg("-p")
|
||||
.arg("3.12")
|
||||
.assert()
|
||||
.success();
|
||||
uv_snapshot!(context.filters(), context.pip_install().arg("--python-version").arg("3.12").arg("."), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
|
||||
@@ -197,7 +197,7 @@ fn find_uv_bin_base_prefix() {
|
||||
"
|
||||
);
|
||||
|
||||
context.venv().assert().success();
|
||||
context.venv().arg("--clear").assert().success();
|
||||
|
||||
// Mutate `base_prefix` to simulate lookup in a system Python installation
|
||||
uv_snapshot!(context.filters(), context.python_command()
|
||||
|
||||
@@ -1478,7 +1478,12 @@ fn run_with_overlay_interpreter() -> Result<()> {
|
||||
");
|
||||
|
||||
// Switch to a relocatable virtual environment.
|
||||
context.venv().arg("--relocatable").assert().success();
|
||||
context
|
||||
.venv()
|
||||
.arg("--allow-existing")
|
||||
.arg("--relocatable")
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
// Cleanup previous shutil
|
||||
fs_err::remove_file(context.temp_dir.child("main"))?;
|
||||
|
||||
+33
-37
@@ -36,16 +36,16 @@ fn create_venv() {
|
||||
uv_snapshot!(context.filters(), context.venv()
|
||||
.arg(context.venv.as_os_str())
|
||||
.arg("--python")
|
||||
.arg("3.12"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
.arg("3.12"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
error: Failed to create virtual environment
|
||||
Caused by: A virtual environment already exists at `[VENV]/`. Use `--clear` to replace it
|
||||
"
|
||||
);
|
||||
|
||||
@@ -221,7 +221,7 @@ fn virtual_empty() -> Result<()> {
|
||||
wow = "someconfig"
|
||||
"#})?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv(), @"
|
||||
uv_snapshot!(context.filters(), context.venv().arg("--clear"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -229,7 +229,6 @@ fn virtual_empty() -> Result<()> {
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
");
|
||||
|
||||
@@ -250,7 +249,7 @@ fn virtual_dependency_group() -> Result<()> {
|
||||
dev = ["sniffio"]
|
||||
"#})?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv(), @"
|
||||
uv_snapshot!(context.filters(), context.venv().arg("--clear"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -258,7 +257,6 @@ fn virtual_dependency_group() -> Result<()> {
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
");
|
||||
|
||||
@@ -1511,7 +1509,19 @@ fn venv_python_preference() {
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
");
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv().arg("--no-managed-python"), @"
|
||||
uv_snapshot!(context.filters(), context.venv().arg("--no-managed-python"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.11.[X] interpreter at: [PYTHON-3.11]
|
||||
Creating virtual environment at: .venv
|
||||
error: Failed to create virtual environment
|
||||
Caused by: A virtual environment already exists at `.venv`. Use `--clear` to replace it
|
||||
");
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv().arg("--clear").arg("--no-managed-python"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1519,23 +1529,22 @@ fn venv_python_preference() {
|
||||
----- stderr -----
|
||||
Using CPython 3.11.[X] interpreter at: [PYTHON-3.11]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
");
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv().arg("--no-managed-python"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
uv_snapshot!(context.filters(), context.venv(), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.11.[X] interpreter at: [PYTHON-3.11]
|
||||
Using CPython 3.12.[X]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
error: Failed to create virtual environment
|
||||
Caused by: A virtual environment already exists at `.venv`. Use `--clear` to replace it
|
||||
");
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv(), @"
|
||||
uv_snapshot!(context.filters(), context.venv().arg("--clear").arg("--managed-python"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1543,19 +1552,6 @@ fn venv_python_preference() {
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
");
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv().arg("--managed-python"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
");
|
||||
}
|
||||
@@ -1653,11 +1649,12 @@ fn create_venv_symlink_recreate_preservation() -> Result<()> {
|
||||
// Verify symlink is preserved after first creation
|
||||
assert!(symlink_path.path().is_symlink());
|
||||
|
||||
// Run uv venv again WITHOUT --clear to test recreation behavior
|
||||
// Run uv venv again with --clear to test symlink preservation during recreation
|
||||
uv_snapshot!(context.filters(), context.venv()
|
||||
.arg(symlink_path.as_os_str())
|
||||
.arg("--clear")
|
||||
.arg("--python")
|
||||
.arg("3.12"), @"
|
||||
.arg("3.12"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1665,7 +1662,6 @@ fn create_venv_symlink_recreate_preservation() -> Result<()> {
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
"
|
||||
);
|
||||
@@ -1717,11 +1713,12 @@ fn create_venv_nested_symlink_preservation() -> Result<()> {
|
||||
assert!(symlink_path.path().is_symlink());
|
||||
assert!(intermediate_link.path().is_symlink());
|
||||
|
||||
// Run uv venv again to test nested symlink preservation during recreation
|
||||
// Run uv venv again with --clear to test nested symlink preservation during recreation
|
||||
uv_snapshot!(context.filters(), context.venv()
|
||||
.arg(symlink_path.as_os_str())
|
||||
.arg("--clear")
|
||||
.arg("--python")
|
||||
.arg("3.12"), @"
|
||||
.arg("3.12"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1729,7 +1726,6 @@ fn create_venv_nested_symlink_preservation() -> Result<()> {
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
warning: A virtual environment already exists at `.venv`. In the future, uv will require `--clear` to replace it
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
"
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user