Coverage for bioimageio/spec/_description_impl.py: 84%

49 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-27 09:20 +0000

1"""implementation details for building a bioimage.io resource description""" 

2 

3import collections.abc 

4from typing import Any, Callable, List, Literal, Mapping, Optional, Type, TypeVar, Union 

5 

6from ._internal.common_nodes import InvalidDescr, ResourceDescrBase 

7from ._internal.io import BioimageioYamlContentView 

8from ._internal.types import FormatVersionPlaceholder 

9from ._internal.validation_context import ValidationContext, get_validation_context 

10from .summary import ( 

11 ErrorEntry, 

12 ValidationDetail, 

13) 

14 

15ResourceDescrT = TypeVar("ResourceDescrT", bound=ResourceDescrBase) 

16 

17 

18DISCOVER: Literal["discover"] = "discover" 

19"""placeholder for whatever format version an RDF specifies""" 

20 

21 

22def get_rd_class_impl( 

23 typ: Any, 

24 format_version: Any, 

25 descriptions_map: Mapping[ 

26 Optional[str], Mapping[Optional[str], Type[ResourceDescrT]] 

27 ], 

28) -> Type[ResourceDescrT]: 

29 assert None in descriptions_map 

30 assert all(None in version_map for version_map in descriptions_map.values()) 

31 assert all( 

32 fv is None or fv.count(".") == 1 

33 for version_map in descriptions_map.values() 

34 for fv in version_map 

35 ) 

36 if not isinstance(typ, str) or typ not in descriptions_map: 

37 typ = None 

38 

39 format_version = str(format_version) 

40 if (ndots := format_version.count(".")) == 0: 

41 use_format_version = format_version + ".0" 

42 elif ndots == 2: 

43 use_format_version = format_version[: format_version.rfind(".")] 

44 else: 

45 use_format_version = None 

46 

47 descr_versions = descriptions_map[typ] 

48 return descr_versions.get(use_format_version, descr_versions[None]) 

49 

50 

51def build_description_impl( 

52 content: BioimageioYamlContentView, 

53 /, 

54 *, 

55 context: Optional[ValidationContext] = None, 

56 format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, 

57 get_rd_class: Callable[[Any, Any], Type[ResourceDescrT]], 

58) -> Union[ResourceDescrT, InvalidDescr]: 

59 context = context or get_validation_context() 

60 errors: List[ErrorEntry] = [] 

61 if isinstance(content, collections.abc.Mapping): 

62 for minimum in ("type", "format_version"): 

63 if minimum not in content: 

64 errors.append( 

65 ErrorEntry( 

66 loc=(minimum,), msg=f"Missing field '{minimum}'", type="error" 

67 ) 

68 ) 

69 elif not isinstance(content[minimum], str): 

70 errors.append( 

71 ErrorEntry( 

72 loc=(minimum,), 

73 msg=f"Invalid type '{type(content[minimum])}'", 

74 type="error", 

75 ) 

76 ) 

77 else: 

78 errors.append( 

79 ErrorEntry( 

80 loc=(), msg=f"Invalid content of type '{type(content)}'", type="error" 

81 ) 

82 ) 

83 content = {} 

84 

85 if errors: 

86 ret = InvalidDescr(**content) # pyright: ignore[reportArgumentType] 

87 ret.validation_summary.add_detail( 

88 ValidationDetail( 

89 name="extract fields to chose description class", 

90 status="failed", 

91 errors=errors, 

92 context=context.summary, 

93 ) 

94 ) 

95 return ret 

96 

97 typ = content["type"] 

98 rd_class = get_rd_class(typ, content["format_version"]) 

99 rd = rd_class.load(content, context=context) 

100 

101 if str(format_version).lower() not in ( 

102 DISCOVER, 

103 rd_class.implemented_format_version, 

104 ".".join(map(str, rd_class.implemented_format_version_tuple[:2])), 

105 ): 

106 # load with requested format_version 

107 discover_details = rd.validation_summary.details 

108 as_rd_class = get_rd_class(typ, format_version) 

109 rd = as_rd_class.load(content, context=context) 

110 assert rd.validation_summary is not None 

111 rd.validation_summary.details[:0] = discover_details 

112 

113 return rd