Allow the project `VIRTUAL_ENV` warning to be silenced with `--no-active` (#11251)

Follow-up to https://github.com/astral-sh/uv/pull/11189

Closes https://github.com/astral-sh/uv-pre-commit/issues/36
This commit is contained in:
Zanie Blue 2025-02-05 13:44:46 -06:00 committed by GitHub
parent 2105b8a89d
commit 239f3d76b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 63 additions and 37 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -602,7 +602,7 @@ impl ProjectInterpreter {
allow_insecure_host: &[TrustedHost], allow_insecure_host: &[TrustedHost],
install_mirrors: &PythonInstallMirrors, install_mirrors: &PythonInstallMirrors,
no_config: bool, no_config: bool,
active: bool, active: Option<bool>,
cache: &Cache, cache: &Cache,
printer: Printer, printer: Printer,
) -> Result<Self, ProjectError> { ) -> Result<Self, ProjectError> {
@ -925,7 +925,7 @@ pub(crate) async fn get_or_init_environment(
native_tls: bool, native_tls: bool,
allow_insecure_host: &[TrustedHost], allow_insecure_host: &[TrustedHost],
no_config: bool, no_config: bool,
active: bool, active: Option<bool>,
cache: &Cache, cache: &Cache,
printer: Printer, printer: Printer,
) -> Result<PythonEnvironment, ProjectError> { ) -> Result<PythonEnvironment, ProjectError> {

View File

@ -43,7 +43,7 @@ pub(crate) async fn remove(
project_dir: &Path, project_dir: &Path,
locked: bool, locked: bool,
frozen: bool, frozen: bool,
active: bool, active: Option<bool>,
no_sync: bool, no_sync: bool,
packages: Vec<PackageName>, packages: Vec<PackageName>,
dependency_type: DependencyType, dependency_type: DependencyType,

View File

@ -65,7 +65,7 @@ pub(crate) async fn run(
show_resolution: bool, show_resolution: bool,
locked: bool, locked: bool,
frozen: bool, frozen: bool,
active: bool, active: Option<bool>,
no_sync: bool, no_sync: bool,
isolated: bool, isolated: bool,
all_packages: bool, all_packages: bool,

View File

@ -45,7 +45,7 @@ pub(crate) async fn sync(
project_dir: &Path, project_dir: &Path,
locked: bool, locked: bool,
frozen: bool, frozen: bool,
active: bool, active: Option<bool>,
all_packages: bool, all_packages: bool,
package: Option<PackageName>, package: Option<PackageName>,
extras: ExtrasSpecification, extras: ExtrasSpecification,

View File

@ -118,7 +118,7 @@ pub(crate) async fn tree(
allow_insecure_host, allow_insecure_host,
&install_mirrors, &install_mirrors,
no_config, no_config,
false, Some(false),
cache, cache,
printer, 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 // 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`. // avoids a breaking change when adding project environment support to `uv venv`.
(project.workspace().install_path() == project_dir) (project.workspace().install_path() == project_dir)
.then(|| project.workspace().venv(false)) .then(|| project.workspace().venv(Some(false)))
}) })
.unwrap_or(PathBuf::from(".venv")), .unwrap_or(PathBuf::from(".venv")),
); );

View File

@ -289,7 +289,7 @@ pub(crate) struct RunSettings {
pub(crate) all_packages: bool, pub(crate) all_packages: bool,
pub(crate) package: Option<PackageName>, pub(crate) package: Option<PackageName>,
pub(crate) no_project: bool, pub(crate) no_project: bool,
pub(crate) active: bool, pub(crate) active: Option<bool>,
pub(crate) no_sync: bool, pub(crate) no_sync: bool,
pub(crate) python: Option<String>, pub(crate) python: Option<String>,
pub(crate) install_mirrors: PythonInstallMirrors, pub(crate) install_mirrors: PythonInstallMirrors,
@ -391,7 +391,7 @@ impl RunSettings {
package, package,
no_project, no_project,
no_sync, no_sync,
active: flag(active, no_active).unwrap_or_default(), active: flag(active, no_active),
python: python.and_then(Maybe::into_option), python: python.and_then(Maybe::into_option),
refresh: Refresh::from(refresh), refresh: Refresh::from(refresh),
settings: ResolverInstallerSettings::combine( settings: ResolverInstallerSettings::combine(
@ -956,7 +956,7 @@ impl PythonPinSettings {
pub(crate) struct SyncSettings { pub(crate) struct SyncSettings {
pub(crate) locked: bool, pub(crate) locked: bool,
pub(crate) frozen: bool, pub(crate) frozen: bool,
pub(crate) active: bool, pub(crate) active: Option<bool>,
pub(crate) extras: ExtrasSpecification, pub(crate) extras: ExtrasSpecification,
pub(crate) dev: DevGroupsSpecification, pub(crate) dev: DevGroupsSpecification,
pub(crate) editable: EditableMode, pub(crate) editable: EditableMode,
@ -1017,7 +1017,7 @@ impl SyncSettings {
Self { Self {
locked, locked,
frozen, frozen,
active: flag(active, no_active).unwrap_or_default(), active: flag(active, no_active),
extras: ExtrasSpecification::from_args( extras: ExtrasSpecification::from_args(
flag(all_extras, no_all_extras).unwrap_or_default(), flag(all_extras, no_all_extras).unwrap_or_default(),
no_extra, no_extra,
@ -1107,7 +1107,7 @@ impl LockSettings {
pub(crate) struct AddSettings { pub(crate) struct AddSettings {
pub(crate) locked: bool, pub(crate) locked: bool,
pub(crate) frozen: bool, pub(crate) frozen: bool,
pub(crate) active: bool, pub(crate) active: Option<bool>,
pub(crate) no_sync: bool, pub(crate) no_sync: bool,
pub(crate) packages: Vec<String>, pub(crate) packages: Vec<String>,
pub(crate) requirements: Vec<PathBuf>, pub(crate) requirements: Vec<PathBuf>,
@ -1220,7 +1220,7 @@ impl AddSettings {
Self { Self {
locked, locked,
frozen, frozen,
active: flag(active, no_active).unwrap_or_default(), active: flag(active, no_active),
no_sync, no_sync,
packages, packages,
requirements, requirements,
@ -1251,7 +1251,7 @@ impl AddSettings {
pub(crate) struct RemoveSettings { pub(crate) struct RemoveSettings {
pub(crate) locked: bool, pub(crate) locked: bool,
pub(crate) frozen: bool, pub(crate) frozen: bool,
pub(crate) active: bool, pub(crate) active: Option<bool>,
pub(crate) no_sync: bool, pub(crate) no_sync: bool,
pub(crate) packages: Vec<PackageName>, pub(crate) packages: Vec<PackageName>,
pub(crate) dependency_type: DependencyType, pub(crate) dependency_type: DependencyType,
@ -1308,7 +1308,7 @@ impl RemoveSettings {
Self { Self {
locked, locked,
frozen, frozen,
active: flag(active, no_active).unwrap_or_default(), active: flag(active, no_active),
no_sync, no_sync,
packages, packages,
dependency_type, dependency_type,

View File

@ -14643,7 +14643,6 @@ fn lock_explicit_default_index() -> Result<()> {
DEBUG Found workspace root: `[TEMP_DIR]/` DEBUG Found workspace root: `[TEMP_DIR]/`
DEBUG Adding current workspace member: `[TEMP_DIR]/` DEBUG Adding current workspace member: `[TEMP_DIR]/`
DEBUG Using Python request `>=3.12` from `requires-python` metadata 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 Checking for Python environment at `.venv`
DEBUG The virtual environment's Python version satisfies `>=3.12` DEBUG The virtual environment's Python version satisfies `>=3.12`
DEBUG Using request timeout of [TIME] DEBUG Using request timeout of [TIME]

View File

@ -3467,6 +3467,21 @@ fn run_active_environment() -> Result<()> {
+ iniconfig==2.0.0 + iniconfig==2.0.0
"###); "###);
// Using `--no-active` should silence the warning
uv_snapshot!(context.filters(), context.run()
.arg("--no-active")
.arg("python").arg("--version")
.env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
success: true
exit_code: 0
----- stdout -----
Python 3.11.[X]
----- stderr -----
Resolved 2 packages in [TIME]
Audited 1 package in [TIME]
"###);
context context
.temp_dir .temp_dir
.child(".venv") .child(".venv")

View File

@ -192,7 +192,8 @@ To target this environment, you'd export `UV_PROJECT_ENVIRONMENT=/usr/local`.
By default, uv does not read the `VIRTUAL_ENV` environment variable during project operations. By default, uv does not read the `VIRTUAL_ENV` environment variable during project operations.
A warning will be displayed if `VIRTUAL_ENV` is set to a different path than the project's A warning will be displayed if `VIRTUAL_ENV` is set to a different path than the project's
environment. The `--active` flag can be used to opt-in to respecting `VIRTUAL_ENV`. environment. The `--active` flag can be used to opt-in to respecting `VIRTUAL_ENV`. The
`--no-active` flag can be used to silence the warning.
## Limited resolution environments ## Limited resolution environments