1
1
# -*- coding: utf-8 -*-
2
2
#
3
- # Copyright (C) 2012-2013 Vinay Sajip.
3
+ # Copyright (C) 2012-2014 Vinay Sajip.
4
4
# Licensed to the Python Software Foundation under a contributor agreement.
5
5
# See LICENSE.txt and CONTRIBUTORS.txt.
6
6
#
@@ -290,9 +290,9 @@ def _get_digest(self, info):
290
290
291
291
def _update_version_data (self , result , info ):
292
292
"""
293
- Update a result dictionary (the final result from _get_project) with a dictionary for a
294
- specific version, whih typically holds information gleaned from a filename or URL for an
295
- archive for the distribution.
293
+ Update a result dictionary (the final result from _get_project) with a
294
+ dictionary for a specific version, which typically holds information
295
+ gleaned from a filename or URL for an archive for the distribution.
296
296
"""
297
297
name = info .pop ('name' )
298
298
version = info .pop ('version' )
@@ -302,9 +302,12 @@ def _update_version_data(self, result, info):
302
302
else :
303
303
dist = make_dist (name , version , scheme = self .scheme )
304
304
md = dist .metadata
305
- dist .digest = self ._get_digest (info )
305
+ dist .digest = digest = self ._get_digest (info )
306
+ url = info ['url' ]
307
+ result ['digests' ][url ] = digest
306
308
if md .source_url != info ['url' ]:
307
- md .source_url = self .prefer_url (md .source_url , info ['url' ])
309
+ md .source_url = self .prefer_url (md .source_url , url )
310
+ result ['urls' ].setdefault (version , set ()).add (url )
308
311
dist .locator = self
309
312
result [version ] = dist
310
313
@@ -350,9 +353,18 @@ def locate(self, requirement, prereleases=False):
350
353
slist = sorted (slist , key = scheme .key )
351
354
if slist :
352
355
logger .debug ('sorted list: %s' , slist )
353
- result = versions [slist [- 1 ]]
354
- if result and r .extras :
355
- result .extras = r .extras
356
+ version = slist [- 1 ]
357
+ result = versions [version ]
358
+ if result :
359
+ if r .extras :
360
+ result .extras = r .extras
361
+ result .download_urls = versions .get ('urls' , {}).get (version , set ())
362
+ d = {}
363
+ sd = versions .get ('digests' , {})
364
+ for url in result .download_urls :
365
+ if url in sd :
366
+ d [url ] = sd [url ]
367
+ result .digests = d
356
368
self .matcher = None
357
369
return result
358
370
@@ -380,7 +392,7 @@ def get_distribution_names(self):
380
392
return set (self .client .list_packages ())
381
393
382
394
def _get_project (self , name ):
383
- result = {}
395
+ result = {'urls' : {}, 'digests' : {} }
384
396
versions = self .client .package_releases (name , True )
385
397
for v in versions :
386
398
urls = self .client .release_urls (name , v )
@@ -398,12 +410,17 @@ def _get_project(self, name):
398
410
dist .digest = self ._get_digest (info )
399
411
dist .locator = self
400
412
result [v ] = dist
413
+ for info in urls :
414
+ url = info ['url' ]
415
+ digest = self ._get_digest (info )
416
+ result ['urls' ].setdefault (v , set ()).add (url )
417
+ result ['digests' ][url ] = digest
401
418
return result
402
419
403
420
class PyPIJSONLocator (Locator ):
404
421
"""
405
422
This locator uses PyPI's JSON interface. It's very limited in functionality
406
- nad probably not worth using.
423
+ and probably not worth using.
407
424
"""
408
425
def __init__ (self , url , ** kwargs ):
409
426
super (PyPIJSONLocator , self ).__init__ (** kwargs )
@@ -416,7 +433,7 @@ def get_distribution_names(self):
416
433
raise NotImplementedError ('Not available from this locator' )
417
434
418
435
def _get_project (self , name ):
419
- result = {}
436
+ result = {'urls' : {}, 'digests' : {} }
420
437
url = urljoin (self .base_url , '%s/json' % quote (name ))
421
438
try :
422
439
resp = self .opener .open (url )
@@ -437,6 +454,10 @@ def _get_project(self, name):
437
454
dist .digest = self ._get_digest (info )
438
455
dist .locator = self
439
456
result [md .version ] = dist
457
+ for info in urls :
458
+ url = info ['url' ]
459
+ result ['urls' ].setdefault (md .version , set ()).add (url )
460
+ result ['digests' ][url ] = digest
440
461
except Exception as e :
441
462
logger .exception ('JSON fetch failed: %s' , e )
442
463
return result
@@ -567,7 +588,7 @@ def _wait_threads(self):
567
588
self ._threads = []
568
589
569
590
def _get_project (self , name ):
570
- result = {}
591
+ result = {'urls' : {}, 'digests' : {} }
571
592
with self ._gplock :
572
593
self .result = result
573
594
self .project_name = name
@@ -774,7 +795,7 @@ def should_include(self, filename, parent):
774
795
return filename .endswith (self .downloadable_extensions )
775
796
776
797
def _get_project (self , name ):
777
- result = {}
798
+ result = {'urls' : {}, 'digests' : {} }
778
799
for root , dirs , files in os .walk (self .base_dir ):
779
800
for fn in files :
780
801
if self .should_include (fn , root ):
@@ -822,7 +843,7 @@ def get_distribution_names(self):
822
843
raise NotImplementedError ('Not available from this locator' )
823
844
824
845
def _get_project (self , name ):
825
- result = {}
846
+ result = {'urls' : {}, 'digests' : {} }
826
847
data = get_project_data (name )
827
848
if data :
828
849
for info in data .get ('files' , []):
@@ -843,6 +864,7 @@ def _get_project(self, name):
843
864
md .dependencies = info .get ('requirements' , {})
844
865
dist .exports = info .get ('exports' , {})
845
866
result [dist .version ] = dist
867
+ result ['urls' ].setdefault (dist .version , set ()).add (info ['url' ])
846
868
return result
847
869
848
870
class DistPathLocator (Locator ):
@@ -865,7 +887,10 @@ def _get_project(self, name):
865
887
if dist is None :
866
888
result = {}
867
889
else :
868
- result = { dist .version : dist }
890
+ result = {
891
+ dist .version : dist ,
892
+ 'urls' : {dist .version : set ([dist .source_url ])}
893
+ }
869
894
return result
870
895
871
896
@@ -907,7 +932,20 @@ def _get_project(self, name):
907
932
d = locator .get_project (name )
908
933
if d :
909
934
if self .merge :
935
+ files = result .get ('urls' , {})
936
+ digests = result .get ('digests' , {})
937
+ # next line could overwrite result['urls'], result['digests']
910
938
result .update (d )
939
+ df = result .get ('urls' )
940
+ if files and df :
941
+ for k , v in files .items ():
942
+ if k in df :
943
+ df [k ] |= v
944
+ else :
945
+ df [k ] = v
946
+ dd = result .get ('digests' )
947
+ if digests and dd :
948
+ dd .update (digests )
911
949
else :
912
950
# See issue #18. If any dists are found and we're looking
913
951
# for specific constraints, we only return something if
@@ -1071,7 +1109,8 @@ def try_to_replace(self, provider, other, problems):
1071
1109
unmatched .add (s )
1072
1110
if unmatched :
1073
1111
# can't replace other with provider
1074
- problems .add (('cantreplace' , provider , other , unmatched ))
1112
+ problems .add (('cantreplace' , provider , other ,
1113
+ frozenset (unmatched )))
1075
1114
result = False
1076
1115
else :
1077
1116
# can replace other with provider
0 commit comments