@@ -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