@@ -1425,4 +1425,100 @@ class BoundedForecastDownloader (Downloader):
classDownloaderWithFallbacks(Downloader):
def__init__(self,name,downloaders):
"""
:param str name: Brief human readable description, for logging
:param downloaders: Downloaders to try, in priority order (most preferred first)
:type downloaders: list of Downloaders
"""
assertlen(downloaders)>1,f"At least two Downloaders should be passed into DownloaderWithFallbacks"
url_base=downloaders[0].url_base
package_env_id=downloaders[0].package_env_id
fordownloaderindownloaders[1:]:
asserturl_base==downloader.url_base,f"All Downloaders must share a common url_base, but both {url_base} and {downloader.url_base} are present"
assertpackage_env_id==downloader.package_env_id,f"All Downloaders must share a common package_env_id, but both {package_env_id} and {downloader.package_env_id} are present"
super().__init__(
name=name,
# While we are a type of Downloader, we don't use any of these;
# instead we hand responsibility off to our downloaders
""" Return FileSets to create a local cache between start and end, inclusive
Like Downloader.get_cache_filesets, but returns FileSets merged from
the individual self.downloaders.
"""
oldest_cache=self.downloaders[0].oldest_cache
fordownloaderinself.downloaders[1:]:
ifdownloader.oldest_cache<timedelta(days=0):
raiseValueError(f"oldest_cache should be positive; it is {downloader.oldest_cache} in {downloader.name}")
assertoldest_cache==downloader.oldest_cache,"All child downloaders to DownloaderWithFallbacks should have a common oldest_cache, but that is not true."
ifendisNone:end=datetime.datetime.now()
ifstartisNone:start=end-oldest_cache
ifstart>end:
raiseValueError(f"start ({start}) should be before end ({end})")
# Ensure we get data for the last one
# (Which is start, as we work backword)
start=self._find_latest_start_time(start)
times_list=self._collect_unique_times(start,end)
fileset_list_list=[]
fortimeintimes_list:
fileset_list=self.get_filesets_for_time(time)
fileset_list_list.append(fileset_list)
#print("fileset_list_list:", fileset_list)
returnfileset_list_list
defis_expected(self,time):
fordownloaderinself.downloaders:
ifdownloader.is_expected(time):
returnTrue
returnFalse
defget_filesets_for_time(self,time):
""" Return list of FileSets suitable for use at time
Like Downloader.get_filesets_for_time, but returns FileSets merged from