1
1
use std:: fmt:: { Display , Formatter } ;
2
- use uv_distribution_filename:: BuildTag ;
2
+ use uv_distribution_filename:: { BuildTag , WheelFilename } ;
3
3
4
4
use uv_pep440:: VersionSpecifiers ;
5
+ use uv_pep508:: { MarkerExpression , MarkerOperator , MarkerTree , MarkerValueString } ;
5
6
use uv_platform_tags:: { IncompatibleTag , TagPriority } ;
6
7
use uv_pypi_types:: { HashDigest , Yanked } ;
7
8
@@ -14,7 +15,7 @@ use crate::{
14
15
pub struct PrioritizedDist ( Box < PrioritizedDistInner > ) ;
15
16
16
17
/// [`PrioritizedDist`] is boxed because [`Dist`] is large.
17
- #[ derive( Debug , Default , Clone ) ]
18
+ #[ derive( Debug , Clone ) ]
18
19
struct PrioritizedDistInner {
19
20
/// The highest-priority source distribution. Between compatible source distributions this priority is arbitrary.
20
21
source : Option < ( RegistrySourceDist , SourceDistCompatibility ) > ,
@@ -25,6 +26,20 @@ struct PrioritizedDistInner {
25
26
wheels : Vec < ( RegistryBuiltWheel , WheelCompatibility ) > ,
26
27
/// The hashes for each distribution.
27
28
hashes : Vec < HashDigest > ,
29
+ /// The set of supported platforms for the distribution, described in terms of their markers.
30
+ markers : MarkerTree ,
31
+ }
32
+
33
+ impl Default for PrioritizedDistInner {
34
+ fn default ( ) -> Self {
35
+ Self {
36
+ source : None ,
37
+ best_wheel_index : None ,
38
+ wheels : Vec :: new ( ) ,
39
+ hashes : Vec :: new ( ) ,
40
+ markers : MarkerTree :: FALSE ,
41
+ }
42
+ }
28
43
}
29
44
30
45
/// A distribution that can be used for both resolution and installation.
@@ -70,6 +85,16 @@ impl CompatibleDist<'_> {
70
85
CompatibleDist :: IncompatibleWheel { sdist, .. } => sdist. file . requires_python . as_ref ( ) ,
71
86
}
72
87
}
88
+
89
+ /// Return the set of supported platform the distribution, in terms of their markers.
90
+ pub fn implied_markers ( & self ) -> MarkerTree {
91
+ match self {
92
+ CompatibleDist :: InstalledDist ( _) => MarkerTree :: TRUE ,
93
+ CompatibleDist :: SourceDist { prioritized, .. } => prioritized. 0 . markers ,
94
+ CompatibleDist :: CompatibleWheel { prioritized, .. } => prioritized. 0 . markers ,
95
+ CompatibleDist :: IncompatibleWheel { prioritized, .. } => prioritized. 0 . markers ,
96
+ }
97
+ }
73
98
}
74
99
75
100
#[ derive( Debug , PartialEq , Eq , Clone ) ]
@@ -257,6 +282,7 @@ impl PrioritizedDist {
257
282
compatibility : WheelCompatibility ,
258
283
) -> Self {
259
284
Self ( Box :: new ( PrioritizedDistInner {
285
+ markers : implied_markers ( & dist. filename ) ,
260
286
best_wheel_index : Some ( 0 ) ,
261
287
wheels : vec ! [ ( dist, compatibility) ] ,
262
288
source : None ,
@@ -271,6 +297,7 @@ impl PrioritizedDist {
271
297
compatibility : SourceDistCompatibility ,
272
298
) -> Self {
273
299
Self ( Box :: new ( PrioritizedDistInner {
300
+ markers : MarkerTree :: TRUE ,
274
301
best_wheel_index : None ,
275
302
wheels : vec ! [ ] ,
276
303
source : Some ( ( dist, compatibility) ) ,
@@ -293,8 +320,11 @@ impl PrioritizedDist {
293
320
} else {
294
321
self . 0 . best_wheel_index = Some ( self . 0 . wheels . len ( ) ) ;
295
322
}
296
- self . 0 . wheels . push ( ( dist, compatibility) ) ;
297
323
self . 0 . hashes . extend ( hashes) ;
324
+ if !self . 0 . markers . is_true ( ) {
325
+ self . 0 . markers . or ( implied_markers ( & dist. filename ) ) ;
326
+ }
327
+ self . 0 . wheels . push ( ( dist, compatibility) ) ;
298
328
}
299
329
300
330
/// Insert the given source distribution into the [`PrioritizedDist`].
@@ -312,7 +342,9 @@ impl PrioritizedDist {
312
342
} else {
313
343
self . 0 . source = Some ( ( dist, compatibility) ) ;
314
344
}
315
-
345
+ if !self . 0 . markers . is_true ( ) {
346
+ self . 0 . markers . or ( MarkerTree :: TRUE ) ;
347
+ }
316
348
self . 0 . hashes . extend ( hashes) ;
317
349
}
318
350
@@ -563,6 +595,7 @@ impl IncompatibleSource {
563
595
}
564
596
565
597
impl IncompatibleWheel {
598
+ #[ allow( clippy:: match_like_matches_macro) ]
566
599
fn is_more_compatible ( & self , other : & Self ) -> bool {
567
600
match self {
568
601
Self :: ExcludeNewer ( timestamp_self) => match other {
@@ -599,3 +632,39 @@ impl IncompatibleWheel {
599
632
}
600
633
}
601
634
}
635
+
636
+ /// Given a wheel filename, determine the set of supported platforms, in terms of their markers.
637
+ pub fn implied_markers ( filename : & WheelFilename ) -> MarkerTree {
638
+ let mut marker = MarkerTree :: FALSE ;
639
+ for platform_tag in & filename. platform_tag {
640
+ match platform_tag. as_str ( ) {
641
+ "any" => marker. or ( MarkerTree :: TRUE ) ,
642
+ tag if tag. starts_with ( "win" ) => {
643
+ marker. or ( MarkerTree :: expression ( MarkerExpression :: String {
644
+ key : MarkerValueString :: SysPlatform ,
645
+ operator : MarkerOperator :: Equal ,
646
+ value : "win32" . to_string ( ) ,
647
+ } ) ) ;
648
+ }
649
+ tag if tag. starts_with ( "macosx" ) => {
650
+ marker. or ( MarkerTree :: expression ( MarkerExpression :: String {
651
+ key : MarkerValueString :: SysPlatform ,
652
+ operator : MarkerOperator :: Equal ,
653
+ value : "darwin" . to_string ( ) ,
654
+ } ) ) ;
655
+ }
656
+ tag if tag. starts_with ( "manylinux" )
657
+ || tag. starts_with ( "musllinux" )
658
+ || tag. starts_with ( "linux" ) =>
659
+ {
660
+ marker. or ( MarkerTree :: expression ( MarkerExpression :: String {
661
+ key : MarkerValueString :: SysPlatform ,
662
+ operator : MarkerOperator :: Equal ,
663
+ value : "linux" . to_string ( ) ,
664
+ } ) ) ;
665
+ }
666
+ _ => { }
667
+ }
668
+ }
669
+ marker
670
+ }
0 commit comments