chore(🧹): const env var usage cleanup (#16950)

## Summary

* Updates existing references to use EnvVars where usage was missing.
* Adds missing entries to env var usages, e.g. new env var declarations
in uv-trampoline, tests, etc.
* Note: this doesn't affect trampoline sizes as the end result is the
same
* Fixes versioning of `UV_HIDE_BUILD_OUTPUT`.

## Test Plan

Existing Tests. Compiled the trampolines locally to verify zero changes
(size, binary).

## Question

Will this complicate the crates publishing release process? I'm not
certain yet if it will be an issue for uv-trampoline (non-workspace
member) to reference a uv workspace member from a bump & release
perspective wrt lock files. If so, I'll revert the uv-trampoline changes
but keep the others.
This commit is contained in:
samypr100 2025-12-03 01:16:46 -05:00 committed by GitHub
parent d2db06983a
commit ed63be5dab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 128 additions and 32 deletions

View File

@ -82,4 +82,6 @@ tempfile = { workspace = true }
test-log = { workspace = true } test-log = { workspace = true }
[build-dependencies] [build-dependencies]
uv-static = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }

View File

@ -4,6 +4,8 @@ use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use std::{env, fs}; use std::{env, fs};
use uv_static::EnvVars;
fn process_json(data: &serde_json::Value) -> serde_json::Value { fn process_json(data: &serde_json::Value) -> serde_json::Value {
let mut out_data = serde_json::Map::new(); let mut out_data = serde_json::Map::new();
@ -18,12 +20,12 @@ fn process_json(data: &serde_json::Value) -> serde_json::Value {
fn main() { fn main() {
let version_metadata = PathBuf::from_iter([ let version_metadata = PathBuf::from_iter([
env::var("CARGO_MANIFEST_DIR").unwrap(), env::var(EnvVars::CARGO_MANIFEST_DIR).unwrap(),
"download-metadata.json".into(), "download-metadata.json".into(),
]); ]);
let version_metadata_minified = PathBuf::from_iter([ let version_metadata_minified = PathBuf::from_iter([
env::var("OUT_DIR").unwrap(), env::var(EnvVars::OUT_DIR).unwrap(),
"download-metadata-minified.json".into(), "download-metadata-minified.json".into(),
]); ]);

View File

@ -224,7 +224,7 @@ mod tests {
Some(self.installations.root().as_os_str()), Some(self.installations.root().as_os_str()),
), ),
// Set a working directory // Set a working directory
("PWD", Some(self.workdir.path().as_os_str())), (EnvVars::PWD, Some(self.workdir.path().as_os_str())),
]; ];
for (key, value) in vars { for (key, value) in vars {
run_vars.push((key, *value)); run_vars.push((key, *value));

View File

@ -348,7 +348,11 @@ mod tests {
use tempfile::tempdir; use tempfile::tempdir;
// First option used by std::env::home_dir. // First option used by std::env::home_dir.
const HOME_DIR_ENV_VAR: &str = if cfg!(windows) { "USERPROFILE" } else { "HOME" }; const HOME_DIR_ENV_VAR: &str = if cfg!(windows) {
EnvVars::USERPROFILE
} else {
EnvVars::HOME
};
#[test] #[test]
fn configuration_files_zsh_no_existing_zshenv() { fn configuration_files_zsh_no_existing_zshenv() {
@ -357,7 +361,7 @@ mod tests {
with_vars( with_vars(
[ [
("ZDOTDIR", None), (EnvVars::ZDOTDIR, None),
(HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()), (HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()),
], ],
|| { || {
@ -370,7 +374,7 @@ mod tests {
with_vars( with_vars(
[ [
("ZDOTDIR", tmp_zdotdir.path().to_str()), (EnvVars::ZDOTDIR, tmp_zdotdir.path().to_str()),
(HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()), (HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()),
], ],
|| { || {
@ -391,7 +395,7 @@ mod tests {
with_vars( with_vars(
[ [
("ZDOTDIR", None), (EnvVars::ZDOTDIR, None),
(HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()), (HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()),
], ],
|| { || {
@ -404,7 +408,7 @@ mod tests {
with_vars( with_vars(
[ [
("ZDOTDIR", tmp_zdotdir.path().to_str()), (EnvVars::ZDOTDIR, tmp_zdotdir.path().to_str()),
(HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()), (HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()),
], ],
|| { || {
@ -425,7 +429,7 @@ mod tests {
with_vars( with_vars(
[ [
("ZDOTDIR", tmp_zdotdir.path().to_str()), (EnvVars::ZDOTDIR, tmp_zdotdir.path().to_str()),
(HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()), (HOME_DIR_ENV_VAR, tmp_home_dir.path().to_str()),
], ],
|| { || {

View File

@ -850,6 +850,16 @@ impl EnvVars {
#[attr_added_in("0.8.18")] #[attr_added_in("0.8.18")]
pub const GITLAB_CI: &'static str = "GITLAB_CI"; pub const GITLAB_CI: &'static str = "GITLAB_CI";
/// Used for testing GitLab CI trusted publishing.
#[attr_hidden]
#[attr_added_in("0.8.18")]
pub const PYPI_ID_TOKEN: &'static str = "PYPI_ID_TOKEN";
/// Used for testing GitLab CI trusted publishing.
#[attr_hidden]
#[attr_added_in("0.8.18")]
pub const TESTPYPI_ID_TOKEN: &'static str = "TESTPYPI_ID_TOKEN";
/// Sets the encoding for standard I/O streams (e.g., PYTHONIOENCODING=utf-8). /// Sets the encoding for standard I/O streams (e.g., PYTHONIOENCODING=utf-8).
#[attr_hidden] #[attr_hidden]
#[attr_added_in("0.4.18")] #[attr_added_in("0.4.18")]
@ -869,6 +879,16 @@ impl EnvVars {
#[attr_added_in("0.1.22")] #[attr_added_in("0.1.22")]
pub const PYTHONPATH: &'static str = "PYTHONPATH"; pub const PYTHONPATH: &'static str = "PYTHONPATH";
/// Used to set the location of Python stdlib when using trampolines.
#[attr_hidden]
#[attr_added_in("0.7.13")]
pub const PYTHONHOME: &'static str = "PYTHONHOME";
/// Used to correctly detect virtual environments when using trampolines.
#[attr_hidden]
#[attr_added_in("0.7.13")]
pub const PYVENV_LAUNCHER: &'static str = "__PYVENV_LAUNCHER__";
/// Used in tests to enforce a consistent locale setting. /// Used in tests to enforce a consistent locale setting.
#[attr_hidden] #[attr_hidden]
#[attr_added_in("0.4.28")] #[attr_added_in("0.4.28")]
@ -989,6 +1009,16 @@ impl EnvVars {
#[attr_added_in("0.0.5")] #[attr_added_in("0.0.5")]
pub const CARGO_TARGET_DIR: &'static str = "CARGO_TARGET_DIR"; pub const CARGO_TARGET_DIR: &'static str = "CARGO_TARGET_DIR";
/// Set by cargo when compiling for Windows-like platforms.
#[attr_hidden]
#[attr_added_in("0.0.5")]
pub const CARGO_CFG_WINDOWS: &'static str = "CARGO_CFG_WINDOWS";
/// Specifies the directory where Cargo stores intermediate build artifacts.
#[attr_hidden]
#[attr_added_in("0.8.25")]
pub const OUT_DIR: &'static str = "OUT_DIR";
/// Used in tests for environment substitution testing in `requirements.in`. /// Used in tests for environment substitution testing in `requirements.in`.
#[attr_hidden] #[attr_hidden]
#[attr_added_in("0.1.18")] #[attr_added_in("0.1.18")]
@ -1239,6 +1269,6 @@ impl EnvVars {
/// Suppress output from the build backend when building source distributions, even in the event /// Suppress output from the build backend when building source distributions, even in the event
/// of build failures. /// of build failures.
#[attr_added_in("0.9.14")] #[attr_added_in("0.9.15")]
pub const UV_HIDE_BUILD_OUTPUT: &'static str = "UV_HIDE_BUILD_OUTPUT"; pub const UV_HIDE_BUILD_OUTPUT: &'static str = "UV_HIDE_BUILD_OUTPUT";
} }

View File

@ -25,13 +25,19 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.36" version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "smawk"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"
@ -54,6 +60,17 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "textwrap"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
dependencies = [
"smawk",
"unicode-linebreak",
"unicode-width",
]
[[package]] [[package]]
name = "ufmt" name = "ufmt"
version = "0.2.0" version = "0.2.0"
@ -87,6 +104,35 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-linebreak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-width"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
[[package]]
name = "uv-macros"
version = "0.0.5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"textwrap",
]
[[package]]
name = "uv-static"
version = "0.0.5"
dependencies = [
"uv-macros",
]
[[package]] [[package]]
name = "uv-trampoline" name = "uv-trampoline"
version = "0.1.0" version = "0.1.0"
@ -95,6 +141,7 @@ dependencies = [
"embed-manifest", "embed-manifest",
"ufmt", "ufmt",
"ufmt-write", "ufmt-write",
"uv-static",
"windows", "windows",
] ]

View File

@ -35,6 +35,8 @@ debug = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
uv-static = { path = "../uv-static" }
windows = { version = "0.61.0", features = [ windows = { version = "0.61.0", features = [
"std", "std",
"Win32_Foundation", "Win32_Foundation",
@ -51,4 +53,6 @@ ufmt = { version = "0.2.0", features = ["std"] }
dunce = { version = "1.0.5" } dunce = { version = "1.0.5" }
[build-dependencies] [build-dependencies]
uv-static = { path = "../uv-static" }
embed-manifest = "1.4.0" embed-manifest = "1.4.0"

View File

@ -4,8 +4,10 @@
// don't have to mess with utf-16. // don't have to mess with utf-16.
use embed_manifest::{embed_manifest, new_manifest}; use embed_manifest::{embed_manifest, new_manifest};
use uv_static::EnvVars;
fn main() { fn main() {
if std::env::var_os("CARGO_CFG_WINDOWS").is_some() { if std::env::var_os(EnvVars::CARGO_CFG_WINDOWS).is_some() {
let manifest = let manifest =
new_manifest("uv.Trampoline").remove_dependency("Microsoft.Windows.Common-Controls"); new_manifest("uv.Trampoline").remove_dependency("Microsoft.Windows.Common-Controls");
embed_manifest(manifest).expect("unable to embed manifest"); embed_manifest(manifest).expect("unable to embed manifest");

View File

@ -30,6 +30,8 @@ use windows::Win32::{
}; };
use windows::core::{BOOL, PSTR, s}; use windows::core::{BOOL, PSTR, s};
use uv_static::EnvVars;
use crate::{error, format, warn}; use crate::{error, format, warn};
// https://learn.microsoft.com/en-us/windows/win32/menurc/resource-types // https://learn.microsoft.com/en-us/windows/win32/menurc/resource-types
@ -146,7 +148,7 @@ fn make_child_cmdline() -> CString {
// the approach taken by CPython for Python Launchers // the approach taken by CPython for Python Launchers
// (in `launcher.c`). This allows virtual environments to // (in `launcher.c`). This allows virtual environments to
// be correctly detected when using trampolines. // be correctly detected when using trampolines.
std::env::set_var("__PYVENV_LAUNCHER__", &executable_name); std::env::set_var(EnvVars::PYVENV_LAUNCHER, &executable_name);
// If this is not a virtual environment and `PYTHONHOME` has // If this is not a virtual environment and `PYTHONHOME` has
// not been set, then set `PYTHONHOME` to the parent directory of // not been set, then set `PYTHONHOME` to the parent directory of
@ -154,10 +156,10 @@ fn make_child_cmdline() -> CString {
// directories are added to `sys.path` when running with a junction // directories are added to `sys.path` when running with a junction
// trampoline. // trampoline.
let python_home_set = let python_home_set =
std::env::var("PYTHONHOME").is_ok_and(|home| !home.is_empty()); std::env::var(EnvVars::PYTHONHOME).is_ok_and(|home| !home.is_empty());
if !is_virtualenv(python_exe.as_path()) && !python_home_set { if !is_virtualenv(python_exe.as_path()) && !python_home_set {
std::env::set_var( std::env::set_var(
"PYTHONHOME", EnvVars::PYTHONHOME,
python_exe python_exe
.parent() .parent()
.expect("Python executable should have a parent directory"), .expect("Python executable should have a parent directory"),

View File

@ -122,6 +122,7 @@ self-replace = { workspace = true }
windows = { workspace = true } windows = { workspace = true }
[build-dependencies] [build-dependencies]
uv-static = { workspace = true }
uv-version = { workspace = true } uv-version = { workspace = true }
embed-manifest = { workspace = true } embed-manifest = { workspace = true }

View File

@ -16,8 +16,10 @@
use embed_manifest::manifest::{ActiveCodePage, ExecutionLevel, Setting, SupportedOS}; use embed_manifest::manifest::{ActiveCodePage, ExecutionLevel, Setting, SupportedOS};
use embed_manifest::{embed_manifest, empty_manifest}; use embed_manifest::{embed_manifest, empty_manifest};
use uv_static::EnvVars;
fn main() { fn main() {
if std::env::var_os("CARGO_CFG_WINDOWS").is_some() { if std::env::var_os(EnvVars::CARGO_CFG_WINDOWS).is_some() {
let [major, minor, patch] = uv_version::version() let [major, minor, patch] = uv_version::version()
.splitn(3, '.') .splitn(3, '.')
.map(str::parse) .map(str::parse)

View File

@ -17834,8 +17834,8 @@ fn credentials_from_subdirectory() -> Result<()> {
uv_snapshot!(context.filters(), context uv_snapshot!(context.filters(), context
.pip_compile() .pip_compile()
.arg("foo/pyproject.toml") .arg("foo/pyproject.toml")
.env("UV_INDEX_INTERNAL_USERNAME", "public") .env(EnvVars::index_username("INTERNAL"), "public")
.env("UV_INDEX_INTERNAL_PASSWORD", "heron"), @r" .env(EnvVars::index_password("INTERNAL"), "heron"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

View File

@ -10710,7 +10710,7 @@ fn no_sources_workspace_discovery() -> Result<()> {
uv_snapshot!(context.filters(), context.pip_install() uv_snapshot!(context.filters(), context.pip_install()
.arg("--upgrade") .arg("--upgrade")
.arg(".") .arg(".")
.env("UV_NO_SOURCES", "true"), @r###" .env(EnvVars::UV_NO_SOURCES, "true"), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@ -10730,7 +10730,7 @@ fn no_sources_workspace_discovery() -> Result<()> {
uv_snapshot!(context.filters(), context.pip_install() uv_snapshot!(context.filters(), context.pip_install()
.arg("--upgrade") .arg("--upgrade")
.arg(".") .arg(".")
.env("UV_NO_SOURCES", "false"), @r###" .env(EnvVars::UV_NO_SOURCES, "false"), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@ -10751,7 +10751,7 @@ fn no_sources_workspace_discovery() -> Result<()> {
.arg("--upgrade") .arg("--upgrade")
.arg("--no-sources") .arg("--no-sources")
.arg(".") .arg(".")
.env("UV_NO_SOURCES", "False"), @r" .env(EnvVars::UV_NO_SOURCES, "False"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

View File

@ -483,8 +483,8 @@ async fn read_index_credential_env_vars_for_check_url() {
.arg(&wheel) .arg(&wheel)
.arg("--index") .arg("--index")
.arg("private-index") .arg("private-index")
.env("UV_INDEX_PRIVATE_INDEX_USERNAME", "username") .env(EnvVars::index_username("PRIVATE_INDEX"), "username")
.env("UV_INDEX_PRIVATE_INDEX_PASSWORD", "secret") .env(EnvVars::index_password("PRIVATE_INDEX"), "secret")
.arg("--trusted-publishing") .arg("--trusted-publishing")
.arg("never"), .arg("never"),
@r" @r"
@ -540,7 +540,7 @@ async fn gitlab_trusted_publishing_pypi_id_token() {
.arg("../../scripts/links/ok-1.0.0-py3-none-any.whl") .arg("../../scripts/links/ok-1.0.0-py3-none-any.whl")
.env(EnvVars::GITLAB_CI, "true") .env(EnvVars::GITLAB_CI, "true")
.env_remove(EnvVars::GITHUB_ACTIONS) .env_remove(EnvVars::GITHUB_ACTIONS)
.env("PYPI_ID_TOKEN", "gitlab-oidc-jwt"), @r" .env(EnvVars::PYPI_ID_TOKEN, "gitlab-oidc-jwt"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@ -595,7 +595,7 @@ async fn gitlab_trusted_publishing_testpypi_id_token() {
// Emulate GitLab CI with TESTPYPI_ID_TOKEN present // Emulate GitLab CI with TESTPYPI_ID_TOKEN present
.env(EnvVars::GITLAB_CI, "true") .env(EnvVars::GITLAB_CI, "true")
.env_remove(EnvVars::GITHUB_ACTIONS) .env_remove(EnvVars::GITHUB_ACTIONS)
.env("TESTPYPI_ID_TOKEN", "gitlab-oidc-jwt"), @r" .env(EnvVars::TESTPYPI_ID_TOKEN, "gitlab-oidc-jwt"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

View File

@ -2750,7 +2750,7 @@ fn python_install_emulated_macos() {
// Rosetta is not available to run the x86_64 interpreter // Rosetta is not available to run the x86_64 interpreter
// fail the test in CI, otherwise skip it // fail the test in CI, otherwise skip it
#[allow(clippy::manual_assert)] #[allow(clippy::manual_assert)]
if env::var("CI").is_ok() { if env::var(EnvVars::CI).is_ok() {
panic!("x86_64 emulation is not available on this CI runner"); panic!("x86_64 emulation is not available on this CI runner");
} }
debug!("Skipping test because x86_64 emulation is not available"); debug!("Skipping test because x86_64 emulation is not available");

View File

@ -4395,7 +4395,7 @@ fn run_remote_pep723_script() {
r"(?m)^Downloaded remote script to:.*\.py$", r"(?m)^Downloaded remote script to:.*\.py$",
"Downloaded remote script to: [TEMP_PATH].py", "Downloaded remote script to: [TEMP_PATH].py",
)); ));
uv_snapshot!(filters, context.run().arg("https://raw.githubusercontent.com/astral-sh/uv/df45b9ac2584824309ff29a6a09421055ad730f6/scripts/uv-run-remote-script-test.py").arg("CI"), @r###" uv_snapshot!(filters, context.run().arg("https://raw.githubusercontent.com/astral-sh/uv/df45b9ac2584824309ff29a6a09421055ad730f6/scripts/uv-run-remote-script-test.py").arg(EnvVars::CI), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

View File

@ -3549,7 +3549,7 @@ fn sync_exclude_group_with_environment_variable() -> Result<()> {
uv_snapshot!(context.filters(), context.sync() uv_snapshot!(context.filters(), context.sync()
.arg("--group").arg("foo") .arg("--group").arg("foo")
.arg("--group").arg("bar") .arg("--group").arg("bar")
.env("UV_NO_GROUP", "bar"), @r" .env(EnvVars::UV_NO_GROUP, "bar"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@ -3569,7 +3569,7 @@ fn sync_exclude_group_with_environment_variable() -> Result<()> {
.arg("--group").arg("foo") .arg("--group").arg("foo")
.arg("--group").arg("bar") .arg("--group").arg("bar")
.arg("--group").arg("baz") .arg("--group").arg("baz")
.env("UV_NO_GROUP", "bar baz"), @r" .env(EnvVars::UV_NO_GROUP, "bar baz"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@ -3586,7 +3586,7 @@ fn sync_exclude_group_with_environment_variable() -> Result<()> {
.arg("--group").arg("bar") .arg("--group").arg("bar")
.arg("--group").arg("baz") .arg("--group").arg("baz")
.arg("--no-group").arg("bar") .arg("--no-group").arg("bar")
.env("UV_NO_GROUP", "baz"), @r" .env(EnvVars::UV_NO_GROUP, "baz"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

View File

@ -151,7 +151,7 @@ Equivalent to the `--token` argument for self update. A GitHub token for authent
Enables fetching files stored in Git LFS when installing a package from a Git repository. Enables fetching files stored in Git LFS when installing a package from a Git repository.
### `UV_HIDE_BUILD_OUTPUT` ### `UV_HIDE_BUILD_OUTPUT`
<small class="added-in">added in `0.9.14`</small> <small class="added-in">added in `0.9.15`</small>
Suppress output from the build backend when building source distributions, even in the event Suppress output from the build backend when building source distributions, even in the event
of build failures. of build failures.