mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-23 04:55:28 +00:00
Use a global flags instance for wheel check (#16047)
Some checks failed
CI / Determine changes (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / cargo shear (push) Has been cancelled
CI / typos (push) Has been cancelled
CI / mkdocs (push) Has been cancelled
zizmor / Run zizmor (push) Has been cancelled
CI / cargo clippy | ubuntu (push) Has been cancelled
CI / cargo clippy | windows (push) Has been cancelled
CI / cargo dev generate-all (push) Has been cancelled
CI / cargo test | ubuntu (push) Has been cancelled
CI / cargo test | macos (push) Has been cancelled
CI / cargo test | windows (push) Has been cancelled
CI / check windows trampoline | aarch64 (push) Has been cancelled
CI / check windows trampoline | i686 (push) Has been cancelled
CI / check windows trampoline | x86_64 (push) Has been cancelled
CI / test windows trampoline | aarch64 (push) Has been cancelled
CI / test windows trampoline | i686 (push) Has been cancelled
CI / test windows trampoline | x86_64 (push) Has been cancelled
CI / build binary | linux libc (push) Has been cancelled
CI / build binary | linux aarch64 (push) Has been cancelled
CI / build binary | linux musl (push) Has been cancelled
CI / build binary | macos aarch64 (push) Has been cancelled
CI / build binary | macos x86_64 (push) Has been cancelled
CI / build binary | windows x86_64 (push) Has been cancelled
CI / build binary | windows aarch64 (push) Has been cancelled
CI / build binary | msrv (push) Has been cancelled
CI / build binary | freebsd (push) Has been cancelled
CI / ecosystem test | pydantic/pydantic-core (push) Has been cancelled
CI / ecosystem test | prefecthq/prefect (push) Has been cancelled
CI / ecosystem test | pallets/flask (push) Has been cancelled
CI / smoke test | linux (push) Has been cancelled
CI / smoke test | linux aarch64 (push) Has been cancelled
CI / check system | alpine (push) Has been cancelled
CI / smoke test | macos (push) Has been cancelled
CI / smoke test | windows x86_64 (push) Has been cancelled
CI / smoke test | windows aarch64 (push) Has been cancelled
CI / integration test | activate nushell venv (push) Has been cancelled
CI / integration test | conda on ubuntu (push) Has been cancelled
CI / integration test | deadsnakes python3.9 on ubuntu (push) Has been cancelled
CI / integration test | free-threaded on windows (push) Has been cancelled
CI / integration test | aarch64 windows implicit (push) Has been cancelled
CI / integration test | aarch64 windows explicit (push) Has been cancelled
CI / integration test | pypy on ubuntu (push) Has been cancelled
CI / integration test | pypy on windows (push) Has been cancelled
CI / integration test | graalpy on ubuntu (push) Has been cancelled
CI / integration test | graalpy on windows (push) Has been cancelled
CI / integration test | pyodide on ubuntu (push) Has been cancelled
CI / integration test | github actions (push) Has been cancelled
CI / integration test | free-threaded python on github actions (push) Has been cancelled
CI / integration test | pyenv on wsl x86-64 (push) Has been cancelled
CI / integration test | determine publish changes (push) Has been cancelled
CI / integration test | registries (push) Has been cancelled
CI / integration test | uv publish (push) Has been cancelled
CI / integration test | uv_build (push) Has been cancelled
CI / check cache | ubuntu (push) Has been cancelled
CI / check cache | macos aarch64 (push) Has been cancelled
CI / check system | python on debian (push) Has been cancelled
CI / check system | python on fedora (push) Has been cancelled
CI / check system | python on ubuntu (push) Has been cancelled
CI / check system | python on rocky linux 8 (push) Has been cancelled
CI / check system | python on rocky linux 9 (push) Has been cancelled
CI / check system | graalpy on ubuntu (push) Has been cancelled
CI / check system | pypy on ubuntu (push) Has been cancelled
CI / check system | pyston (push) Has been cancelled
CI / check system | python on macos aarch64 (push) Has been cancelled
CI / check system | homebrew python on macos aarch64 (push) Has been cancelled
CI / check system | x86-64 python on macos aarch64 (push) Has been cancelled
CI / check system | python on macos x86-64 (push) Has been cancelled
CI / check system | python3.10 on windows x86-64 (push) Has been cancelled
CI / check system | python3.10 on windows x86 (push) Has been cancelled
CI / check system | python3.13 on windows x86-64 (push) Has been cancelled
CI / check system | x86-64 python3.13 on windows aarch64 (push) Has been cancelled
CI / check system | aarch64 python3.13 on windows aarch64 (push) Has been cancelled
CI / check system | windows registry (push) Has been cancelled
CI / check system | python3.12 via chocolatey (push) Has been cancelled
CI / check system | python3.9 via pyenv (push) Has been cancelled
CI / check system | python3.13 (push) Has been cancelled
CI / check system | conda3.11 on macos aarch64 (push) Has been cancelled
CI / check system | conda3.8 on macos aarch64 (push) Has been cancelled
CI / check system | conda3.11 on linux x86-64 (push) Has been cancelled
CI / check system | conda3.8 on linux x86-64 (push) Has been cancelled
CI / check system | conda3.11 on windows x86-64 (push) Has been cancelled
CI / check system | conda3.8 on windows x86-64 (push) Has been cancelled
CI / check system | amazonlinux (push) Has been cancelled
CI / check system | embedded python3.10 on windows x86-64 (push) Has been cancelled
CI / benchmarks | walltime aarch64 linux (push) Has been cancelled
CI / benchmarks | instrumented (push) Has been cancelled
Some checks failed
CI / Determine changes (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / cargo shear (push) Has been cancelled
CI / typos (push) Has been cancelled
CI / mkdocs (push) Has been cancelled
zizmor / Run zizmor (push) Has been cancelled
CI / cargo clippy | ubuntu (push) Has been cancelled
CI / cargo clippy | windows (push) Has been cancelled
CI / cargo dev generate-all (push) Has been cancelled
CI / cargo test | ubuntu (push) Has been cancelled
CI / cargo test | macos (push) Has been cancelled
CI / cargo test | windows (push) Has been cancelled
CI / check windows trampoline | aarch64 (push) Has been cancelled
CI / check windows trampoline | i686 (push) Has been cancelled
CI / check windows trampoline | x86_64 (push) Has been cancelled
CI / test windows trampoline | aarch64 (push) Has been cancelled
CI / test windows trampoline | i686 (push) Has been cancelled
CI / test windows trampoline | x86_64 (push) Has been cancelled
CI / build binary | linux libc (push) Has been cancelled
CI / build binary | linux aarch64 (push) Has been cancelled
CI / build binary | linux musl (push) Has been cancelled
CI / build binary | macos aarch64 (push) Has been cancelled
CI / build binary | macos x86_64 (push) Has been cancelled
CI / build binary | windows x86_64 (push) Has been cancelled
CI / build binary | windows aarch64 (push) Has been cancelled
CI / build binary | msrv (push) Has been cancelled
CI / build binary | freebsd (push) Has been cancelled
CI / ecosystem test | pydantic/pydantic-core (push) Has been cancelled
CI / ecosystem test | prefecthq/prefect (push) Has been cancelled
CI / ecosystem test | pallets/flask (push) Has been cancelled
CI / smoke test | linux (push) Has been cancelled
CI / smoke test | linux aarch64 (push) Has been cancelled
CI / check system | alpine (push) Has been cancelled
CI / smoke test | macos (push) Has been cancelled
CI / smoke test | windows x86_64 (push) Has been cancelled
CI / smoke test | windows aarch64 (push) Has been cancelled
CI / integration test | activate nushell venv (push) Has been cancelled
CI / integration test | conda on ubuntu (push) Has been cancelled
CI / integration test | deadsnakes python3.9 on ubuntu (push) Has been cancelled
CI / integration test | free-threaded on windows (push) Has been cancelled
CI / integration test | aarch64 windows implicit (push) Has been cancelled
CI / integration test | aarch64 windows explicit (push) Has been cancelled
CI / integration test | pypy on ubuntu (push) Has been cancelled
CI / integration test | pypy on windows (push) Has been cancelled
CI / integration test | graalpy on ubuntu (push) Has been cancelled
CI / integration test | graalpy on windows (push) Has been cancelled
CI / integration test | pyodide on ubuntu (push) Has been cancelled
CI / integration test | github actions (push) Has been cancelled
CI / integration test | free-threaded python on github actions (push) Has been cancelled
CI / integration test | pyenv on wsl x86-64 (push) Has been cancelled
CI / integration test | determine publish changes (push) Has been cancelled
CI / integration test | registries (push) Has been cancelled
CI / integration test | uv publish (push) Has been cancelled
CI / integration test | uv_build (push) Has been cancelled
CI / check cache | ubuntu (push) Has been cancelled
CI / check cache | macos aarch64 (push) Has been cancelled
CI / check system | python on debian (push) Has been cancelled
CI / check system | python on fedora (push) Has been cancelled
CI / check system | python on ubuntu (push) Has been cancelled
CI / check system | python on rocky linux 8 (push) Has been cancelled
CI / check system | python on rocky linux 9 (push) Has been cancelled
CI / check system | graalpy on ubuntu (push) Has been cancelled
CI / check system | pypy on ubuntu (push) Has been cancelled
CI / check system | pyston (push) Has been cancelled
CI / check system | python on macos aarch64 (push) Has been cancelled
CI / check system | homebrew python on macos aarch64 (push) Has been cancelled
CI / check system | x86-64 python on macos aarch64 (push) Has been cancelled
CI / check system | python on macos x86-64 (push) Has been cancelled
CI / check system | python3.10 on windows x86-64 (push) Has been cancelled
CI / check system | python3.10 on windows x86 (push) Has been cancelled
CI / check system | python3.13 on windows x86-64 (push) Has been cancelled
CI / check system | x86-64 python3.13 on windows aarch64 (push) Has been cancelled
CI / check system | aarch64 python3.13 on windows aarch64 (push) Has been cancelled
CI / check system | windows registry (push) Has been cancelled
CI / check system | python3.12 via chocolatey (push) Has been cancelled
CI / check system | python3.9 via pyenv (push) Has been cancelled
CI / check system | python3.13 (push) Has been cancelled
CI / check system | conda3.11 on macos aarch64 (push) Has been cancelled
CI / check system | conda3.8 on macos aarch64 (push) Has been cancelled
CI / check system | conda3.11 on linux x86-64 (push) Has been cancelled
CI / check system | conda3.8 on linux x86-64 (push) Has been cancelled
CI / check system | conda3.11 on windows x86-64 (push) Has been cancelled
CI / check system | conda3.8 on windows x86-64 (push) Has been cancelled
CI / check system | amazonlinux (push) Has been cancelled
CI / check system | embedded python3.10 on windows x86-64 (push) Has been cancelled
CI / benchmarks | walltime aarch64 linux (push) Has been cancelled
CI / benchmarks | instrumented (push) Has been cancelled
## Summary This stands up the idea proposed in https://github.com/astral-sh/uv/pull/16046/files#r2384395797.
This commit is contained in:
parent
7d9ea797b0
commit
ab2f394019
13 changed files with 179 additions and 114 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -5351,6 +5351,7 @@ dependencies = [
|
||||||
"uv-distribution-filename",
|
"uv-distribution-filename",
|
||||||
"uv-distribution-types",
|
"uv-distribution-types",
|
||||||
"uv-extract",
|
"uv-extract",
|
||||||
|
"uv-flags",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-git",
|
"uv-git",
|
||||||
"uv-git-types",
|
"uv-git-types",
|
||||||
|
|
@ -5982,6 +5983,13 @@ dependencies = [
|
||||||
"zstd",
|
"zstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uv-flags"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uv-fs"
|
name = "uv-fs"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
|
@ -6085,13 +6093,13 @@ dependencies = [
|
||||||
"thiserror 2.0.16",
|
"thiserror 2.0.16",
|
||||||
"tracing",
|
"tracing",
|
||||||
"uv-distribution-filename",
|
"uv-distribution-filename",
|
||||||
|
"uv-flags",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-normalize",
|
"uv-normalize",
|
||||||
"uv-pep440",
|
"uv-pep440",
|
||||||
"uv-preview",
|
"uv-preview",
|
||||||
"uv-pypi-types",
|
"uv-pypi-types",
|
||||||
"uv-shell",
|
"uv-shell",
|
||||||
"uv-static",
|
|
||||||
"uv-trampoline-builder",
|
"uv-trampoline-builder",
|
||||||
"uv-warnings",
|
"uv-warnings",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
|
|
@ -6559,6 +6567,7 @@ dependencies = [
|
||||||
"uv-distribution",
|
"uv-distribution",
|
||||||
"uv-distribution-filename",
|
"uv-distribution-filename",
|
||||||
"uv-distribution-types",
|
"uv-distribution-types",
|
||||||
|
"uv-flags",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-git",
|
"uv-git",
|
||||||
"uv-git-types",
|
"uv-git-types",
|
||||||
|
|
@ -6621,6 +6630,7 @@ dependencies = [
|
||||||
"uv-configuration",
|
"uv-configuration",
|
||||||
"uv-dirs",
|
"uv-dirs",
|
||||||
"uv-distribution-types",
|
"uv-distribution-types",
|
||||||
|
"uv-flags",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-install-wheel",
|
"uv-install-wheel",
|
||||||
"uv-macros",
|
"uv-macros",
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ uv-distribution = { path = "crates/uv-distribution" }
|
||||||
uv-distribution-filename = { path = "crates/uv-distribution-filename" }
|
uv-distribution-filename = { path = "crates/uv-distribution-filename" }
|
||||||
uv-distribution-types = { path = "crates/uv-distribution-types" }
|
uv-distribution-types = { path = "crates/uv-distribution-types" }
|
||||||
uv-extract = { path = "crates/uv-extract" }
|
uv-extract = { path = "crates/uv-extract" }
|
||||||
|
uv-flags = { path = "crates/uv-flags" }
|
||||||
uv-fs = { path = "crates/uv-fs", features = ["serde", "tokio"] }
|
uv-fs = { path = "crates/uv-fs", features = ["serde", "tokio"] }
|
||||||
uv-git = { path = "crates/uv-git" }
|
uv-git = { path = "crates/uv-git" }
|
||||||
uv-git-types = { path = "crates/uv-git-types" }
|
uv-git-types = { path = "crates/uv-git-types" }
|
||||||
|
|
|
||||||
24
crates/uv-flags/Cargo.toml
Normal file
24
crates/uv-flags/Cargo.toml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
[package]
|
||||||
|
name = "uv-flags"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = { workspace = true }
|
||||||
|
rust-version = { workspace = true }
|
||||||
|
homepage = { workspace = true }
|
||||||
|
documentation = { workspace = true }
|
||||||
|
repository = { workspace = true }
|
||||||
|
authors = { workspace = true }
|
||||||
|
license = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bitflags = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
21
crates/uv-flags/src/lib.rs
Normal file
21
crates/uv-flags/src/lib.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
static FLAGS: OnceLock<EnvironmentFlags> = OnceLock::new();
|
||||||
|
|
||||||
|
bitflags::bitflags! {
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
|
pub struct EnvironmentFlags: u32 {
|
||||||
|
const SKIP_WHEEL_FILENAME_CHECK = 1 << 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize the environment flags.
|
||||||
|
#[allow(clippy::result_unit_err)]
|
||||||
|
pub fn init(flags: EnvironmentFlags) -> Result<(), ()> {
|
||||||
|
FLAGS.set(flags).map_err(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if a specific environment flag is set.
|
||||||
|
pub fn contains(flag: EnvironmentFlags) -> bool {
|
||||||
|
FLAGS.get_or_init(EnvironmentFlags::default).contains(flag)
|
||||||
|
}
|
||||||
|
|
@ -22,13 +22,13 @@ name = "uv_install_wheel"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
uv-distribution-filename = { workspace = true }
|
uv-distribution-filename = { workspace = true }
|
||||||
|
uv-flags = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-normalize = { workspace = true }
|
uv-normalize = { workspace = true }
|
||||||
uv-pep440 = { workspace = true }
|
uv-pep440 = { workspace = true }
|
||||||
uv-preview = { workspace = true }
|
uv-preview = { workspace = true }
|
||||||
uv-pypi-types = { workspace = true }
|
uv-pypi-types = { workspace = true }
|
||||||
uv-shell = { workspace = true }
|
uv-shell = { workspace = true }
|
||||||
uv-static = { workspace = true }
|
|
||||||
uv-trampoline-builder = { workspace = true }
|
uv-trampoline-builder = { workspace = true }
|
||||||
uv-warnings = { workspace = true }
|
uv-warnings = { workspace = true }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ use tracing::{instrument, trace};
|
||||||
use uv_distribution_filename::WheelFilename;
|
use uv_distribution_filename::WheelFilename;
|
||||||
use uv_pep440::Version;
|
use uv_pep440::Version;
|
||||||
use uv_pypi_types::{DirectUrl, Metadata10};
|
use uv_pypi_types::{DirectUrl, Metadata10};
|
||||||
use uv_static::{EnvVars, parse_boolish_environment_variable};
|
|
||||||
|
|
||||||
use crate::linker::{LinkMode, Locks};
|
use crate::linker::{LinkMode, Locks};
|
||||||
use crate::wheel::{
|
use crate::wheel::{
|
||||||
|
|
@ -49,25 +48,15 @@ pub fn install_wheel<Cache: serde::Serialize, Build: serde::Serialize>(
|
||||||
let version = Version::from_str(&version)?;
|
let version = Version::from_str(&version)?;
|
||||||
|
|
||||||
// Validate the wheel name and version.
|
// Validate the wheel name and version.
|
||||||
{
|
if !uv_flags::contains(uv_flags::EnvironmentFlags::SKIP_WHEEL_FILENAME_CHECK) {
|
||||||
if name != filename.name {
|
if name != filename.name {
|
||||||
if !matches!(
|
|
||||||
parse_boolish_environment_variable(EnvVars::UV_SKIP_WHEEL_FILENAME_CHECK),
|
|
||||||
Ok(Some(true))
|
|
||||||
) {
|
|
||||||
return Err(Error::MismatchedName(name, filename.name.clone()));
|
return Err(Error::MismatchedName(name, filename.name.clone()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if version != filename.version && version != filename.version.clone().without_local() {
|
if version != filename.version && version != filename.version.clone().without_local() {
|
||||||
if !matches!(
|
|
||||||
parse_boolish_environment_variable(EnvVars::UV_SKIP_WHEEL_FILENAME_CHECK),
|
|
||||||
Ok(Some(true))
|
|
||||||
) {
|
|
||||||
return Err(Error::MismatchedVersion(version, filename.version.clone()));
|
return Err(Error::MismatchedVersion(version, filename.version.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// We're going step by step though
|
// We're going step by step though
|
||||||
// https://packaging.python.org/en/latest/specifications/binary-distribution-format/#installing-a-wheel-distribution-1-0-py32-none-any-whl
|
// https://packaging.python.org/en/latest/specifications/binary-distribution-format/#installing-a-wheel-distribution-1-0-py32-none-any-whl
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ uv-configuration = { workspace = true }
|
||||||
uv-distribution = { workspace = true }
|
uv-distribution = { workspace = true }
|
||||||
uv-distribution-filename = { workspace = true }
|
uv-distribution-filename = { workspace = true }
|
||||||
uv-distribution-types = { workspace = true }
|
uv-distribution-types = { workspace = true }
|
||||||
|
uv-flags = { workspace = true }
|
||||||
uv-fs = { workspace = true, features = ["serde"] }
|
uv-fs = { workspace = true, features = ["serde"] }
|
||||||
uv-git = { workspace = true }
|
uv-git = { workspace = true }
|
||||||
uv-git-types = { workspace = true }
|
uv-git-types = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ use uv_pypi_types::{
|
||||||
};
|
};
|
||||||
use uv_redacted::DisplaySafeUrl;
|
use uv_redacted::DisplaySafeUrl;
|
||||||
use uv_small_str::SmallString;
|
use uv_small_str::SmallString;
|
||||||
use uv_static::{EnvVars, parse_boolish_environment_variable};
|
|
||||||
use uv_types::{BuildContext, HashStrategy};
|
use uv_types::{BuildContext, HashStrategy};
|
||||||
use uv_workspace::{Editability, WorkspaceMember};
|
use uv_workspace::{Editability, WorkspaceMember};
|
||||||
|
|
||||||
|
|
@ -3241,15 +3240,12 @@ impl PackageWire {
|
||||||
unambiguous_package_ids: &FxHashMap<PackageName, PackageId>,
|
unambiguous_package_ids: &FxHashMap<PackageName, PackageId>,
|
||||||
) -> Result<Package, LockError> {
|
) -> Result<Package, LockError> {
|
||||||
// Consistency check
|
// Consistency check
|
||||||
|
if !uv_flags::contains(uv_flags::EnvironmentFlags::SKIP_WHEEL_FILENAME_CHECK) {
|
||||||
if let Some(version) = &self.id.version {
|
if let Some(version) = &self.id.version {
|
||||||
for wheel in &self.wheels {
|
for wheel in &self.wheels {
|
||||||
if *version != wheel.filename.version
|
if *version != wheel.filename.version
|
||||||
&& *version != wheel.filename.version.clone().without_local()
|
&& *version != wheel.filename.version.clone().without_local()
|
||||||
{
|
{
|
||||||
if !matches!(
|
|
||||||
parse_boolish_environment_variable(EnvVars::UV_SKIP_WHEEL_FILENAME_CHECK),
|
|
||||||
Ok(Some(true))
|
|
||||||
) {
|
|
||||||
return Err(LockError::from(LockErrorKind::InconsistentVersions {
|
return Err(LockError::from(LockErrorKind::InconsistentVersions {
|
||||||
name: self.id.name,
|
name: self.id.name,
|
||||||
version: version.clone(),
|
version: version.clone(),
|
||||||
|
|
@ -3257,10 +3253,10 @@ impl PackageWire {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// We can't check the source dist version since it does not need to contain the version
|
// We can't check the source dist version since it does not need to contain the version
|
||||||
// in the filename.
|
// in the filename.
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let unwire_deps = |deps: Vec<DependencyWire>| -> Result<Vec<Dependency>, LockError> {
|
let unwire_deps = |deps: Vec<DependencyWire>| -> Result<Vec<Dependency>, LockError> {
|
||||||
deps.into_iter()
|
deps.into_iter()
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ uv-cache-info = { workspace = true, features = ["schemars"] }
|
||||||
uv-configuration = { workspace = true, features = ["schemars", "clap"] }
|
uv-configuration = { workspace = true, features = ["schemars", "clap"] }
|
||||||
uv-dirs = { workspace = true }
|
uv-dirs = { workspace = true }
|
||||||
uv-distribution-types = { workspace = true, features = ["schemars"] }
|
uv-distribution-types = { workspace = true, features = ["schemars"] }
|
||||||
|
uv-flags = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-install-wheel = { workspace = true, features = ["schemars", "clap"] }
|
uv-install-wheel = { workspace = true, features = ["schemars", "clap"] }
|
||||||
uv-macros = { workspace = true }
|
uv-macros = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ use std::ops::Deref;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use uv_dirs::{system_config_file, user_config_dir};
|
use uv_dirs::{system_config_file, user_config_dir};
|
||||||
|
use uv_flags::EnvironmentFlags;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_static::{EnvVars, parse_boolish_environment_variable, parse_string_environment_variable};
|
use uv_static::EnvVars;
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
|
|
||||||
pub use crate::combine::*;
|
pub use crate::combine::*;
|
||||||
|
|
@ -554,8 +555,12 @@ pub enum Error {
|
||||||
#[error("Failed to parse: `{}`. The `{}` field is not allowed in a `uv.toml` file. `{}` is only applicable in the context of a project, and should be placed in a `pyproject.toml` file instead.", _0.user_display(), _1, _1)]
|
#[error("Failed to parse: `{}`. The `{}` field is not allowed in a `uv.toml` file. `{}` is only applicable in the context of a project, and should be placed in a `pyproject.toml` file instead.", _0.user_display(), _1, _1)]
|
||||||
PyprojectOnlyField(PathBuf, &'static str),
|
PyprojectOnlyField(PathBuf, &'static str),
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("Failed to parse environment variable `{name}` with invalid value `{value}`: {err}")]
|
||||||
InvalidEnvironmentVariable(String),
|
InvalidEnvironmentVariable {
|
||||||
|
name: String,
|
||||||
|
value: String,
|
||||||
|
err: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options loaded from environment variables.
|
/// Options loaded from environment variables.
|
||||||
|
|
@ -564,6 +569,7 @@ pub enum Error {
|
||||||
/// the CLI level, however there are limited semantics in that context.
|
/// the CLI level, however there are limited semantics in that context.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EnvironmentOptions {
|
pub struct EnvironmentOptions {
|
||||||
|
pub skip_wheel_filename_check: Option<bool>,
|
||||||
pub python_install_bin: Option<bool>,
|
pub python_install_bin: Option<bool>,
|
||||||
pub python_install_registry: Option<bool>,
|
pub python_install_registry: Option<bool>,
|
||||||
pub install_mirrors: PythonInstallMirrors,
|
pub install_mirrors: PythonInstallMirrors,
|
||||||
|
|
@ -574,28 +580,109 @@ impl EnvironmentOptions {
|
||||||
/// Create a new [`EnvironmentOptions`] from environment variables.
|
/// Create a new [`EnvironmentOptions`] from environment variables.
|
||||||
pub fn new() -> Result<Self, Error> {
|
pub fn new() -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
python_install_bin: parse_boolish_environment_variable(EnvVars::UV_PYTHON_INSTALL_BIN)
|
skip_wheel_filename_check: parse_boolish_environment_variable(
|
||||||
.map_err(Error::InvalidEnvironmentVariable)?,
|
EnvVars::UV_SKIP_WHEEL_FILENAME_CHECK,
|
||||||
|
)?,
|
||||||
|
python_install_bin: parse_boolish_environment_variable(EnvVars::UV_PYTHON_INSTALL_BIN)?,
|
||||||
python_install_registry: parse_boolish_environment_variable(
|
python_install_registry: parse_boolish_environment_variable(
|
||||||
EnvVars::UV_PYTHON_INSTALL_REGISTRY,
|
EnvVars::UV_PYTHON_INSTALL_REGISTRY,
|
||||||
)
|
)?,
|
||||||
.map_err(Error::InvalidEnvironmentVariable)?,
|
|
||||||
install_mirrors: PythonInstallMirrors {
|
install_mirrors: PythonInstallMirrors {
|
||||||
python_install_mirror: parse_string_environment_variable(
|
python_install_mirror: parse_string_environment_variable(
|
||||||
EnvVars::UV_PYTHON_INSTALL_MIRROR,
|
EnvVars::UV_PYTHON_INSTALL_MIRROR,
|
||||||
)
|
)?,
|
||||||
.map_err(Error::InvalidEnvironmentVariable)?,
|
|
||||||
pypy_install_mirror: parse_string_environment_variable(
|
pypy_install_mirror: parse_string_environment_variable(
|
||||||
EnvVars::UV_PYPY_INSTALL_MIRROR,
|
EnvVars::UV_PYPY_INSTALL_MIRROR,
|
||||||
)
|
)?,
|
||||||
.map_err(Error::InvalidEnvironmentVariable)?,
|
|
||||||
python_downloads_json_url: parse_string_environment_variable(
|
python_downloads_json_url: parse_string_environment_variable(
|
||||||
EnvVars::UV_PYTHON_DOWNLOADS_JSON_URL,
|
EnvVars::UV_PYTHON_DOWNLOADS_JSON_URL,
|
||||||
)
|
)?,
|
||||||
.map_err(Error::InvalidEnvironmentVariable)?,
|
|
||||||
},
|
},
|
||||||
log_context: parse_boolish_environment_variable(EnvVars::UV_LOG_CONTEXT)
|
log_context: parse_boolish_environment_variable(EnvVars::UV_LOG_CONTEXT)?,
|
||||||
.map_err(Error::InvalidEnvironmentVariable)?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a boolean environment variable.
|
||||||
|
///
|
||||||
|
/// Adapted from Clap's `BoolishValueParser` which is dual licensed under the MIT and Apache-2.0.
|
||||||
|
fn parse_boolish_environment_variable(name: &'static str) -> Result<Option<bool>, Error> {
|
||||||
|
// See `clap_builder/src/util/str_to_bool.rs`
|
||||||
|
// We want to match Clap's accepted values
|
||||||
|
|
||||||
|
// True values are `y`, `yes`, `t`, `true`, `on`, and `1`.
|
||||||
|
const TRUE_LITERALS: [&str; 6] = ["y", "yes", "t", "true", "on", "1"];
|
||||||
|
|
||||||
|
// False values are `n`, `no`, `f`, `false`, `off`, and `0`.
|
||||||
|
const FALSE_LITERALS: [&str; 6] = ["n", "no", "f", "false", "off", "0"];
|
||||||
|
|
||||||
|
// Converts a string literal representation of truth to true or false.
|
||||||
|
//
|
||||||
|
// `false` values are `n`, `no`, `f`, `false`, `off`, and `0` (case insensitive).
|
||||||
|
//
|
||||||
|
// Any other value will be considered as `true`.
|
||||||
|
fn str_to_bool(val: impl AsRef<str>) -> Option<bool> {
|
||||||
|
let pat: &str = &val.as_ref().to_lowercase();
|
||||||
|
if TRUE_LITERALS.contains(&pat) {
|
||||||
|
Some(true)
|
||||||
|
} else if FALSE_LITERALS.contains(&pat) {
|
||||||
|
Some(false)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(value) = std::env::var_os(name) else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(value) = value.to_str() else {
|
||||||
|
return Err(Error::InvalidEnvironmentVariable {
|
||||||
|
name: name.to_string(),
|
||||||
|
value: value.to_string_lossy().to_string(),
|
||||||
|
err: "expected a valid UTF-8 string".to_string(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(value) = str_to_bool(value) else {
|
||||||
|
return Err(Error::InvalidEnvironmentVariable {
|
||||||
|
name: name.to_string(),
|
||||||
|
value: value.to_string(),
|
||||||
|
err: "expected a boolish value".to_string(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a string environment variable.
|
||||||
|
fn parse_string_environment_variable(name: &'static str) -> Result<Option<String>, Error> {
|
||||||
|
match std::env::var(name) {
|
||||||
|
Ok(v) => {
|
||||||
|
if v.is_empty() {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Ok(Some(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => match e {
|
||||||
|
std::env::VarError::NotPresent => Ok(None),
|
||||||
|
std::env::VarError::NotUnicode(err) => Err(Error::InvalidEnvironmentVariable {
|
||||||
|
name: name.to_string(),
|
||||||
|
value: err.to_string_lossy().to_string(),
|
||||||
|
err: "expected a valid UTF-8 string".to_string(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Populate the [`EnvironmentFlags`] from the given [`EnvironmentOptions`].
|
||||||
|
impl From<&EnvironmentOptions> for EnvironmentFlags {
|
||||||
|
fn from(options: &EnvironmentOptions) -> Self {
|
||||||
|
let mut flags = Self::empty();
|
||||||
|
if options.skip_wheel_filename_check == Some(true) {
|
||||||
|
flags.insert(Self::SKIP_WHEEL_FILENAME_CHECK);
|
||||||
|
}
|
||||||
|
flags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,3 @@
|
||||||
pub use env_vars::*;
|
pub use env_vars::*;
|
||||||
|
|
||||||
mod env_vars;
|
mod env_vars;
|
||||||
|
|
||||||
/// Parse a boolean environment variable.
|
|
||||||
///
|
|
||||||
/// Adapted from Clap's `BoolishValueParser` which is dual licensed under the MIT and Apache-2.0.
|
|
||||||
pub fn parse_boolish_environment_variable(name: &'static str) -> Result<Option<bool>, String> {
|
|
||||||
// See `clap_builder/src/util/str_to_bool.rs`
|
|
||||||
// We want to match Clap's accepted values
|
|
||||||
|
|
||||||
// True values are `y`, `yes`, `t`, `true`, `on`, and `1`.
|
|
||||||
const TRUE_LITERALS: [&str; 6] = ["y", "yes", "t", "true", "on", "1"];
|
|
||||||
|
|
||||||
// False values are `n`, `no`, `f`, `false`, `off`, and `0`.
|
|
||||||
const FALSE_LITERALS: [&str; 6] = ["n", "no", "f", "false", "off", "0"];
|
|
||||||
|
|
||||||
// Converts a string literal representation of truth to true or false.
|
|
||||||
//
|
|
||||||
// `false` values are `n`, `no`, `f`, `false`, `off`, and `0` (case insensitive).
|
|
||||||
//
|
|
||||||
// Any other value will be considered as `true`.
|
|
||||||
fn str_to_bool(val: impl AsRef<str>) -> Option<bool> {
|
|
||||||
let pat: &str = &val.as_ref().to_lowercase();
|
|
||||||
if TRUE_LITERALS.contains(&pat) {
|
|
||||||
Some(true)
|
|
||||||
} else if FALSE_LITERALS.contains(&pat) {
|
|
||||||
Some(false)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(value) = std::env::var_os(name) else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(value) = value.to_str() else {
|
|
||||||
return Err(format!(
|
|
||||||
"Failed to parse environment variable `{}` with invalid value `{}`: expected a valid UTF-8 string",
|
|
||||||
name,
|
|
||||||
value.to_string_lossy()
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(value) = str_to_bool(value) else {
|
|
||||||
return Err(format!(
|
|
||||||
"Failed to parse environment variable `{name}` with invalid value `{value}`: expected a boolish value"
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Some(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a string environment variable.
|
|
||||||
pub fn parse_string_environment_variable(name: &'static str) -> Result<Option<String>, String> {
|
|
||||||
match std::env::var(name) {
|
|
||||||
Ok(v) => {
|
|
||||||
if v.is_empty() {
|
|
||||||
Ok(None)
|
|
||||||
} else {
|
|
||||||
Ok(Some(v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => match e {
|
|
||||||
std::env::VarError::NotPresent => Ok(None),
|
|
||||||
std::env::VarError::NotUnicode(err) => Err(format!(
|
|
||||||
"Failed to parse environment variable `{}` with invalid value `{}`: expected a valid UTF-8 string",
|
|
||||||
name,
|
|
||||||
err.to_string_lossy()
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ uv-distribution = { workspace = true }
|
||||||
uv-distribution-filename = { workspace = true }
|
uv-distribution-filename = { workspace = true }
|
||||||
uv-distribution-types = { workspace = true }
|
uv-distribution-types = { workspace = true }
|
||||||
uv-extract = { workspace = true }
|
uv-extract = { workspace = true }
|
||||||
|
uv-flags = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-git = { workspace = true }
|
uv-git = { workspace = true }
|
||||||
uv-git-types = { workspace = true }
|
uv-git-types = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ use uv_cli::{
|
||||||
};
|
};
|
||||||
use uv_client::BaseClientBuilder;
|
use uv_client::BaseClientBuilder;
|
||||||
use uv_configuration::min_stack_size;
|
use uv_configuration::min_stack_size;
|
||||||
|
use uv_flags::EnvironmentFlags;
|
||||||
use uv_fs::{CWD, Simplified};
|
use uv_fs::{CWD, Simplified};
|
||||||
#[cfg(feature = "self-update")]
|
#[cfg(feature = "self-update")]
|
||||||
use uv_pep440::release_specifiers_to_ranges;
|
use uv_pep440::release_specifiers_to_ranges;
|
||||||
|
|
@ -314,6 +315,10 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
// Resolve the cache settings.
|
// Resolve the cache settings.
|
||||||
let cache_settings = CacheSettings::resolve(*cli.top_level.cache_args, filesystem.as_ref());
|
let cache_settings = CacheSettings::resolve(*cli.top_level.cache_args, filesystem.as_ref());
|
||||||
|
|
||||||
|
// Set the global flags.
|
||||||
|
uv_flags::init(EnvironmentFlags::from(&environment))
|
||||||
|
.map_err(|()| anyhow::anyhow!("Flags are already initialized"))?;
|
||||||
|
|
||||||
// Enforce the required version.
|
// Enforce the required version.
|
||||||
if let Some(required_version) = globals.required_version.as_ref() {
|
if let Some(required_version) = globals.required_version.as_ref() {
|
||||||
let package_version = uv_pep440::Version::from_str(uv_version::version())?;
|
let package_version = uv_pep440::Version::from_str(uv_version::version())?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue