@@ -625,20 +625,46 @@ def is_valid_url(url):
625625
626626
627627class IndexDownloader :
628- def __init__ (self , source , index_cls , auth = None , cache = None ):
628+ def __init__ (self , source , index_cls , auth = None , cache = None , disk_cache = None ):
629629 self .index_cls = index_cls
630630 self ._url = source .rstrip ("/" )
631631 if not self ._url .casefold ().endswith (".json" .casefold ()):
632632 self ._url += "/index.json"
633633 self ._auth = auth if auth is not None else {}
634634 self ._cache = cache if cache is not None else {}
635+ self ._disk_cache = Path (disk_cache ) if disk_cache is not None else None
635636 self ._urlopen = urlopen
637+ self ._used_auth = False
638+
639+ def _use_disk_cache (self , url , data = None ):
640+ if not self ._disk_cache :
641+ return None
642+ try :
643+ if extract_url_auth (url ):
644+ return None
645+ except OSError :
646+ return None
647+ from hashlib import sha256
648+ from time import time
649+ path = self ._disk_cache / (sha256 (url .encode ("utf-8" , "unicodeescape" )).hexdigest () + ".cache" )
650+ if data :
651+ path .parent .mkdir (parents = True , exist_ok = True )
652+ path .write_bytes (data )
653+ return
654+ try :
655+ if time () - path .lstat ().st_mtime < 60 :
656+ return path .read_bytes ()
657+ path .unlink ()
658+ return None
659+ except OSError :
660+ return None
636661
637662 def __iter__ (self ):
638663 return self
639664
640665 def on_auth (self , url ):
641666 # TODO: Try looking for parent paths from URL
667+ self ._used_auth = True
642668 try :
643669 return self ._auth [url ]
644670 except LookupError :
@@ -658,14 +684,21 @@ def __next__(self):
658684 except LookupError :
659685 data = None
660686
687+ data = self ._use_disk_cache (url )
688+ if data :
689+ LOGGER .debug ("Fetched from disk cache" )
690+
661691 if not data :
662692 try :
693+ self ._used_auth = False
663694 data = self ._cache [url ] = self ._urlopen (
664695 url ,
665696 "GET" ,
666697 {"Accepts" : "application/json" },
667698 on_auth_request = self .on_auth ,
668699 )
700+ if not self ._used_auth :
701+ self ._use_disk_cache (url , data )
669702 except FileNotFoundError : # includes 404
670703 LOGGER .error ("Unable to find runtimes index at %s" , sanitise_url (url ))
671704 raise
0 commit comments