Refactor dist info variants json

This commit is contained in:
konstin 2025-10-02 10:06:41 +02:00 committed by Charlie Marsh
parent fa1585cadf
commit 2c0750849b
6 changed files with 37 additions and 32 deletions

1
Cargo.lock generated
View File

@ -5360,6 +5360,7 @@ dependencies = [
"uv-torch", "uv-torch",
"uv-trampoline-builder", "uv-trampoline-builder",
"uv-types", "uv-types",
"uv-variants",
"uv-version", "uv-version",
"uv-virtualenv", "uv-virtualenv",
"uv-warnings", "uv-warnings",

View File

@ -17,10 +17,10 @@ use uv_normalize::PackageName;
use uv_pep440::Version; use uv_pep440::Version;
use uv_pypi_types::{DirectUrl, MetadataError}; use uv_pypi_types::{DirectUrl, MetadataError};
use uv_redacted::DisplaySafeUrl; use uv_redacted::DisplaySafeUrl;
use uv_variants::variants_json::DistInfoVariantsJson;
use crate::{ use crate::{
BuildInfo, DistributionMetadata, InstalledMetadata, InstalledVersion, Name, VariantsJson, BuildInfo, DistributionMetadata, InstalledMetadata, InstalledVersion, Name, VersionOrUrlRef,
VersionOrUrlRef,
}; };
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -486,15 +486,16 @@ impl InstalledDist {
} }
/// Read the `variant.json` file of the distribution, if it exists. /// Read the `variant.json` file of the distribution, if it exists.
pub fn read_variant_json(&self) -> Result<Option<VariantsJson>, InstalledDistError> { pub fn read_variant_json(&self) -> Result<Option<DistInfoVariantsJson>, InstalledDistError> {
let path = self.install_path().join("variant.json"); let path = self.install_path().join("variant.json");
let file = match fs_err::File::open(&path) { let file = match fs_err::File::open(&path) {
Ok(file) => file, Ok(file) => file,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None), Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
Err(err) => return Err(err.into()), Err(err) => return Err(err.into()),
}; };
let variants_json = let variants_json = serde_json::from_reader::<BufReader<fs_err::File>, DistInfoVariantsJson>(
serde_json::from_reader::<BufReader<fs_err::File>, VariantsJson>(BufReader::new(file))?; BufReader::new(file),
)?;
Ok(Some(variants_json)) Ok(Some(variants_json))
} }

View File

@ -1,5 +1,6 @@
use rustc_hash::FxHashMap; use std::fmt::Display;
use std::{fmt::Display, str::FromStr}; use std::str::FromStr;
use uv_normalize::{InvalidNameError, PackageName}; use uv_normalize::{InvalidNameError, PackageName};
use uv_pep440::{Version, VersionParseError}; use uv_pep440::{Version, VersionParseError};
@ -13,25 +14,6 @@ pub enum VariantsJsonError {
InvalidVersion(#[from] VersionParseError), InvalidVersion(#[from] VersionParseError),
} }
/// A `<name>-<version>-variants.json` file.
#[derive(Debug, Clone, serde::Deserialize)]
pub struct VariantsJson {
variants: FxHashMap<String, serde_json::Value>,
}
impl VariantsJson {
/// Returns the label for the current variant.
pub fn label(&self) -> Option<&str> {
let mut keys = self.variants.keys();
let label = keys.next()?;
if keys.next().is_some() {
None
} else {
Some(label)
}
}
}
/// A `<name>-<version>-variants.json` filename. /// A `<name>-<version>-variants.json` filename.
#[derive( #[derive(
Debug, Debug,

View File

@ -96,6 +96,26 @@ pub struct VariantsJsonContent {
pub variants: FxHashMap<VariantLabel, Variant>, pub variants: FxHashMap<VariantLabel, Variant>,
} }
/// A `{name}-{version}.dist-info/variant.json` file.
#[derive(Debug, Clone, serde::Deserialize)]
#[allow(clippy::zero_sized_map_values)]
pub struct DistInfoVariantsJson {
pub variants: FxHashMap<VariantLabel, serde::de::IgnoredAny>,
}
impl DistInfoVariantsJson {
/// Returns the label for the current variant.
pub fn label(&self) -> Option<&VariantLabel> {
let mut keys = self.variants.keys();
let label = keys.next()?;
if keys.next().is_some() {
None
} else {
Some(label)
}
}
}
/// Default provider priorities /// Default provider priorities
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]

View File

@ -59,6 +59,7 @@ uv-tool = { workspace = true }
uv-torch = { workspace = true } uv-torch = { workspace = true }
uv-trampoline-builder = { workspace = true } uv-trampoline-builder = { workspace = true }
uv-types = { workspace = true } uv-types = { workspace = true }
uv-variants = { workspace = true }
uv-version = { workspace = true } uv-version = { workspace = true }
uv-virtualenv = { workspace = true } uv-virtualenv = { workspace = true }
uv-warnings = { workspace = true } uv-warnings = { workspace = true }

View File

@ -16,10 +16,9 @@ use uv_cache_info::Timestamp;
use uv_cli::ListFormat; use uv_cli::ListFormat;
use uv_client::{BaseClientBuilder, RegistryClientBuilder}; use uv_client::{BaseClientBuilder, RegistryClientBuilder};
use uv_configuration::{Concurrency, IndexStrategy, KeyringProviderType}; use uv_configuration::{Concurrency, IndexStrategy, KeyringProviderType};
use uv_distribution_filename::DistFilename; use uv_distribution_filename::{DistFilename, VariantLabel};
use uv_distribution_types::{ use uv_distribution_types::{
Diagnostic, IndexCapabilities, IndexLocations, InstalledDist, Name, RequiresPython, Diagnostic, IndexCapabilities, IndexLocations, InstalledDist, Name, RequiresPython,
VariantsJson,
}; };
use uv_fs::Simplified; use uv_fs::Simplified;
use uv_installer::SitePackages; use uv_installer::SitePackages;
@ -29,6 +28,7 @@ use uv_preview::Preview;
use uv_python::PythonRequest; use uv_python::PythonRequest;
use uv_python::{EnvironmentPreference, PythonEnvironment, PythonPreference}; use uv_python::{EnvironmentPreference, PythonEnvironment, PythonPreference};
use uv_resolver::{ExcludeNewer, PrereleaseMode}; use uv_resolver::{ExcludeNewer, PrereleaseMode};
use uv_variants::variants_json::DistInfoVariantsJson;
use crate::commands::ExitStatus; use crate::commands::ExitStatus;
use crate::commands::pip::latest::LatestClient; use crate::commands::pip::latest::LatestClient;
@ -172,8 +172,8 @@ pub(crate) async fn pip_list(
.ok() .ok()
.flatten() .flatten()
.as_ref() .as_ref()
.and_then(VariantsJson::label) .and_then(DistInfoVariantsJson::label)
.map(ToString::to_string), .cloned(),
latest_version: latest latest_version: latest
.get(dist.name()) .get(dist.name())
.and_then(|filename| filename.as_ref()) .and_then(|filename| filename.as_ref())
@ -220,7 +220,7 @@ pub(crate) async fn pip_list(
.ok() .ok()
.flatten() .flatten()
.as_ref() .as_ref()
.and_then(VariantsJson::label) .and_then(DistInfoVariantsJson::label)
.map(ToString::to_string) .map(ToString::to_string)
}) })
.collect_vec(); .collect_vec();
@ -360,7 +360,7 @@ struct Entry {
name: PackageName, name: PackageName,
version: Version, version: Version,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
variant: Option<String>, variant: Option<VariantLabel>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
latest_version: Option<Version>, latest_version: Option<Version>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]