Add support for respecting VIRTUAL_ENV in project commands via --active (#11189)

I think `UV_PROJECT_ENVIRONMENT` is too complicated for use-cases where
the user wants to sync to the active environment. I don't see a
compelling reason not to make opt-in easier. I see a lot of questions
about how to deal with this warning in the issue tracker, but it seems
painful to collect them here for posterity.

A notable behavior here — we'll treat this as equivalent to
`UV_PROJECT_ENVIRONMENT` so... if you point us to a valid virtual
environment that needs to be recreated for some reason (e.g., new Python
version request), we'll happily delete it and start over.
This commit is contained in:
Zanie Blue 2025-02-05 10:12:19 -06:00 committed by GitHub
parent 6f8d9b85d8
commit 989b103171
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 368 additions and 33 deletions

View file

@ -2805,6 +2805,19 @@ pub struct RunArgs {
#[arg(long)]
pub isolated: bool,
/// Prefer the active virtual environment over the project's virtual environment.
///
/// If the project virtual environment is active or no virtual environment is active, this has
/// no effect.
#[arg(long, overrides_with = "no_active")]
pub active: bool,
/// Prefer project's virtual environment over an active environment.
///
/// This is the default behavior.
#[arg(long, overrides_with = "active", hide = true)]
pub no_active: bool,
/// Avoid syncing the virtual environment.
///
/// Implies `--frozen`, as the project dependencies will be ignored (i.e., the lockfile will not
@ -3004,6 +3017,19 @@ pub struct SyncArgs {
#[arg(long, overrides_with("inexact"), hide = true)]
pub exact: bool,
/// Prefer the active virtual environment over the project's virtual environment.
///
/// If the project virtual environment is active or no virtual environment is active, this has
/// no effect.
#[arg(long, overrides_with = "no_active")]
pub active: bool,
/// Prefer project's virtual environment over an active environment.
///
/// This is the default behavior.
#[arg(long, overrides_with = "active", hide = true)]
pub no_active: bool,
/// Do not install the current project.
///
/// By default, the current project is installed into the environment with all of its
@ -3247,6 +3273,19 @@ pub struct AddArgs {
#[arg(long, env = EnvVars::UV_FROZEN, value_parser = clap::builder::BoolishValueParser::new(), conflicts_with = "locked")]
pub frozen: bool,
/// Prefer the active virtual environment over the project's virtual environment.
///
/// If the project virtual environment is active or no virtual environment is active, this has
/// no effect.
#[arg(long, overrides_with = "no_active")]
pub active: bool,
/// Prefer project's virtual environment over an active environment.
///
/// This is the default behavior.
#[arg(long, overrides_with = "active", hide = true)]
pub no_active: bool,
#[command(flatten)]
pub installer: ResolverInstallerArgs,
@ -3313,6 +3352,19 @@ pub struct RemoveArgs {
#[arg(long, env = EnvVars::UV_NO_SYNC, value_parser = clap::builder::BoolishValueParser::new(), conflicts_with = "frozen")]
pub no_sync: bool,
/// Prefer the active virtual environment over the project's virtual environment.
///
/// If the project virtual environment is active or no virtual environment is active, this has
/// no effect.
#[arg(long, overrides_with = "no_active")]
pub active: bool,
/// Prefer project's virtual environment over an active environment.
///
/// This is the default behavior.
#[arg(long, overrides_with = "active", hide = true)]
pub no_active: bool,
/// Assert that the `uv.lock` will remain unchanged.
///
/// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,

View file

@ -538,7 +538,7 @@ impl Workspace {
///
/// If `UV_PROJECT_ENVIRONMENT` is set, it will take precedence. If a relative path is provided,
/// it is resolved relative to the install path.
pub fn venv(&self) -> PathBuf {
pub fn venv(&self, active: bool) -> PathBuf {
/// Resolve the `UV_PROJECT_ENVIRONMENT` value, if any.
fn from_project_environment_variable(workspace: &Workspace) -> Option<PathBuf> {
let value = std::env::var_os(EnvVars::UV_PROJECT_ENVIRONMENT)?;
@ -606,12 +606,24 @@ impl Workspace {
// Warn if it conflicts with `VIRTUAL_ENV`
if let Some(from_virtual_env) = from_virtual_env_variable() {
if !is_same_dir(&from_virtual_env, &project_env).unwrap_or(false) {
if active {
debug!(
"Using active virtual environment `{}` instead of project environment `{}`",
from_virtual_env.user_display(),
project_env.user_display()
);
return from_virtual_env;
}
warn_user_once!(
"`VIRTUAL_ENV={}` does not match the project environment path `{}` and will be ignored",
"`VIRTUAL_ENV={}` does not match the project environment path `{}` and will be ignored; use `--active` to target the active environment instead",
from_virtual_env.user_display(),
project_env.user_display()
);
}
} else {
debug!(
"Use of the active virtual environment was requested, but `VIRTUAL_ENV` is not set"
);
}
project_env

View file

@ -61,6 +61,7 @@ pub(crate) async fn add(
project_dir: &Path,
locked: bool,
frozen: bool,
active: bool,
no_sync: bool,
requirements: Vec<RequirementsSource>,
editable: Option<bool>,
@ -213,6 +214,7 @@ pub(crate) async fn add(
allow_insecure_host,
&install_mirrors,
no_config,
active,
cache,
printer,
)
@ -231,6 +233,7 @@ pub(crate) async fn add(
connectivity,
native_tls,
allow_insecure_host,
active,
no_config,
cache,
printer,

View file

@ -163,6 +163,7 @@ pub(crate) async fn export(
allow_insecure_host,
&install_mirrors,
no_config,
false,
cache,
printer,
)

View file

@ -121,6 +121,7 @@ pub(crate) async fn lock(
allow_insecure_host,
&install_mirrors,
no_config,
false,
cache,
printer,
)

View file

@ -602,6 +602,7 @@ impl ProjectInterpreter {
allow_insecure_host: &[TrustedHost],
install_mirrors: &PythonInstallMirrors,
no_config: bool,
active: bool,
cache: &Cache,
printer: Printer,
) -> Result<Self, ProjectError> {
@ -614,7 +615,7 @@ impl ProjectInterpreter {
.await?;
// Read from the virtual environment first.
let venv = workspace.venv();
let venv = workspace.venv(active);
match PythonEnvironment::from_root(&venv, cache) {
Ok(venv) => {
if python_request.as_ref().map_or(true, |request| {
@ -924,6 +925,7 @@ pub(crate) async fn get_or_init_environment(
native_tls: bool,
allow_insecure_host: &[TrustedHost],
no_config: bool,
active: bool,
cache: &Cache,
printer: Printer,
) -> Result<PythonEnvironment, ProjectError> {
@ -938,6 +940,7 @@ pub(crate) async fn get_or_init_environment(
allow_insecure_host,
install_mirrors,
no_config,
active,
cache,
printer,
)
@ -948,7 +951,7 @@ pub(crate) async fn get_or_init_environment(
// Otherwise, create a virtual environment with the discovered interpreter.
ProjectInterpreter::Interpreter(interpreter) => {
let venv = workspace.venv();
let venv = workspace.venv(active);
// Avoid removing things that are not virtual environments
let should_remove = match (venv.try_exists(), venv.join("pyvenv.cfg").try_exists()) {

View file

@ -43,6 +43,7 @@ pub(crate) async fn remove(
project_dir: &Path,
locked: bool,
frozen: bool,
active: bool,
no_sync: bool,
packages: Vec<PackageName>,
dependency_type: DependencyType,
@ -209,6 +210,7 @@ pub(crate) async fn remove(
allow_insecure_host,
&install_mirrors,
no_config,
active,
cache,
printer,
)
@ -228,6 +230,7 @@ pub(crate) async fn remove(
native_tls,
allow_insecure_host,
no_config,
active,
cache,
printer,
)

View file

@ -65,6 +65,7 @@ pub(crate) async fn run(
show_resolution: bool,
locked: bool,
frozen: bool,
active: bool,
no_sync: bool,
isolated: bool,
all_packages: bool,
@ -666,6 +667,7 @@ pub(crate) async fn run(
native_tls,
allow_insecure_host,
no_config,
active,
cache,
printer,
)

View file

@ -45,6 +45,7 @@ pub(crate) async fn sync(
project_dir: &Path,
locked: bool,
frozen: bool,
active: bool,
all_packages: bool,
package: Option<PackageName>,
extras: ExtrasSpecification,
@ -125,6 +126,7 @@ pub(crate) async fn sync(
native_tls,
allow_insecure_host,
no_config,
active,
cache,
printer,
)

View file

@ -118,6 +118,7 @@ pub(crate) async fn tree(
allow_insecure_host,
&install_mirrors,
no_config,
false,
cache,
printer,
)

View file

@ -187,7 +187,7 @@ async fn venv_impl(
// This isn't strictly necessary and we may want to change it later, but this
// avoids a breaking change when adding project environment support to `uv venv`.
(project.workspace().install_path() == project_dir)
.then(|| project.workspace().venv())
.then(|| project.workspace().venv(false))
})
.unwrap_or(PathBuf::from(".venv")),
);

View file

@ -1484,6 +1484,7 @@ async fn run_project(
args.show_resolution || globals.verbose > 0,
args.locked,
args.frozen,
args.active,
args.no_sync,
args.isolated,
args.all_packages,
@ -1528,6 +1529,7 @@ async fn run_project(
project_dir,
args.locked,
args.frozen,
args.active,
args.all_packages,
args.package,
args.extras,
@ -1619,6 +1621,7 @@ async fn run_project(
project_dir,
args.locked,
args.frozen,
args.active,
args.no_sync,
requirements,
args.editable,
@ -1671,6 +1674,7 @@ async fn run_project(
project_dir,
args.locked,
args.frozen,
args.active,
args.no_sync,
args.packages,
args.dependency_type,

View file

@ -281,6 +281,7 @@ pub(crate) struct RunSettings {
pub(crate) all_packages: bool,
pub(crate) package: Option<PackageName>,
pub(crate) no_project: bool,
pub(crate) active: bool,
pub(crate) no_sync: bool,
pub(crate) python: Option<String>,
pub(crate) install_mirrors: PythonInstallMirrors,
@ -318,6 +319,8 @@ impl RunSettings {
with_editable,
with_requirements,
isolated,
active,
no_active,
no_sync,
locked,
frozen,
@ -380,6 +383,7 @@ impl RunSettings {
package,
no_project,
no_sync,
active: flag(active, no_active).unwrap_or_default(),
python: python.and_then(Maybe::into_option),
refresh: Refresh::from(refresh),
settings: ResolverInstallerSettings::combine(
@ -944,6 +948,7 @@ impl PythonPinSettings {
pub(crate) struct SyncSettings {
pub(crate) locked: bool,
pub(crate) frozen: bool,
pub(crate) active: bool,
pub(crate) extras: ExtrasSpecification,
pub(crate) dev: DevGroupsSpecification,
pub(crate) editable: EditableMode,
@ -982,6 +987,8 @@ impl SyncSettings {
no_install_package,
locked,
frozen,
active,
no_active,
installer,
build,
refresh,
@ -1002,6 +1009,7 @@ impl SyncSettings {
Self {
locked,
frozen,
active: flag(active, no_active).unwrap_or_default(),
extras: ExtrasSpecification::from_args(
flag(all_extras, no_all_extras).unwrap_or_default(),
no_extra,
@ -1091,6 +1099,7 @@ impl LockSettings {
pub(crate) struct AddSettings {
pub(crate) locked: bool,
pub(crate) frozen: bool,
pub(crate) active: bool,
pub(crate) no_sync: bool,
pub(crate) packages: Vec<String>,
pub(crate) requirements: Vec<PathBuf>,
@ -1130,6 +1139,8 @@ impl AddSettings {
no_sync,
locked,
frozen,
active,
no_active,
installer,
build,
refresh,
@ -1201,6 +1212,7 @@ impl AddSettings {
Self {
locked,
frozen,
active: flag(active, no_active).unwrap_or_default(),
no_sync,
packages,
requirements,
@ -1231,6 +1243,7 @@ impl AddSettings {
pub(crate) struct RemoveSettings {
pub(crate) locked: bool,
pub(crate) frozen: bool,
pub(crate) active: bool,
pub(crate) no_sync: bool,
pub(crate) packages: Vec<PackageName>,
pub(crate) dependency_type: DependencyType,
@ -1254,6 +1267,8 @@ impl RemoveSettings {
no_sync,
locked,
frozen,
active,
no_active,
installer,
build,
refresh,
@ -1285,6 +1300,7 @@ impl RemoveSettings {
Self {
locked,
frozen,
active: flag(active, no_active).unwrap_or_default(),
no_sync,
packages,
dependency_type,

View file

@ -124,7 +124,7 @@ fn init_application() -> Result<()> {
Hello from foo!
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 1 package in [TIME]
@ -305,7 +305,7 @@ fn init_application_package() -> Result<()> {
Hello from foo!
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 1 package in [TIME]
@ -387,7 +387,7 @@ fn init_library() -> Result<()> {
Hello from foo!
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 1 package in [TIME]

View file

@ -14643,6 +14643,7 @@ fn lock_explicit_default_index() -> Result<()> {
DEBUG Found workspace root: `[TEMP_DIR]/`
DEBUG Adding current workspace member: `[TEMP_DIR]/`
DEBUG Using Python request `>=3.12` from `requires-python` metadata
DEBUG Use of the active virtual environment was requested, but `VIRTUAL_ENV` is not set
DEBUG Checking for Python environment at `.venv`
DEBUG The virtual environment's Python version satisfies `>=3.12`
DEBUG Using request timeout of [TIME]

View file

@ -5,7 +5,7 @@ use assert_cmd::assert::OutputAssertExt;
use assert_fs::{fixture::ChildPath, prelude::*};
use indoc::indoc;
use insta::assert_snapshot;
use predicates::str::contains;
use predicates::{prelude::predicate, str::contains};
use std::path::Path;
use uv_fs::copy_dir_all;
use uv_python::PYTHON_VERSION_FILENAME;
@ -2354,7 +2354,7 @@ fn run_from_directory() -> Result<()> {
3.12.[X]
----- stderr -----
warning: `VIRTUAL_ENV=.venv` does not match the project environment path `[PROJECT_VENV]/` and will be ignored
warning: `VIRTUAL_ENV=.venv` does not match the project environment path `[PROJECT_VENV]/` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: [PROJECT_VENV]/
Resolved 1 package in [TIME]
@ -2370,7 +2370,7 @@ fn run_from_directory() -> Result<()> {
----- stdout -----
----- stderr -----
warning: `VIRTUAL_ENV=.venv` does not match the project environment path `[PROJECT_VENV]/` and will be ignored
warning: `VIRTUAL_ENV=.venv` does not match the project environment path `[PROJECT_VENV]/` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: [PROJECT_VENV]/
Resolved 1 package in [TIME]
@ -2387,7 +2387,7 @@ fn run_from_directory() -> Result<()> {
3.12.[X]
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 1 package in [TIME]
@ -2402,7 +2402,7 @@ fn run_from_directory() -> Result<()> {
----- stdout -----
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 1 package in [TIME]
@ -2417,7 +2417,7 @@ fn run_from_directory() -> Result<()> {
----- stdout -----
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 1 package in [TIME]
@ -2446,7 +2446,7 @@ fn run_from_directory() -> Result<()> {
3.10.[X]
----- stderr -----
warning: `VIRTUAL_ENV=.venv` does not match the project environment path `[PROJECT_VENV]/` and will be ignored
warning: `VIRTUAL_ENV=.venv` does not match the project environment path `[PROJECT_VENV]/` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.10.[X] interpreter at: [PYTHON-3.10]
Creating virtual environment at: [PROJECT_VENV]/
Resolved 1 package in [TIME]
@ -2462,7 +2462,7 @@ fn run_from_directory() -> Result<()> {
3.10.[X]
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.10.[X] interpreter at: [PYTHON-3.10]
Creating virtual environment at: .venv
Resolved 1 package in [TIME]
@ -3431,6 +3431,98 @@ fn run_linked_environment_path() -> Result<()> {
Ok(())
}
#[test]
fn run_active_environment() -> Result<()> {
let context = TestContext::new_with_versions(&["3.11", "3.12"])
.with_filtered_virtualenv_bin()
.with_filtered_python_names();
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["iniconfig"]
"#,
)?;
// Running `uv run` with `VIRTUAL_ENV` should warn
uv_snapshot!(context.filters(), context.run()
.arg("python").arg("--version")
.env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
success: true
exit_code: 0
----- stdout -----
Python 3.11.[X]
----- stderr -----
warning: `VIRTUAL_ENV=foo` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.11.[X] interpreter at: [PYTHON-3.11]
Creating virtual environment at: .venv
Resolved 2 packages in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###);
context
.temp_dir
.child(".venv")
.assert(predicate::path::is_dir());
context
.temp_dir
.child("foo")
.assert(predicate::path::missing());
// Using `--active` should create the environment
uv_snapshot!(context.filters(), context.run()
.arg("--active")
.arg("python").arg("--version")
.env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
success: true
exit_code: 0
----- stdout -----
Python 3.11.[X]
----- stderr -----
Using CPython 3.11.[X] interpreter at: [PYTHON-3.11]
Creating virtual environment at: foo
Resolved 2 packages in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###);
context
.temp_dir
.child("foo")
.assert(predicate::path::is_dir());
// Requesting a different Python version should invalidate the environment
uv_snapshot!(context.filters(), context.run()
.arg("--active")
.arg("-p").arg("3.12")
.arg("python").arg("--version")
.env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
success: true
exit_code: 0
----- stdout -----
Python 3.12.[X]
----- stderr -----
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Removed virtual environment at: foo
Creating virtual environment at: foo
Resolved 2 packages in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###);
Ok(())
}
#[test]
#[cfg(not(windows))]
fn run_gui_script_explicit_stdin_unix() -> Result<()> {

View file

@ -3182,6 +3182,131 @@ fn sync_custom_environment_path() -> Result<()> {
Ok(())
}
#[test]
fn sync_active_environment() -> Result<()> {
let context = TestContext::new_with_versions(&["3.11", "3.12"])
.with_filtered_virtualenv_bin()
.with_filtered_python_names();
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["iniconfig"]
"#,
)?;
// Running `uv sync` with `VIRTUAL_ENV` should warn
uv_snapshot!(context.filters(), context.sync().env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
warning: `VIRTUAL_ENV=foo` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.11.[X] interpreter at: [PYTHON-3.11]
Creating virtual environment at: .venv
Resolved 2 packages in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###);
context
.temp_dir
.child(".venv")
.assert(predicate::path::is_dir());
context
.temp_dir
.child("foo")
.assert(predicate::path::missing());
// Using `--active` should create the environment
uv_snapshot!(context.filters(), context.sync().env(EnvVars::VIRTUAL_ENV, "foo").arg("--active"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Using CPython 3.11.[X] interpreter at: [PYTHON-3.11]
Creating virtual environment at: foo
Resolved 2 packages in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###);
context
.temp_dir
.child("foo")
.assert(predicate::path::is_dir());
// A subsequent sync will re-use the environment
uv_snapshot!(context.filters(), context.sync().env(EnvVars::VIRTUAL_ENV, "foo").arg("--active"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 2 packages in [TIME]
Audited 1 package in [TIME]
"###);
// Setting both the `VIRTUAL_ENV` and `UV_PROJECT_ENVIRONMENT` is fine if they agree
uv_snapshot!(context.filters(), context.sync()
.arg("--active")
.env(EnvVars::VIRTUAL_ENV, "foo")
.env(EnvVars::UV_PROJECT_ENVIRONMENT, "foo"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 2 packages in [TIME]
Audited 1 package in [TIME]
"###);
// If they disagree, we use `VIRTUAL_ENV` because of `--active`
uv_snapshot!(context.filters(), context.sync()
.arg("--active")
.env(EnvVars::VIRTUAL_ENV, "foo")
.env(EnvVars::UV_PROJECT_ENVIRONMENT, "bar"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 2 packages in [TIME]
Audited 1 package in [TIME]
"###);
context
.temp_dir
.child("bar")
.assert(predicate::path::missing());
// Requesting another Python version will invalidate the environment
uv_snapshot!(context.filters(), context.sync()
.env(EnvVars::VIRTUAL_ENV, "foo").arg("--active").arg("-p").arg("3.12"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Removed virtual environment at: foo
Creating virtual environment at: foo
Resolved 2 packages in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###);
Ok(())
}
#[test]
#[cfg(feature = "git")]
fn sync_workspace_custom_environment_path() -> Result<()> {
@ -3417,7 +3542,7 @@ fn sync_legacy_non_project_warning() -> Result<()> {
----- stdout -----
----- stderr -----
warning: `VIRTUAL_ENV=foo` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=foo` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Resolved 2 packages in [TIME]
Audited 1 package in [TIME]
"###);
@ -3429,7 +3554,7 @@ fn sync_legacy_non_project_warning() -> Result<()> {
----- stdout -----
----- stderr -----
warning: `VIRTUAL_ENV=foo` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=foo` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Resolved 2 packages in [TIME]
Audited 1 package in [TIME]
"###);
@ -3455,7 +3580,7 @@ fn sync_legacy_non_project_warning() -> Result<()> {
----- stdout -----
----- stderr -----
warning: `VIRTUAL_ENV=foo` does not match the project environment path `bar` and will be ignored
warning: `VIRTUAL_ENV=foo` does not match the project environment path `bar` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: bar
Resolved 2 packages in [TIME]
@ -3474,7 +3599,7 @@ fn sync_legacy_non_project_warning() -> Result<()> {
----- stdout -----
----- stderr -----
warning: `VIRTUAL_ENV=foo` does not match the project environment path `[TEMP_DIR]/foo` and will be ignored
warning: `VIRTUAL_ENV=foo` does not match the project environment path `[TEMP_DIR]/foo` and will be ignored; use `--active` to target the active environment instead
Resolved 2 packages in [TIME]
Audited 1 package in [TIME]
"###);

View file

@ -414,7 +414,7 @@ fn test_uv_run_with_package_virtual_workspace() -> Result<()> {
Success
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 8 packages in [TIME]
@ -440,7 +440,7 @@ fn test_uv_run_with_package_virtual_workspace() -> Result<()> {
Success
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Resolved 8 packages in [TIME]
Prepared 2 packages in [TIME]
Installed 2 packages in [TIME]
@ -474,7 +474,7 @@ fn test_uv_run_virtual_workspace_root() -> Result<()> {
Success
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 8 packages in [TIME]
@ -519,7 +519,7 @@ fn test_uv_run_with_package_root_workspace() -> Result<()> {
Success
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 8 packages in [TIME]
@ -545,7 +545,7 @@ fn test_uv_run_with_package_root_workspace() -> Result<()> {
Success
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Resolved 8 packages in [TIME]
Prepared 2 packages in [TIME]
Installed 2 packages in [TIME]
@ -584,7 +584,7 @@ fn test_uv_run_isolate() -> Result<()> {
Success
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
Creating virtual environment at: .venv
Resolved 8 packages in [TIME]
@ -615,7 +615,7 @@ fn test_uv_run_isolate() -> Result<()> {
Success
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Resolved 8 packages in [TIME]
Audited 5 packages in [TIME]
"###