diff --git a/Cargo.lock b/Cargo.lock index 2faea988b..2f25cf023 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6797,7 +6797,6 @@ name = "uv-variants" version = "0.1.0" dependencies = [ "indexmap", - "indoc", "insta", "itertools 0.14.0", "rustc-hash", diff --git a/crates/uv-distribution/src/distribution_database.rs b/crates/uv-distribution/src/distribution_database.rs index 7683b8913..94f08319e 100644 --- a/crates/uv-distribution/src/distribution_database.rs +++ b/crates/uv-distribution/src/distribution_database.rs @@ -1,5 +1,5 @@ use futures::{FutureExt, StreamExt, TryStreamExt}; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use std::ffi::OsString; use std::future::Future; use std::path::Path; @@ -625,7 +625,8 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> { // Query the install time provider. // TODO(konsti): Don't use threads if we're fully static. - let mut provider_outputs: FxHashMap> = + let mut disabled_namespaces = FxHashSet::default(); + let mut resolved_namespaces: FxHashMap> = futures::stream::iter(variants_json.providers.iter().filter(|(_, provider)| { provider.plugin_use.unwrap_or_default().run_on_install() && provider @@ -641,12 +642,20 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> { .await?; // "Query" the non-install time providers, whose properties are all in the priorities - for (namespace, _provider) in variants_json.providers.iter().filter(|(_, provider)| { - !provider.plugin_use.unwrap_or_default().run_on_install() - && provider - .enable_if - .evaluate(marker_env, &MarkerVariantsUniversal, &[]) - }) { + for (namespace, provider) in &variants_json.providers { + // Track disabled namespaces for consistency checks. + if !provider + .enable_if + .evaluate(marker_env, &MarkerVariantsUniversal, &[]) + { + disabled_namespaces.insert(namespace.clone()); + continue; + } + + if provider.plugin_use.unwrap_or_default().run_on_install() { + continue; + } + let Some(features) = variants_json.default_priorities.property.get(namespace) else { warn!( "Missing namespace {namespace} in default properties for {}=={}", @@ -654,7 +663,7 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> { ); continue; }; - provider_outputs.insert( + resolved_namespaces.insert( namespace.clone(), Arc::new(VariantProviderOutput { namespace: namespace.clone(), @@ -665,7 +674,8 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> { Ok(ResolvedVariants { variants_json, - target_variants: provider_outputs, + resolved_namespaces, + disabled_namespaces, }) } diff --git a/crates/uv-variant-frontend/src/lib.rs b/crates/uv-variant-frontend/src/lib.rs index 5d121839f..309010908 100644 --- a/crates/uv-variant-frontend/src/lib.rs +++ b/crates/uv-variant-frontend/src/lib.rs @@ -74,7 +74,7 @@ impl VariantBuild { let no_isolation = env::var(EnvVars::UV_NO_PROVIDER_ISOLATION).is_ok_and(|no_provider_isolation| { no_provider_isolation - .split(",") + .split(',') .any(|api| (api) == plugin_api) }); diff --git a/crates/uv-variants/src/resolved_variants.rs b/crates/uv-variants/src/resolved_variants.rs index 7d85237a1..213579aef 100644 --- a/crates/uv-variants/src/resolved_variants.rs +++ b/crates/uv-variants/src/resolved_variants.rs @@ -1,7 +1,7 @@ use std::sync::Arc; -use rustc_hash::FxHashMap; -use tracing::{debug, warn}; +use rustc_hash::{FxHashMap, FxHashSet}; +use tracing::{debug, trace, warn}; use uv_distribution_filename::VariantLabel; use uv_pep508::{VariantNamespace, VariantValue}; @@ -12,7 +12,9 @@ use crate::variants_json::{DefaultPriorities, Variant, VariantsJsonContent}; #[derive(Debug, Clone)] pub struct ResolvedVariants { pub variants_json: VariantsJsonContent, - pub target_variants: FxHashMap>, + pub resolved_namespaces: FxHashMap>, + /// Namespaces where `enable-if` didn't match. + pub disabled_namespaces: FxHashSet, } impl ResolvedVariants { @@ -24,7 +26,8 @@ impl ResolvedVariants { score_variant( &self.variants_json.default_priorities, - &self.target_variants, + &self.resolved_namespaces, + &self.disabled_namespaces, variants_properties, ) } @@ -34,6 +37,7 @@ impl ResolvedVariants { pub fn score_variant( default_priorities: &DefaultPriorities, target_namespaces: &FxHashMap>, + disabled_namespaces: &FxHashSet, variants_properties: &Variant, ) -> Option> { for (namespace, features) in &**variants_properties { @@ -54,11 +58,15 @@ pub fn score_variant( // comparison function instead. let mut scores = Vec::new(); for namespace in &default_priorities.namespace { + if disabled_namespaces.contains(namespace) { + trace!("Skipping disabled namespace: {}", namespace); + continue; + } // Explicit priorities are optional, but take priority over the provider let explicit_feature_priorities = default_priorities.feature.get(namespace); let Some(target_variants) = target_namespaces.get(namespace) else { // TODO(konsti): Can this even happen? - debug!("missing namespace priority {namespace}"); + debug!("Missing namespace priority: {namespace}"); continue; }; let feature_priorities = explicit_feature_priorities.into_iter().flatten().chain( @@ -108,7 +116,7 @@ pub fn score_variant( mod tests { use insta::assert_snapshot; use itertools::Itertools; - use rustc_hash::FxHashMap; + use rustc_hash::{FxHashMap, FxHashSet}; use serde_json::json; use std::sync::Arc; @@ -159,7 +167,12 @@ mod tests { } fn score(variant: &Variant) -> Option { - let score = score_variant(&default_priorities(), &host(), variant)?; + let score = score_variant( + &default_priorities(), + &host(), + &FxHashSet::default(), + variant, + )?; Some(score.iter().map(ToString::to_string).join(", ")) } @@ -267,8 +280,13 @@ mod tests { // "shuffle" wheels2.reverse(); wheels2.sort_by(|a, b| { - score_variant(&default_priorities(), &host(), a) - .cmp(&score_variant(&default_priorities(), &host(), b)) + score_variant(&default_priorities(), &host(), &FxHashSet::default(), a) + .cmp(&score_variant( + &default_priorities(), + &host(), + &FxHashSet::default(), + b, + )) // higher is better .reverse() });