1
+ use std:: borrow:: Cow ;
1
2
use std:: fmt:: { Display , Formatter } ;
2
3
3
- use crate :: resolver:: { MetadataUnavailable , VersionFork } ;
4
+ use reqwest:: StatusCode ;
5
+
4
6
use uv_distribution_types:: IncompatibleDist ;
5
7
use uv_pep440:: { Version , VersionSpecifiers } ;
6
8
use uv_platform_tags:: { AbiTag , Tags } ;
7
9
10
+ use crate :: resolver:: { MetadataUnavailable , VersionFork } ;
11
+
8
12
/// The reason why a package or a version cannot be used.
9
13
#[ derive( Debug , Clone , Eq , PartialEq ) ]
10
14
pub ( crate ) enum UnavailableReason {
@@ -43,41 +47,46 @@ pub(crate) enum UnavailableVersion {
43
47
/// The source distribution has a `requires-python` requirement that is not met by the installed
44
48
/// Python version (and static metadata is not available).
45
49
RequiresPython ( VersionSpecifiers ) ,
50
+ /// The network request failed with the given status code.
51
+ Network ( StatusCode ) ,
46
52
}
47
53
48
54
impl UnavailableVersion {
49
55
pub ( crate ) fn message ( & self ) -> String {
50
56
match self {
51
- UnavailableVersion :: IncompatibleDist ( invalid_dist) => format ! ( "{invalid_dist}" ) ,
52
- UnavailableVersion :: InvalidMetadata => "invalid metadata" . into ( ) ,
53
- UnavailableVersion :: InconsistentMetadata => "inconsistent metadata" . into ( ) ,
54
- UnavailableVersion :: InvalidStructure => "an invalid package format" . into ( ) ,
55
- UnavailableVersion :: Offline => "to be downloaded from a registry" . into ( ) ,
56
- UnavailableVersion :: RequiresPython ( requires_python) => {
57
+ Self :: IncompatibleDist ( invalid_dist) => format ! ( "{invalid_dist}" ) ,
58
+ Self :: InvalidMetadata => "invalid metadata" . into ( ) ,
59
+ Self :: InconsistentMetadata => "inconsistent metadata" . into ( ) ,
60
+ Self :: InvalidStructure => "an invalid package format" . into ( ) ,
61
+ Self :: Offline => "to be downloaded from a registry" . into ( ) ,
62
+ Self :: RequiresPython ( requires_python) => {
57
63
format ! ( "Python {requires_python}" )
58
64
}
65
+ Self :: Network ( status) => status. to_string ( ) ,
59
66
}
60
67
}
61
68
62
69
pub ( crate ) fn singular_message ( & self ) -> String {
63
70
match self {
64
- UnavailableVersion :: IncompatibleDist ( invalid_dist) => invalid_dist. singular_message ( ) ,
65
- UnavailableVersion :: InvalidMetadata => format ! ( "has {self}" ) ,
66
- UnavailableVersion :: InconsistentMetadata => format ! ( "has {self}" ) ,
67
- UnavailableVersion :: InvalidStructure => format ! ( "has {self}" ) ,
68
- UnavailableVersion :: Offline => format ! ( "needs {self}" ) ,
69
- UnavailableVersion :: RequiresPython ( ..) => format ! ( "requires {self}" ) ,
71
+ Self :: IncompatibleDist ( invalid_dist) => invalid_dist. singular_message ( ) ,
72
+ Self :: InvalidMetadata => format ! ( "has {self}" ) ,
73
+ Self :: InconsistentMetadata => format ! ( "has {self}" ) ,
74
+ Self :: InvalidStructure => format ! ( "has {self}" ) ,
75
+ Self :: Offline => format ! ( "needs {self}" ) ,
76
+ Self :: RequiresPython ( ..) => format ! ( "requires {self}" ) ,
77
+ Self :: Network ( ..) => format ! ( "could not be fetched from the network (`{self}`)" ) ,
70
78
}
71
79
}
72
80
73
81
pub ( crate ) fn plural_message ( & self ) -> String {
74
82
match self {
75
- UnavailableVersion :: IncompatibleDist ( invalid_dist) => invalid_dist. plural_message ( ) ,
76
- UnavailableVersion :: InvalidMetadata => format ! ( "have {self}" ) ,
77
- UnavailableVersion :: InconsistentMetadata => format ! ( "have {self}" ) ,
78
- UnavailableVersion :: InvalidStructure => format ! ( "have {self}" ) ,
79
- UnavailableVersion :: Offline => format ! ( "need {self}" ) ,
80
- UnavailableVersion :: RequiresPython ( ..) => format ! ( "require {self}" ) ,
83
+ Self :: IncompatibleDist ( invalid_dist) => invalid_dist. plural_message ( ) ,
84
+ Self :: InvalidMetadata => format ! ( "have {self}" ) ,
85
+ Self :: InconsistentMetadata => format ! ( "have {self}" ) ,
86
+ Self :: InvalidStructure => format ! ( "have {self}" ) ,
87
+ Self :: Offline => format ! ( "need {self}" ) ,
88
+ Self :: RequiresPython ( ..) => format ! ( "require {self}" ) ,
89
+ Self :: Network ( ..) => format ! ( "could not be fetched from the network (`{self}`)" ) ,
81
90
}
82
91
}
83
92
@@ -87,14 +96,15 @@ impl UnavailableVersion {
87
96
requires_python : Option < AbiTag > ,
88
97
) -> Option < String > {
89
98
match self {
90
- UnavailableVersion :: IncompatibleDist ( invalid_dist) => {
99
+ Self :: IncompatibleDist ( invalid_dist) => {
91
100
invalid_dist. context_message ( tags, requires_python)
92
101
}
93
- UnavailableVersion :: InvalidMetadata => None ,
94
- UnavailableVersion :: InconsistentMetadata => None ,
95
- UnavailableVersion :: InvalidStructure => None ,
96
- UnavailableVersion :: Offline => None ,
97
- UnavailableVersion :: RequiresPython ( ..) => None ,
102
+ Self :: InvalidMetadata => None ,
103
+ Self :: InconsistentMetadata => None ,
104
+ Self :: InvalidStructure => None ,
105
+ Self :: Offline => None ,
106
+ Self :: RequiresPython ( ..) => None ,
107
+ Self :: Network ( ..) => None ,
98
108
}
99
109
}
100
110
}
@@ -108,15 +118,14 @@ impl Display for UnavailableVersion {
108
118
impl From < & MetadataUnavailable > for UnavailableVersion {
109
119
fn from ( reason : & MetadataUnavailable ) -> Self {
110
120
match reason {
111
- MetadataUnavailable :: Offline => UnavailableVersion :: Offline ,
112
- MetadataUnavailable :: InvalidMetadata ( _) => UnavailableVersion :: InvalidMetadata ,
113
- MetadataUnavailable :: InconsistentMetadata ( _) => {
114
- UnavailableVersion :: InconsistentMetadata
115
- }
116
- MetadataUnavailable :: InvalidStructure ( _) => UnavailableVersion :: InvalidStructure ,
121
+ MetadataUnavailable :: Offline => Self :: Offline ,
122
+ MetadataUnavailable :: InvalidMetadata ( _) => Self :: InvalidMetadata ,
123
+ MetadataUnavailable :: InconsistentMetadata ( _) => Self :: InconsistentMetadata ,
124
+ MetadataUnavailable :: InvalidStructure ( _) => Self :: InvalidStructure ,
117
125
MetadataUnavailable :: RequiresPython ( requires_python, _python_version) => {
118
- UnavailableVersion :: RequiresPython ( requires_python. clone ( ) )
126
+ Self :: RequiresPython ( requires_python. clone ( ) )
119
127
}
128
+ MetadataUnavailable :: Network ( status) => Self :: Network ( * status) ,
120
129
}
121
130
}
122
131
}
@@ -134,33 +143,37 @@ pub(crate) enum UnavailablePackage {
134
143
InvalidMetadata ( String ) ,
135
144
/// The package has an invalid structure.
136
145
InvalidStructure ( String ) ,
146
+ /// The network request failed with the given status code.
147
+ Network ( StatusCode ) ,
137
148
}
138
149
139
150
impl UnavailablePackage {
140
- pub ( crate ) fn message ( & self ) -> & ' static str {
151
+ pub ( crate ) fn message ( & self ) -> Cow < ' static , str > {
141
152
match self {
142
- UnavailablePackage :: NoIndex => "not found in the provided package locations" ,
143
- UnavailablePackage :: Offline => "not found in the cache" ,
144
- UnavailablePackage :: NotFound => "not found in the package registry" ,
145
- UnavailablePackage :: InvalidMetadata ( _) => "invalid metadata" ,
146
- UnavailablePackage :: InvalidStructure ( _) => "an invalid package format" ,
153
+ Self :: NoIndex => Cow :: Borrowed ( "not found in the provided package locations" ) ,
154
+ Self :: Offline => Cow :: Borrowed ( "not found in the cache" ) ,
155
+ Self :: NotFound => Cow :: Borrowed ( "not found in the package registry" ) ,
156
+ Self :: InvalidMetadata ( _) => Cow :: Borrowed ( "invalid metadata" ) ,
157
+ Self :: InvalidStructure ( _) => Cow :: Borrowed ( "an invalid package format" ) ,
158
+ Self :: Network ( status) => Cow :: Owned ( status. to_string ( ) ) ,
147
159
}
148
160
}
149
161
150
162
pub ( crate ) fn singular_message ( & self ) -> String {
151
163
match self {
152
- UnavailablePackage :: NoIndex => format ! ( "was {self}" ) ,
153
- UnavailablePackage :: Offline => format ! ( "was {self}" ) ,
154
- UnavailablePackage :: NotFound => format ! ( "was {self}" ) ,
155
- UnavailablePackage :: InvalidMetadata ( _) => format ! ( "has {self}" ) ,
156
- UnavailablePackage :: InvalidStructure ( _) => format ! ( "has {self}" ) ,
164
+ Self :: NoIndex => format ! ( "was {self}" ) ,
165
+ Self :: Offline => format ! ( "was {self}" ) ,
166
+ Self :: NotFound => format ! ( "was {self}" ) ,
167
+ Self :: InvalidMetadata ( _) => format ! ( "has {self}" ) ,
168
+ Self :: InvalidStructure ( _) => format ! ( "has {self}" ) ,
169
+ Self :: Network ( _) => format ! ( "could not be fetched from the network (`{self}`)" ) ,
157
170
}
158
171
}
159
172
}
160
173
161
174
impl Display for UnavailablePackage {
162
175
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
163
- f. write_str ( self . message ( ) )
176
+ f. write_str ( self . message ( ) . as_ref ( ) )
164
177
}
165
178
}
166
179
@@ -176,6 +189,7 @@ impl From<&MetadataUnavailable> for UnavailablePackage {
176
189
MetadataUnavailable :: RequiresPython ( ..) => {
177
190
unreachable ! ( "`requires-python` is only known upfront for registry distributions" )
178
191
}
192
+ MetadataUnavailable :: Network ( status) => Self :: Network ( * status) ,
179
193
}
180
194
}
181
195
}
0 commit comments