1
- use std:: borrow:: Cow ;
2
1
use std:: fmt:: { Display , Formatter } ;
3
2
use std:: hash:: Hash ;
4
3
use std:: str:: FromStr ;
@@ -17,7 +16,6 @@ use uv_platform_tags::{
17
16
AbiTag , LanguageTag , ParseAbiTagError , ParseLanguageTagError , ParsePlatformTagError ,
18
17
PlatformTag , TagCompatibility , Tags ,
19
18
} ;
20
- use uv_variants:: VariantTag ;
21
19
22
20
#[ derive(
23
21
Debug ,
@@ -36,7 +34,7 @@ pub struct WheelFilename {
36
34
pub name : PackageName ,
37
35
pub version : Version ,
38
36
tags : WheelTag ,
39
- variant : Option < VariantTag > ,
37
+ variant : Option < String > ,
40
38
}
41
39
42
40
impl FromStr for WheelFilename {
@@ -166,8 +164,8 @@ impl WheelFilename {
166
164
}
167
165
168
166
/// Return the wheel's variant tag, if present.
169
- pub fn variant ( & self ) -> Option < & VariantTag > {
170
- self . variant . as_ref ( )
167
+ pub fn variant ( & self ) -> Option < & str > {
168
+ self . variant . as_deref ( )
171
169
}
172
170
173
171
/// Return the wheel's Python tags.
@@ -218,38 +216,6 @@ impl WheelFilename {
218
216
///
219
217
/// The originating `filename` is used for high-fidelity error messages.
220
218
fn parse ( stem : & str , filename : & str ) -> Result < Self , WheelFilenameError > {
221
- // Extract variant from filenames with the format, e.g., `dummy_project-0.0.1-~36266d4d~-py3-none-any.whl`.
222
- // TODO(charlie): Integrate this into the filename parsing; it's just easier to do it upfront
223
- // for now.
224
- let mut variant: Option < VariantTag > = None ;
225
- let stem = if let Some ( tilde_start) = stem. find ( "-~" ) {
226
- if let Some ( tilde_end) = stem[ tilde_start + 1 ..] . find ( "~-" ) {
227
- // Skip the "-~".
228
- let variant_start = tilde_start + 2 ;
229
- // End before the "~-".
230
- let variant_end = tilde_start + 1 + tilde_end;
231
- // Validate that the variant is exactly 8 bytes.
232
- let variant_str = & stem[ variant_start..variant_end] ;
233
- if variant_str. len ( ) == 8 && variant_str. as_bytes ( ) . iter ( ) . all ( |& b| b. is_ascii ( ) ) {
234
- variant = Some ( VariantTag :: new ( variant_str. to_string ( ) ) ) ;
235
- } else {
236
- return Err ( WheelFilenameError :: InvalidWheelFileName (
237
- filename. to_string ( ) ,
238
- format ! ( "Variant must be exactly 8 ASCII characters, got: '{variant_str}'" ) ,
239
- ) ) ;
240
- }
241
-
242
- // Create a new stem without the variant.
243
- let before_variant = & stem[ ..tilde_start] ;
244
- let after_variant = & stem[ variant_end + 1 ..] ;
245
- Cow :: Owned ( format ! ( "{before_variant}{after_variant}" ) )
246
- } else {
247
- Cow :: Borrowed ( stem)
248
- }
249
- } else {
250
- Cow :: Borrowed ( stem)
251
- } ;
252
-
253
219
// The wheel filename should contain either five or six entries. If six, then the third
254
220
// entry is the build tag. If five, then the third entry is the Python tag.
255
221
// https://www.python.org/dev/peps/pep-0427/#file-name-convention
@@ -283,24 +249,62 @@ impl WheelFilename {
283
249
) ) ;
284
250
} ;
285
251
286
- let ( name, version, build_tag, python_tag, abi_tag, platform_tag, is_small) =
252
+ let ( name, version, build_tag, python_tag, abi_tag, platform_tag, variant , is_small) =
287
253
if let Some ( platform_tag) = splitter. next ( ) {
288
- if splitter. next ( ) . is_some ( ) {
289
- return Err ( WheelFilenameError :: InvalidWheelFileName (
290
- filename. to_string ( ) ,
291
- "Must have 5 or 6 components, but has more" . to_string ( ) ,
292
- ) ) ;
254
+ // Extract variant from filenames with the format, e.g., `ml_project-0.0.1-py3-none-any-cu128.whl`.
255
+ // TODO(charlie): Integrate this into the filename parsing; it's just easier to do it upfront
256
+ // for now.
257
+ // 7 components: We have both a build tag and a variant_tag
258
+ if let Some ( variant_tag) = splitter. next ( ) {
259
+ if splitter. next ( ) . is_some ( ) {
260
+ return Err ( WheelFilenameError :: InvalidWheelFileName (
261
+ filename. to_string ( ) ,
262
+ "Must have 5 to 7 components, but has more" . to_string ( ) ,
263
+ ) ) ;
264
+ }
265
+ (
266
+ & stem[ ..version] ,
267
+ & stem[ version + 1 ..build_tag_or_python_tag] ,
268
+ Some ( & stem[ build_tag_or_python_tag + 1 ..python_tag_or_abi_tag] ) ,
269
+ & stem[ python_tag_or_abi_tag + 1 ..abi_tag_or_platform_tag] ,
270
+ & stem[ abi_tag_or_platform_tag + 1 ..platform_tag] ,
271
+ & stem[ platform_tag + 1 ..variant_tag] ,
272
+ Some ( & stem[ variant_tag + 1 ..] ) ,
273
+ // Always take the slow path if build or variant tag are present.
274
+ false ,
275
+ )
276
+ } else {
277
+ // 6 components: Check whether we have a build tag or variant tag
278
+ if LanguageTag :: from_str (
279
+ & stem[ build_tag_or_python_tag + 1 ..python_tag_or_abi_tag] ,
280
+ )
281
+ . is_ok ( )
282
+ {
283
+ (
284
+ & stem[ ..version] ,
285
+ & stem[ version + 1 ..build_tag_or_python_tag] ,
286
+ Some ( & stem[ build_tag_or_python_tag + 1 ..python_tag_or_abi_tag] ) ,
287
+ & stem[ python_tag_or_abi_tag + 1 ..abi_tag_or_platform_tag] ,
288
+ & stem[ abi_tag_or_platform_tag + 1 ..platform_tag] ,
289
+ & stem[ platform_tag + 1 ..] ,
290
+ None ,
291
+ // Always take the slow path if a build tag is present.
292
+ false ,
293
+ )
294
+ } else {
295
+ (
296
+ & stem[ ..version] ,
297
+ & stem[ version + 1 ..build_tag_or_python_tag] ,
298
+ None ,
299
+ & stem[ build_tag_or_python_tag + 1 ..python_tag_or_abi_tag] ,
300
+ & stem[ python_tag_or_abi_tag + 1 ..abi_tag_or_platform_tag] ,
301
+ & stem[ abi_tag_or_platform_tag + 1 ..platform_tag] ,
302
+ Some ( & stem[ platform_tag + 1 ..] ) ,
303
+ // Always take the slow path if a build tag is present.
304
+ false ,
305
+ )
306
+ }
293
307
}
294
- (
295
- & stem[ ..version] ,
296
- & stem[ version + 1 ..build_tag_or_python_tag] ,
297
- Some ( & stem[ build_tag_or_python_tag + 1 ..python_tag_or_abi_tag] ) ,
298
- & stem[ python_tag_or_abi_tag + 1 ..abi_tag_or_platform_tag] ,
299
- & stem[ abi_tag_or_platform_tag + 1 ..platform_tag] ,
300
- & stem[ platform_tag + 1 ..] ,
301
- // Always take the slow path if a build tag is present.
302
- false ,
303
- )
304
308
} else {
305
309
(
306
310
& stem[ ..version] ,
@@ -309,6 +313,7 @@ impl WheelFilename {
309
313
& stem[ build_tag_or_python_tag + 1 ..python_tag_or_abi_tag] ,
310
314
& stem[ python_tag_or_abi_tag + 1 ..abi_tag_or_platform_tag] ,
311
315
& stem[ abi_tag_or_platform_tag + 1 ..] ,
316
+ None ,
312
317
// Determine whether any of the tag types contain a period, which would indicate
313
318
// that at least one of the tag types includes multiple tags (which in turn
314
319
// necessitates taking the slow path).
@@ -365,7 +370,7 @@ impl WheelFilename {
365
370
name,
366
371
version,
367
372
tags,
368
- variant,
373
+ variant : variant . map ( ToString :: to_string ) ,
369
374
} )
370
375
}
371
376
}
0 commit comments