@@ -79,6 +79,9 @@ def split_hash_name_and_value(cls, url: str) -> Optional["LinkHash"]:
79
79
name , value = match .groups ()
80
80
return cls (name = name , value = value )
81
81
82
+ def as_dict (self ) -> Dict [str , str ]:
83
+ return {self .name : self .value }
84
+
82
85
def as_hashes (self ) -> Hashes :
83
86
"""Return a Hashes instance which checks only for the current hash."""
84
87
return Hashes ({self .name : [self .value ]})
@@ -165,7 +168,6 @@ class Link(KeyBasedCompareMixin):
165
168
"requires_python" ,
166
169
"yanked_reason" ,
167
170
"dist_info_metadata" ,
168
- "link_hash" ,
169
171
"cache_link_parsing" ,
170
172
"egg_fragment" ,
171
173
]
@@ -177,7 +179,6 @@ def __init__(
177
179
requires_python : Optional [str ] = None ,
178
180
yanked_reason : Optional [str ] = None ,
179
181
dist_info_metadata : Optional [str ] = None ,
180
- link_hash : Optional [LinkHash ] = None ,
181
182
cache_link_parsing : bool = True ,
182
183
hashes : Optional [Mapping [str , str ]] = None ,
183
184
) -> None :
@@ -200,16 +201,11 @@ def __init__(
200
201
attribute, if present, in a simple repository HTML link. This may be parsed
201
202
into its own `Link` by `self.metadata_link()`. See PEP 658 for more
202
203
information and the specification.
203
- :param link_hash: a checksum for the content the link points to. If not
204
- provided, this will be extracted from the link URL, if the URL has
205
- any checksum.
206
204
:param cache_link_parsing: A flag that is used elsewhere to determine
207
- whether resources retrieved from this link
208
- should be cached. PyPI index urls should
209
- generally have this set to False, for
210
- example.
205
+ whether resources retrieved from this link should be cached. PyPI
206
+ URLs should generally have this set to False, for example.
211
207
:param hashes: A mapping of hash names to digests to allow us to
212
- determine the validity of a download.
208
+ determine the validity of a download.
213
209
"""
214
210
215
211
# url can be a UNC windows share
@@ -220,13 +216,18 @@ def __init__(
220
216
# Store the url as a private attribute to prevent accidentally
221
217
# trying to set a new value.
222
218
self ._url = url
223
- self ._hashes = hashes if hashes is not None else {}
219
+
220
+ link_hash = LinkHash .split_hash_name_and_value (url )
221
+ hashes_from_link = {} if link_hash is None else link_hash .as_dict ()
222
+ if hashes is None :
223
+ self ._hashes = hashes_from_link
224
+ else :
225
+ self ._hashes = {** hashes , ** hashes_from_link }
224
226
225
227
self .comes_from = comes_from
226
228
self .requires_python = requires_python if requires_python else None
227
229
self .yanked_reason = yanked_reason
228
230
self .dist_info_metadata = dist_info_metadata
229
- self .link_hash = link_hash or LinkHash .split_hash_name_and_value (self ._url )
230
231
231
232
super ().__init__ (key = url , defining_class = Link )
232
233
@@ -401,29 +402,26 @@ def metadata_link(self) -> Optional["Link"]:
401
402
if self .dist_info_metadata is None :
402
403
return None
403
404
metadata_url = f"{ self .url_without_fragment } .metadata"
404
- link_hash : Optional [LinkHash ] = None
405
405
# If data-dist-info-metadata="true" is set, then the metadata file exists,
406
406
# but there is no information about its checksum or anything else.
407
407
if self .dist_info_metadata != "true" :
408
408
link_hash = LinkHash .split_hash_name_and_value (self .dist_info_metadata )
409
- return Link (metadata_url , link_hash = link_hash )
409
+ else :
410
+ link_hash = None
411
+ if link_hash is None :
412
+ return Link (metadata_url )
413
+ return Link (metadata_url , hashes = link_hash .as_dict ())
410
414
411
- def as_hashes (self ) -> Optional [Hashes ]:
412
- if self .link_hash is not None :
413
- return self .link_hash .as_hashes ()
414
- return None
415
+ def as_hashes (self ) -> Hashes :
416
+ return Hashes ({k : [v ] for k , v in self ._hashes .items ()})
415
417
416
418
@property
417
419
def hash (self ) -> Optional [str ]:
418
- if self .link_hash is not None :
419
- return self .link_hash .value
420
- return None
420
+ return next (iter (self ._hashes .values ()), None )
421
421
422
422
@property
423
423
def hash_name (self ) -> Optional [str ]:
424
- if self .link_hash is not None :
425
- return self .link_hash .name
426
- return None
424
+ return next (iter (self ._hashes ), None )
427
425
428
426
@property
429
427
def show_url (self ) -> str :
@@ -452,15 +450,15 @@ def is_yanked(self) -> bool:
452
450
453
451
@property
454
452
def has_hash (self ) -> bool :
455
- return self .link_hash is not None
453
+ return bool ( self ._hashes )
456
454
457
455
def is_hash_allowed (self , hashes : Optional [Hashes ]) -> bool :
458
456
"""
459
457
Return True if the link has a hash and it is allowed by `hashes`.
460
458
"""
461
- if self . link_hash is None :
459
+ if hashes is None :
462
460
return False
463
- return self .link_hash . is_hash_allowed ( hashes )
461
+ return any ( hashes . is_hash_allowed ( k , v ) for k , v in self ._hashes . items () )
464
462
465
463
466
464
class _CleanResult (NamedTuple ):
0 commit comments