Clear known env vars for tests (#14080)

Currently, it's possible to break our test suite by having an env var
set that influences uv, either a `UV_*` var, or something more generic
such as the XDG env vars. We previously fixed them env-var-by-env-var as
we discovered. By clearing uv-specific env var for subcommands, we can
invert this.

We intentionally avoid clearing all env vars as some of them, especially
on Windows, are system env vars required for basic operations.

Notable limitations are that this only affects tests that use
`TestContext::add_shared_env` (default, can be opted-out).

Fixed #9873
This commit is contained in:
konsti
2026-01-15 11:40:31 +01:00
committed by GitHub
parent 47d3d0c6e1
commit ed50e40d05
2 changed files with 56 additions and 2 deletions
+20
View File
@@ -143,6 +143,21 @@ pub fn attribute_env_vars_metadata(_attr: TokenStream, input: TokenStream) -> To
return quote! { #ast #(#added_in_errors)* }.into();
}
let env_var_names = ast.items.iter().filter_map(|item| {
if let ImplItem::Const(item) = item {
let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit),
..
}) = &item.expr
else {
return None;
};
Some(lit.value())
} else {
None
}
});
let struct_name = &ast.self_ty;
let pairs = constants.iter().map(|(name, doc, added_in, _span)| {
if let Some(added_in) = added_in {
@@ -160,6 +175,11 @@ pub fn attribute_env_vars_metadata(_attr: TokenStream, input: TokenStream) -> To
pub fn metadata<'a>() -> &'a [(&'static str, &'static str, Option<&'static str>)] {
&[#(#pairs),*]
}
/// Returns all environment variable names defined as constants (including hidden ones).
pub fn all_names() -> &'static [&'static str] {
&[#(#env_var_names),*]
}
}
};
+36 -2
View File
@@ -1444,6 +1444,9 @@ impl TestContext {
command
}
/// The path to the Python interpreter in the venv.
///
/// Don't use this for `Command::new`, use `Self::python_command` instead.
pub fn interpreter(&self) -> PathBuf {
let venv = &self.venv;
if cfg!(unix) {
@@ -1726,8 +1729,39 @@ impl TestContext {
/// Creates a new `Command` that is intended to be suitable for use in
/// all tests, but with the given binary.
///
/// Clears environment variables defined in [`EnvVars`] to avoid reading
/// test host settings.
fn new_command_with(bin: &Path) -> Command {
Command::new(bin)
let mut command = Command::new(bin);
let passthrough = [
// For debugging tests.
EnvVars::RUST_LOG,
EnvVars::RUST_BACKTRACE,
// Windows System configuration.
EnvVars::SYSTEMDRIVE,
// Work around small default stack sizes and large futures in debug builds.
EnvVars::RUST_MIN_STACK,
EnvVars::UV_STACK_SIZE,
// Allow running tests with custom network settings.
EnvVars::ALL_PROXY,
EnvVars::HTTPS_PROXY,
EnvVars::HTTP_PROXY,
EnvVars::NO_PROXY,
EnvVars::SSL_CERT_DIR,
EnvVars::SSL_CERT_FILE,
EnvVars::UV_NATIVE_TLS,
];
for env_var in EnvVars::all_names()
.iter()
.filter(|name| !passthrough.contains(name))
{
command.env_remove(env_var);
}
command
}
}
@@ -1790,7 +1824,7 @@ pub fn get_python(version: &PythonVersion) -> PathBuf {
/// Create a virtual environment at the given path.
pub fn create_venv_from_executable<P: AsRef<Path>>(path: P, cache_dir: &ChildPath, python: &Path) {
assert_cmd::Command::new(get_bin())
TestContext::new_command_with(&get_bin())
.arg("venv")
.arg(path.as_ref().as_os_str())
.arg("--clear")