bioimageio.spec.common
1from pydantic import ValidationError 2 3from ._internal.common_nodes import InvalidDescr 4from ._internal.io import ( 5 BioimageioYamlContent, 6 BioimageioYamlSource, 7 FileDescr, 8 YamlValue, 9) 10from ._internal.io_basics import AbsoluteDirectory, AbsoluteFilePath, FileName, Sha256 11from ._internal.root_url import RootHttpUrl 12from ._internal.types import FileSource, PermissiveFileSource, RelativeFilePath 13from ._internal.url import HttpUrl 14 15__all__ = [ 16 "AbsoluteDirectory", 17 "AbsoluteFilePath", 18 "BioimageioYamlContent", 19 "BioimageioYamlSource", 20 "FileDescr", 21 "FileName", 22 "FileSource", 23 "HttpUrl", 24 "InvalidDescr", 25 "PermissiveFileSource", 26 "RelativeFilePath", 27 "RootHttpUrl", 28 "Sha256", 29 "ValidationError", 30 "YamlValue", 31]
768class FileDescr(Node): 769 source: ImportantFileSource 770 """∈📦 file source""" 771 772 sha256: Optional[Sha256] = None 773 """SHA256 checksum of the source file""" 774 775 @model_validator(mode="after") 776 def validate_sha256(self) -> Self: 777 context = validation_context_var.get() 778 if not context.perform_io_checks: 779 return self 780 elif (src_str := str(self.source)) in context.known_files: 781 actual_sha = context.known_files[src_str] 782 else: 783 local_source = download(self.source, sha256=self.sha256).path 784 actual_sha = get_sha256(local_source) 785 context.known_files[str(self.source)] = actual_sha 786 787 if self.sha256 is None: 788 self.sha256 = actual_sha 789 elif self.sha256 != actual_sha: 790 raise ValueError( 791 f"Sha256 mismatch for {self.source}. Expected {self.sha256}, got " 792 + f"{actual_sha}. Update expected `sha256` or point to the matching " 793 + "file." 794 ) 795 796 return self 797 798 def download(self): 799 800 return download(self.source, sha256=self.sha256)
Subpart of a resource description
∈📦 file source
775 @model_validator(mode="after") 776 def validate_sha256(self) -> Self: 777 context = validation_context_var.get() 778 if not context.perform_io_checks: 779 return self 780 elif (src_str := str(self.source)) in context.known_files: 781 actual_sha = context.known_files[src_str] 782 else: 783 local_source = download(self.source, sha256=self.sha256).path 784 actual_sha = get_sha256(local_source) 785 context.known_files[str(self.source)] = actual_sha 786 787 if self.sha256 is None: 788 self.sha256 = actual_sha 789 elif self.sha256 != actual_sha: 790 raise ValueError( 791 f"Sha256 mismatch for {self.source}. Expected {self.sha256}, got " 792 + f"{actual_sha}. Update expected `sha256` or point to the matching " 793 + "file." 794 ) 795 796 return self
118class HttpUrl(RootHttpUrl): 119 root_model: ClassVar[Type[RootModel[Any]]] = RootModel[pydantic.HttpUrl] 120 _exists: Optional[bool] = None 121 122 @model_validator(mode="after") 123 def _validate_url(self): 124 url = self._validated 125 context = validation_context_var.get() 126 if context.perform_io_checks and str(url) not in context.known_files: 127 self._validated = _validate_url(url) 128 self._exists = True 129 130 return self 131 132 def exists(self): 133 """True if URL is available""" 134 if self._exists is None: 135 try: 136 self._validated = _validate_url(self._validated) 137 except Exception as e: 138 logger.info(e) 139 self._exists = False 140 else: 141 self._exists = True 142 143 return self._exists
A 'URL folder', possibly an invalid http URL
the pydantic root model to validate the string
132 def exists(self): 133 """True if URL is available""" 134 if self._exists is None: 135 try: 136 self._validated = _validate_url(self._validated) 137 except Exception as e: 138 logger.info(e) 139 self._exists = False 140 else: 141 self._exists = True 142 143 return self._exists
True if URL is available
514class InvalidDescr( 515 ResourceDescrBase, 516 extra="allow", 517 title="An invalid resource description", 518): 519 """A representation of an invalid resource description""" 520 521 type: Any = "unknown" 522 format_version: Any = "unknown" 523 fields_to_set_explicitly: ClassVar[FrozenSet[LiteralString]] = frozenset()
A representation of an invalid resource description
set set these fields explicitly with their default value if they are not set, such that they are always included even when dumping with 'exlude_unset'
124 def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 125 """We need to both initialize private attributes and call the user-defined model_post_init 126 method. 127 """ 128 init_private_attributes(self, context) 129 original_model_post_init(self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
186class RelativeFilePath( 187 RelativePathBase[Union[AbsoluteFilePath, HttpUrl, ZipPath]], frozen=True 188): 189 """A path relative to the `rdf.yaml` file (also if the RDF source is a URL).""" 190 191 def model_post_init(self, __context: Any) -> None: 192 """add validation @private""" 193 if not self.root.parts: # an empty path can only be a directory 194 raise ValueError(f"{self.root} is not a valid file path.") 195 196 super().model_post_init(__context) 197 198 def get_absolute( 199 self, root: "RootHttpUrl | Path | AnyUrl | ZipFile" 200 ) -> "AbsoluteFilePath | HttpUrl | ZipPath": 201 absolute = self._get_absolute_impl(root) 202 if ( 203 isinstance(absolute, Path) 204 and (context := validation_context_var.get()).perform_io_checks 205 and str(self.root) not in context.known_files 206 and not absolute.is_file() 207 ): 208 raise ValueError(f"{absolute} does not point to an existing file") 209 210 return absolute
A path relative to the rdf.yaml
file (also if the RDF source is a URL).
124 def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 125 """We need to both initialize private attributes and call the user-defined model_post_init 126 method. 127 """ 128 init_private_attributes(self, context) 129 original_model_post_init(self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
198 def get_absolute( 199 self, root: "RootHttpUrl | Path | AnyUrl | ZipFile" 200 ) -> "AbsoluteFilePath | HttpUrl | ZipPath": 201 absolute = self._get_absolute_impl(root) 202 if ( 203 isinstance(absolute, Path) 204 and (context := validation_context_var.get()).perform_io_checks 205 and str(self.root) not in context.known_files 206 and not absolute.is_file() 207 ): 208 raise ValueError(f"{absolute} does not point to an existing file") 209 210 return absolute
13class RootHttpUrl(ValidatedString): 14 """A 'URL folder', possibly an invalid http URL""" 15 16 root_model: ClassVar[Type[RootModel[Any]]] = RootModel[pydantic.HttpUrl] 17 _validated: pydantic.HttpUrl 18 19 def absolute(self): 20 """analog to `absolute` method of pathlib.""" 21 return self 22 23 @property 24 def scheme(self) -> str: 25 return self._validated.scheme 26 27 @property 28 def host(self) -> Optional[str]: 29 return self._validated.host 30 31 @property 32 def path(self) -> Optional[str]: 33 return self._validated.path 34 35 @property 36 def parent(self) -> RootHttpUrl: 37 parsed = urlsplit(str(self)) 38 path = list(parsed.path.split("/")) 39 if ( 40 parsed.netloc == "zenodo.org" 41 and parsed.path.startswith("/api/records/") 42 and parsed.path.endswith("/content") 43 ): 44 path[-2:-1] = [] 45 else: 46 path = path[:-1] 47 48 return RootHttpUrl( 49 urlunsplit( 50 ( 51 parsed.scheme, 52 parsed.netloc, 53 "/".join(path), 54 parsed.query, 55 parsed.fragment, 56 ) 57 ) 58 )
A 'URL folder', possibly an invalid http URL
the pydantic root model to validate the string
35 @property 36 def parent(self) -> RootHttpUrl: 37 parsed = urlsplit(str(self)) 38 path = list(parsed.path.split("/")) 39 if ( 40 parsed.netloc == "zenodo.org" 41 and parsed.path.startswith("/api/records/") 42 and parsed.path.endswith("/content") 43 ): 44 path[-2:-1] = [] 45 else: 46 path = path[:-1] 47 48 return RootHttpUrl( 49 urlunsplit( 50 ( 51 parsed.scheme, 52 parsed.netloc, 53 "/".join(path), 54 parsed.query, 55 parsed.fragment, 56 ) 57 ) 58 )
23class Sha256(ValidatedString): 24 """SHA-256 hash value""" 25 26 root_model: ClassVar[Type[RootModel[Any]]] = RootModel[ 27 Annotated[ 28 str, 29 StringConstraints( 30 strip_whitespace=True, to_lower=True, min_length=64, max_length=64 31 ), 32 ] 33 ]
SHA-256 hash value
Inappropriate argument value (of correct type).