mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-03 10:33:49 +00:00
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:
parent
6f8d9b85d8
commit
989b103171
20 changed files with 368 additions and 33 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -163,6 +163,7 @@ pub(crate) async fn export(
|
|||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
false,
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
|
|
@ -121,6 +121,7 @@ pub(crate) async fn lock(
|
|||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
false,
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -118,6 +118,7 @@ pub(crate) async fn tree(
|
|||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
false,
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
|
|
@ -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")),
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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<()> {
|
||||
|
|
|
@ -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]
|
||||
"###);
|
||||
|
|
|
@ -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]
|
||||
"###
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue