uv_distribution/
download.rs1use std::path::Path;
2
3use uv_cache_info::CacheInfo;
4use uv_distribution_filename::WheelFilename;
5use uv_distribution_types::{BuildInfo, BuiltDist, CachedDist, Dist, Hashed};
6use uv_metadata::{find_flat_dist_info, read_flat_wheel_metadata, read_wheel_variant};
7use uv_preview::PreviewFeature;
8use uv_pypi_types::{HashDigest, HashDigests, ResolutionMetadata};
9
10use crate::{Error, supported_variant_properties};
11
12pub fn check_supported_wheel_variant(dist: &BuiltDist) -> Result<(), Error> {
14 let filename = dist.wheel_filename();
15 if filename.variant().is_some()
16 && (dist.index().is_none() || !uv_preview::is_enabled(PreviewFeature::WheelVariants))
17 {
18 return Err(Error::UnsupportedWheelVariant(Box::new(filename.clone())));
19 }
20 Ok(())
21}
22
23pub(crate) fn check_wheel_variant_compatibility(
25 filename: &WheelFilename,
26 archive: &Path,
27) -> Result<(), Error> {
28 let Some(label) = filename.variant() else {
29 return Ok(());
30 };
31 if !uv_preview::is_enabled(PreviewFeature::WheelVariants) {
32 return Err(Error::UnsupportedWheelVariant(Box::new(filename.clone())));
33 }
34
35 let dist_info = find_flat_dist_info(filename, archive)
36 .map_err(|err| Error::WheelMetadata(archive.to_path_buf(), Box::new(err)))?;
37 let path = archive.join(format!("{dist_info}.dist-info/variant.json"));
38 let metadata = read_wheel_variant(&path, label)
39 .map_err(|err| Error::WheelMetadata(path, Box::new(err)))?;
40 if let Some(properties) =
41 metadata.unsupported_variant_properties(label, &supported_variant_properties(&metadata))
42 {
43 return Err(Error::IncompatibleWheelVariant {
44 label: label.clone(),
45 properties,
46 });
47 }
48 Ok(())
49}
50
51#[derive(Debug, Clone)]
53pub struct LocalWheel {
54 pub(crate) dist: Dist,
56 pub(crate) filename: WheelFilename,
58 pub(crate) archive: Box<Path>,
61 pub(crate) cache: CacheInfo,
63 pub(crate) build: Option<BuildInfo>,
65 pub(crate) hashes: HashDigests,
67}
68
69impl LocalWheel {
70 fn remote(&self) -> &Dist {
72 &self.dist
73 }
74
75 pub(crate) fn metadata(&self) -> Result<ResolutionMetadata, Error> {
77 read_flat_wheel_metadata(&self.filename, &self.archive)
78 .map_err(|err| Error::WheelMetadata(self.archive.to_path_buf(), Box::new(err)))
79 }
80}
81
82impl Hashed for LocalWheel {
83 fn hashes(&self) -> &[HashDigest] {
84 self.hashes.as_slice()
85 }
86}
87
88impl From<LocalWheel> for CachedDist {
90 fn from(wheel: LocalWheel) -> Self {
91 Self::from_remote(
92 wheel.dist,
93 wheel.filename,
94 wheel.hashes,
95 wheel.cache,
96 wheel.build,
97 wheel.archive,
98 )
99 }
100}
101
102impl std::fmt::Display for LocalWheel {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 write!(f, "{}", self.remote())
105 }
106}