44from typing import Any , Callable , List , Literal , Mapping , Optional , Type , TypeVar , Union
55
66from ._internal .common_nodes import InvalidDescr , ResourceDescrBase
7+ from ._internal .field_validation import issue_warning
78from ._internal .io import BioimageioYamlContentView
89from ._internal .types import FormatVersionPlaceholder
910from ._internal .validation_context import ValidationContext , get_validation_context
@@ -23,6 +24,7 @@ def get_rd_class_impl(
2324 typ : Any ,
2425 format_version : Any ,
2526 descriptions_map : Mapping [Optional [str ], Mapping [str , Type [ResourceDescrT ]]],
27+ fallback_to_latest : bool ,
2628) -> Type [ResourceDescrT ]:
2729 """get the resource description class for the given type and format version"""
2830 assert None in descriptions_map
@@ -46,10 +48,20 @@ def get_rd_class_impl(
4648
4749 descr_versions = descriptions_map [typ ]
4850 if use_format_version not in descr_versions :
49- raise ValueError (
50- f"Unsupported format version '{ format_version } ' for type '{ typ } '. "
51- + f"Supported format versions are: { ', ' .join (sorted (fv for fv in descr_versions ))} "
52- )
51+ if fallback_to_latest :
52+ issue_warning (
53+ "Unsupported format version '{value}' for type '{typ}'." ,
54+ value = format_version ,
55+ field = "format_version" ,
56+ log_depth = 3 ,
57+ msg_context = {"typ" : typ },
58+ )
59+ use_format_version = "latest"
60+ else :
61+ raise ValueError (
62+ f"Unsupported format version '{ format_version } ' for type '{ typ } '."
63+ + " Supported format versions are: {', '.join(sorted(fv for fv in descr_versions))}"
64+ )
5365
5466 return descr_versions [use_format_version ]
5567
@@ -60,7 +72,7 @@ def build_description_impl(
6072 * ,
6173 context : Optional [ValidationContext ] = None ,
6274 format_version : Union [FormatVersionPlaceholder , str ] = DISCOVER ,
63- get_rd_class : Callable [[Any , Any ], Type [ResourceDescrT ]],
75+ get_rd_class : Callable [[Any , Any , bool ], Type [ResourceDescrT ]],
6476) -> Union [ResourceDescrT , InvalidDescr ]:
6577 context = context or get_validation_context ()
6678 errors : List [ErrorEntry ] = []
@@ -101,17 +113,19 @@ def build_description_impl(
101113 return ret
102114
103115 typ = content ["type" ]
104- rd_class = get_rd_class (typ , content ["format_version" ])
116+ # check format_version argument before loading as 'discover'
117+ # to throw an exception for an invalid format_version early
118+ if str (format_version ).lower () != DISCOVER :
119+ as_rd_class = get_rd_class (typ , format_version , False )
120+ else :
121+ as_rd_class = None
122+ # always load with discovered format_version first
123+ rd_class = get_rd_class (typ , content ["format_version" ], True )
105124 rd = rd_class .load (content , context = context )
106125
107- if str (format_version ).lower () not in (
108- DISCOVER ,
109- rd_class .implemented_format_version ,
110- "." .join (map (str , rd_class .implemented_format_version_tuple [:2 ])),
111- ):
126+ if as_rd_class is not None and as_rd_class is not rd_class :
112127 # load with requested format_version
113128 discover_details = rd .validation_summary .details
114- as_rd_class = get_rd_class (typ , format_version )
115129 rd = as_rd_class .load (content , context = context )
116130 assert rd .validation_summary is not None
117131 rd .validation_summary .details [:0 ] = discover_details
0 commit comments