bioimageio.spec.generic.v0_3

  1from __future__ import annotations
  2
  3import string
  4from functools import partial
  5from typing import (
  6    TYPE_CHECKING,
  7    Any,
  8    ClassVar,
  9    Dict,
 10    List,
 11    Literal,
 12    Optional,
 13    Sequence,
 14    Type,
 15    TypeVar,
 16    Union,
 17)
 18
 19import annotated_types
 20from annotated_types import Len, LowerCase, MaxLen, MinLen
 21from pydantic import Field, RootModel, ValidationInfo, field_validator, model_validator
 22from typing_extensions import Annotated
 23
 24from .._internal.common_nodes import Node, ResourceDescrBase
 25from .._internal.constants import TAG_CATEGORIES
 26from .._internal.field_validation import validate_gh_user
 27from .._internal.field_warning import as_warning, warn
 28from .._internal.io import (
 29    BioimageioYamlContent,
 30    FileDescr,
 31    V_suffix,
 32    include_in_package_serializer,
 33    is_yaml_value,
 34    validate_suffix,
 35)
 36from .._internal.io_basics import AbsoluteFilePath, Sha256
 37from .._internal.license_id import DeprecatedLicenseId, LicenseId
 38from .._internal.node_converter import Converter
 39from .._internal.types import ImportantFileSource, NotEmpty, RelativeFilePath
 40from .._internal.url import HttpUrl
 41from .._internal.validated_string import ValidatedString
 42from .._internal.validator_annotations import (
 43    AfterValidator,
 44    Predicate,
 45    RestrictCharacters,
 46)
 47from .._internal.version_type import Version
 48from .._internal.warning_levels import ALERT, INFO
 49from ._v0_3_converter import convert_from_older_format
 50from .v0_2 import Author as _Author_v0_2
 51from .v0_2 import BadgeDescr, CoverImageSource, Doi, OrcidId, Uploader
 52from .v0_2 import Maintainer as _Maintainer_v0_2
 53
 54__all__ = [
 55    "Author",
 56    "BadgeDescr",
 57    "CiteEntry",
 58    "DeprecatedLicenseId",
 59    "Doi",
 60    "FileDescr",
 61    "GenericDescr",
 62    "HttpUrl",
 63    "KNOWN_SPECIFIC_RESOURCE_TYPES",
 64    "LicenseId",
 65    "LinkedResource",
 66    "Maintainer",
 67    "OrcidId",
 68    "RelativeFilePath",
 69    "ResourceId",
 70    "Sha256",
 71    "Uploader",
 72    "VALID_COVER_IMAGE_EXTENSIONS",
 73    "Version",
 74]
 75
 76KNOWN_SPECIFIC_RESOURCE_TYPES = (
 77    "application",
 78    "collection",
 79    "dataset",
 80    "model",
 81    "notebook",
 82)
 83VALID_COVER_IMAGE_EXTENSIONS = (
 84    ".gif",
 85    ".jpeg",
 86    ".jpg",
 87    ".png",
 88    ".svg",
 89)
 90
 91
 92class ResourceId(ValidatedString):
 93    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
 94        Annotated[
 95            NotEmpty[str],
 96            RestrictCharacters(string.ascii_lowercase + string.digits + "_-/."),
 97            annotated_types.Predicate(
 98                lambda s: not (s.startswith("/") or s.endswith("/"))
 99            ),
100        ]
101    ]
102
103
104def _validate_md_suffix(value: V_suffix) -> V_suffix:
105    return validate_suffix(value, suffix=".md", case_sensitive=True)
106
107
108DocumentationSource = Annotated[
109    Union[AbsoluteFilePath, RelativeFilePath, HttpUrl],
110    Field(union_mode="left_to_right"),
111    AfterValidator(_validate_md_suffix),
112    include_in_package_serializer,
113]
114
115
116def _has_no_slash(s: str) -> bool:
117    return "/" not in s and "\\" not in s
118
119
120class Author(_Author_v0_2):
121    name: Annotated[str, Predicate(_has_no_slash)]
122    github_user: Optional[str] = None
123
124    @field_validator("github_user", mode="after")
125    def _validate_gh_user(cls, value: Optional[str]):
126        if value is None:
127            return None
128        else:
129            return validate_gh_user(value)
130
131
132class _AuthorConv(Converter[_Author_v0_2, Author]):
133    def _convert(
134        self, src: _Author_v0_2, tgt: "type[Author] | type[dict[str, Any]]"
135    ) -> "Author | dict[str, Any]":
136        return tgt(
137            name=src.name,
138            github_user=src.github_user,
139            affiliation=src.affiliation,
140            email=src.email,
141            orcid=src.orcid,
142        )
143
144
145_author_conv = _AuthorConv(_Author_v0_2, Author)
146
147
148class Maintainer(_Maintainer_v0_2):
149    name: Optional[Annotated[str, Predicate(_has_no_slash)]] = None
150    github_user: str
151
152    @field_validator("github_user", mode="after")
153    def validate_gh_user(cls, value: str):
154        return validate_gh_user(value)
155
156
157class _MaintainerConv(Converter[_Maintainer_v0_2, Maintainer]):
158    def _convert(
159        self, src: _Maintainer_v0_2, tgt: "type[Maintainer | dict[str, Any]]"
160    ) -> "Maintainer | dict[str, Any]":
161        return tgt(
162            name=src.name,
163            github_user=src.github_user,
164            affiliation=src.affiliation,
165            email=src.email,
166            orcid=src.orcid,
167        )
168
169
170_maintainer_conv = _MaintainerConv(_Maintainer_v0_2, Maintainer)
171
172
173class CiteEntry(Node):
174    """A citation that should be referenced in work using this resource."""
175
176    text: str
177    """free text description"""
178
179    doi: Optional[Doi] = None
180    """A digital object identifier (DOI) is the prefered citation reference.
181    See https://www.doi.org/ for details.
182    Note:
183        Either **doi** or **url** have to be specified.
184    """
185
186    url: Optional[HttpUrl] = None
187    """URL to cite (preferably specify a **doi** instead/also).
188    Note:
189        Either **doi** or **url** have to be specified.
190    """
191
192    @model_validator(mode="after")
193    def _check_doi_or_url(self):
194        if not self.doi and not self.url:
195            raise ValueError("Either 'doi' or 'url' is required")
196
197        return self
198
199
200class LinkedResourceBase(Node):
201
202    @model_validator(mode="before")
203    def _remove_version_number(  # pyright: ignore[reportUnknownParameterType]
204        cls, value: Union[Any, Dict[Any, Any]]
205    ):
206        if isinstance(value, dict):
207            vn: Any = value.pop("version_number", None)
208            if vn is not None and value.get("version") is None:
209                value["version"] = vn
210
211        return value  # pyright: ignore[reportUnknownVariableType]
212
213    version: Optional[Version] = None
214    """The version of the linked resource following SemVer 2.0."""
215
216
217class LinkedResource(LinkedResourceBase):
218    """Reference to a bioimage.io resource"""
219
220    id: ResourceId
221    """A valid resource `id` from the official bioimage.io collection."""
222
223
224class BioimageioConfig(Node, extra="allow"):
225    """bioimage.io internal metadata."""
226
227
228class Config(Node, extra="allow"):
229    """A place to store additional metadata (often tool specific).
230
231    Such additional metadata is typically set programmatically by the respective tool
232    or by people with specific insights into the tool.
233    If you want to store additional metadata that does not match any of the other
234    fields, think of a key unlikely to collide with anyone elses use-case/tool and save
235    it here.
236
237    Please consider creating [an issue in the bioimageio.spec repository](https://github.com/bioimage-io/spec-bioimage-io/issues/new?template=Blank+issue)
238    if you are not sure if an existing field could cover your use case
239    or if you think such a field should exist.
240    """
241
242    bioimageio: BioimageioConfig = Field(default_factory=BioimageioConfig)
243    """bioimage.io internal metadata."""
244
245    @model_validator(mode="after")
246    def _validate_extra_fields(self):
247        if self.model_extra:
248            for k, v in self.model_extra.items():
249                if not isinstance(v, Node) and not is_yaml_value(v):
250                    raise ValueError(
251                        f"config.{k} is not a valid YAML value or `Node` instance"
252                    )
253
254        return self
255
256
257class GenericModelDescrBase(ResourceDescrBase):
258    """Base for all resource descriptions including of model descriptions"""
259
260    name: Annotated[
261        Annotated[
262            str, RestrictCharacters(string.ascii_letters + string.digits + "_+- ()")
263        ],
264        MinLen(5),
265        MaxLen(128),
266        warn(MaxLen(64), "Name longer than 64 characters.", INFO),
267    ]
268    name: Annotated[NotEmpty[str], MaxLen(128)]
269    """A human-friendly name of the resource description.
270    May only contains letters, digits, underscore, minus, parentheses and spaces."""
271
272    description: Annotated[
273        str, MaxLen(1024), warn(MaxLen(512), "Description longer than 512 characters.")
274    ]
275    """A string containing a brief description."""
276
277    covers: Annotated[
278        List[CoverImageSource],
279        Field(
280            examples=[],
281            description=(
282                "Cover images. Please use an image smaller than 500KB and an aspect"
283                " ratio width to height of 2:1 or 1:1.\nThe supported image formats"
284                f" are: {VALID_COVER_IMAGE_EXTENSIONS}"
285            ),
286        ),
287    ] = Field(default_factory=list)
288    """∈📦 Cover images."""
289
290    id_emoji: Optional[
291        Annotated[str, Len(min_length=1, max_length=2), Field(examples=["🦈", "🦥"])]
292    ] = None
293    """UTF-8 emoji for display alongside the `id`."""
294
295    authors: NotEmpty[List[Author]]
296    """The authors are the creators of this resource description and the primary points of contact."""
297
298    attachments: List[FileDescr] = Field(default_factory=list)
299    """file attachments"""
300
301    cite: NotEmpty[List[CiteEntry]]
302    """citations"""
303
304    license: Annotated[
305        Annotated[
306            Union[LicenseId, DeprecatedLicenseId], Field(union_mode="left_to_right")
307        ],
308        warn(
309            LicenseId,
310            "{value} is deprecated, see https://spdx.org/licenses/{value}.html",
311        ),
312        Field(examples=["CC0-1.0", "MIT", "BSD-2-Clause"]),
313    ]
314    """A [SPDX license identifier](https://spdx.org/licenses/).
315    We do not support custom license beyond the SPDX license list, if you need that please
316    [open a GitHub issue](https://github.com/bioimage-io/spec-bioimage-io/issues/new/choose)
317    to discuss your intentions with the community."""
318
319    git_repo: Annotated[
320        Optional[HttpUrl],
321        Field(
322            examples=[
323                "https://github.com/bioimage-io/spec-bioimage-io/tree/main/example_descriptions/models/unet2d_nuclei_broad"
324            ],
325        ),
326    ] = None
327    """A URL to the Git repository where the resource is being developed."""
328
329    icon: Union[
330        Annotated[str, Len(min_length=1, max_length=2)], ImportantFileSource, None
331    ] = None
332    """An icon for illustration, e.g. on bioimage.io"""
333
334    links: Annotated[
335        List[str],
336        Field(
337            examples=[
338                (
339                    "ilastik/ilastik",
340                    "deepimagej/deepimagej",
341                    "zero/notebook_u-net_3d_zerocostdl4mic",
342                )
343            ],
344        ),
345    ] = Field(default_factory=list)
346    """IDs of other bioimage.io resources"""
347
348    uploader: Optional[Uploader] = None
349    """The person who uploaded the model (e.g. to bioimage.io)"""
350
351    maintainers: List[Maintainer] = Field(default_factory=list)
352    """Maintainers of this resource.
353    If not specified, `authors` are maintainers and at least some of them has to specify their `github_user` name"""
354
355    @partial(as_warning, severity=ALERT)
356    @field_validator("maintainers", mode="after")
357    @classmethod
358    def check_maintainers_exist(
359        cls, maintainers: List[Maintainer], info: ValidationInfo
360    ) -> List[Maintainer]:
361        if not maintainers and "authors" in info.data:
362            authors: List[Author] = info.data["authors"]
363            if all(a.github_user is None for a in authors):
364                raise ValueError(
365                    "Missing `maintainers` or any author in `authors` with a specified"
366                    + " `github_user` name."
367                )
368
369        return maintainers
370
371    tags: Annotated[
372        List[str],
373        Field(examples=[("unet2d", "pytorch", "nucleus", "segmentation", "dsb2018")]),
374    ] = Field(default_factory=list)
375    """Associated tags"""
376
377    @as_warning
378    @field_validator("tags")
379    @classmethod
380    def warn_about_tag_categories(
381        cls, value: List[str], info: ValidationInfo
382    ) -> List[str]:
383        categories = TAG_CATEGORIES.get(info.data["type"], {})
384        missing_categories: List[Dict[str, Sequence[str]]] = []
385        for cat, entries in categories.items():
386            if not any(e in value for e in entries):
387                missing_categories.append({cat: entries})
388
389        if missing_categories:
390            raise ValueError(
391                f"Missing tags from bioimage.io categories: {missing_categories}"
392            )
393
394        return value
395
396    version: Optional[Version] = None
397    """The version of the resource following SemVer 2.0."""
398
399    @model_validator(mode="before")
400    def _remove_version_number(  # pyright: ignore[reportUnknownParameterType]
401        cls, value: Union[Any, Dict[Any, Any]]
402    ):
403        if isinstance(value, dict):
404            vn: Any = value.pop("version_number", None)
405            if vn is not None and value.get("version") is None:
406                value["version"] = vn
407
408        return value  # pyright: ignore[reportUnknownVariableType]
409
410
411class GenericDescrBase(GenericModelDescrBase):
412    """Base for all resource descriptions except for the model descriptions"""
413
414    implemented_format_version: ClassVar[Literal["0.3.0"]] = "0.3.0"
415    if TYPE_CHECKING:
416        format_version: Literal["0.3.0"] = "0.3.0"
417    else:
418        format_version: Literal["0.3.0"]
419        """The **format** version of this resource specification"""
420
421    @model_validator(mode="before")
422    @classmethod
423    def _convert_from_older_format(
424        cls, data: BioimageioYamlContent, /
425    ) -> BioimageioYamlContent:
426        cls.convert_from_old_format_wo_validation(data)
427        return data
428
429    @classmethod
430    def convert_from_old_format_wo_validation(cls, data: BioimageioYamlContent) -> None:
431        """Convert metadata following an older format version to this classes' format
432        without validating the result.
433        """
434        convert_from_older_format(data)
435
436    documentation: Annotated[
437        Optional[DocumentationSource],
438        Field(
439            examples=[
440                "https://raw.githubusercontent.com/bioimage-io/spec-bioimage-io/main/example_descriptions/models/unet2d_nuclei_broad/README.md",
441                "README.md",
442            ],
443        ),
444    ] = None
445    """∈📦 URL or relative path to a markdown file encoded in UTF-8 with additional documentation.
446    The recommended documentation file name is `README.md`. An `.md` suffix is mandatory."""
447
448    badges: List[BadgeDescr] = Field(default_factory=list)
449    """badges associated with this resource"""
450
451    config: Config = Field(default_factory=Config)
452    """A field for custom configuration that can contain any keys not present in the RDF spec.
453    This means you should not store, for example, a GitHub repo URL in `config` since there is a `git_repo` field.
454    Keys in `config` may be very specific to a tool or consumer software. To avoid conflicting definitions,
455    it is recommended to wrap added configuration into a sub-field named with the specific domain or tool name,
456    for example:
457    ```yaml
458    config:
459        giraffe_neckometer:  # here is the domain name
460            length: 3837283
461            address:
462                home: zoo
463        imagej:              # config specific to ImageJ
464            macro_dir: path/to/macro/file
465    ```
466    If possible, please use [`snake_case`](https://en.wikipedia.org/wiki/Snake_case) for keys in `config`.
467    You may want to list linked files additionally under `attachments` to include them when packaging a resource.
468    (Packaging a resource means downloading/copying important linked files and creating a ZIP archive that contains
469    an altered rdf.yaml file with local references to the downloaded files.)"""
470
471
472ResourceDescrType = TypeVar("ResourceDescrType", bound=GenericDescrBase)
473
474
475class GenericDescr(GenericDescrBase, extra="ignore"):
476    """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).
477
478    An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook.
479    Note that those resources are described with a type-specific RDF.
480    Use this generic resource description, if none of the known specific types matches your resource.
481    """
482
483    type: Annotated[str, LowerCase] = Field("generic", frozen=True)
484    """The resource type assigns a broad category to the resource."""
485
486    id: Optional[
487        Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])]
488    ] = None
489    """bioimage.io-wide unique resource identifier
490    assigned by bioimage.io; version **un**specific."""
491
492    parent: Optional[ResourceId] = None
493    """The description from which this one is derived"""
494
495    source: Optional[HttpUrl] = None
496    """The primary source of the resource"""
497
498    @field_validator("type", mode="after")
499    @classmethod
500    def check_specific_types(cls, value: str) -> str:
501        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
502            raise ValueError(
503                f"Use the {value} description instead of this generic description for"
504                + f" your '{value}' resource."
505            )
506
507        return value
class Author(bioimageio.spec.generic.v0_2.Author):
121class Author(_Author_v0_2):
122    name: Annotated[str, Predicate(_has_no_slash)]
123    github_user: Optional[str] = None
124
125    @field_validator("github_user", mode="after")
126    def _validate_gh_user(cls, value: Optional[str]):
127        if value is None:
128            return None
129        else:
130            return validate_gh_user(value)
name: Annotated[str, Predicate(func=<function _has_no_slash at 0x7f26001e9e40>)]
github_user: Optional[str]
class BadgeDescr(bioimageio.spec._internal.node.Node):
142class BadgeDescr(Node):
143    """A custom badge"""
144
145    label: Annotated[str, Field(examples=["Open in Colab"])]
146    """badge label to display on hover"""
147
148    icon: Annotated[
149        Optional[InPackageIfLocalFileSource],
150        Field(examples=["https://colab.research.google.com/assets/colab-badge.svg"]),
151    ] = None
152    """badge icon"""
153
154    url: Annotated[
155        HttpUrl,
156        Field(
157            examples=[
158                "https://colab.research.google.com/github/HenriquesLab/ZeroCostDL4Mic/blob/master/Colab_notebooks/U-net_2D_ZeroCostDL4Mic.ipynb"
159            ]
160        ),
161    ]
162    """target URL"""

A custom badge

label: Annotated[str, FieldInfo(annotation=NoneType, required=True, examples=['Open in Colab'])]

badge label to display on hover

icon: Annotated[Union[Annotated[Union[Annotated[pathlib.Path, PathType(path_type='file'), FieldInfo(annotation=NoneType, required=True, title='FilePath')], RelativeFilePath], AfterValidator(func=<function wo_special_file_name at 0x7f2602536ca0>), PlainSerializer(func=<function _package at 0x7f2602535e40>, return_type=PydanticUndefined, when_used='unless-none')], HttpUrl, Annotated[pydantic_core._pydantic_core.Url, UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=None, default_host=None, default_port=None, default_path=None)], NoneType], FieldInfo(annotation=NoneType, required=True, examples=['https://colab.research.google.com/assets/colab-badge.svg'])]

badge icon

url: Annotated[HttpUrl, FieldInfo(annotation=NoneType, required=True, examples=['https://colab.research.google.com/github/HenriquesLab/ZeroCostDL4Mic/blob/master/Colab_notebooks/U-net_2D_ZeroCostDL4Mic.ipynb'])]

target URL

class CiteEntry(bioimageio.spec._internal.node.Node):
174class CiteEntry(Node):
175    """A citation that should be referenced in work using this resource."""
176
177    text: str
178    """free text description"""
179
180    doi: Optional[Doi] = None
181    """A digital object identifier (DOI) is the prefered citation reference.
182    See https://www.doi.org/ for details.
183    Note:
184        Either **doi** or **url** have to be specified.
185    """
186
187    url: Optional[HttpUrl] = None
188    """URL to cite (preferably specify a **doi** instead/also).
189    Note:
190        Either **doi** or **url** have to be specified.
191    """
192
193    @model_validator(mode="after")
194    def _check_doi_or_url(self):
195        if not self.doi and not self.url:
196            raise ValueError("Either 'doi' or 'url' is required")
197
198        return self

A citation that should be referenced in work using this resource.

text: str

free text description

doi: Optional[Doi]

A digital object identifier (DOI) is the prefered citation reference. See https://www.doi.org/ for details.

Note:

Either doi or url have to be specified.

url: Optional[HttpUrl]

URL to cite (preferably specify a doi instead/also).

Note:

Either doi or url have to be specified.

class DeprecatedLicenseId(bioimageio.spec._internal.validated_string.ValidatedString):
24class DeprecatedLicenseId(ValidatedString):
25    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[DeprecatedLicenseIdLiteral]

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

root_model: ClassVar[Type[pydantic.root_model.RootModel[Any]]] = <class 'pydantic.root_model.RootModel[Literal['AGPL-1.0', 'AGPL-3.0', 'BSD-2-Clause-FreeBSD', 'BSD-2-Clause-NetBSD', 'bzip2-1.0.5', 'eCos-2.0', 'GFDL-1.1', 'GFDL-1.2', 'GFDL-1.3', 'GPL-1.0', 'GPL-1.0+', 'GPL-2.0', 'GPL-2.0+', 'GPL-2.0-with-autoconf-exception', 'GPL-2.0-with-bison-exception', 'GPL-2.0-with-classpath-exception', 'GPL-2.0-with-font-exception', 'GPL-2.0-with-GCC-exception', 'GPL-3.0', 'GPL-3.0+', 'GPL-3.0-with-autoconf-exception', 'GPL-3.0-with-GCC-exception', 'LGPL-2.0', 'LGPL-2.0+', 'LGPL-2.1', 'LGPL-2.1+', 'LGPL-3.0', 'LGPL-3.0+', 'Nunit', 'StandardML-NJ', 'wxWindows']]'>

the pydantic root model to validate the string

class Doi(bioimageio.spec._internal.validated_string.ValidatedString):
115class Doi(ValidatedString):
116    """A digital object identifier, see https://www.doi.org/"""
117
118    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
119        Annotated[str, StringConstraints(pattern=DOI_REGEX)]
120    ]

A digital object identifier, see https://www.doi.org/

root_model: ClassVar[Type[pydantic.root_model.RootModel[Any]]] = <class 'pydantic.root_model.RootModel[Annotated[str, StringConstraints]]'>

the pydantic root model to validate the string

class FileDescr(bioimageio.spec._internal.node.Node):
787class FileDescr(Node):
788    source: ImportantFileSource
789    """∈📦 file source"""
790
791    sha256: Optional[Sha256] = None
792    """SHA256 checksum of the source file"""
793
794    @model_validator(mode="after")
795    def _validate_sha256(self) -> Self:
796        if get_validation_context().perform_io_checks:
797            self.validate_sha256()
798
799        return self
800
801    def validate_sha256(self):
802        context = get_validation_context()
803        if (src_str := str(self.source)) in context.known_files:
804            actual_sha = context.known_files[src_str]
805        else:
806            local_source = download(self.source, sha256=self.sha256).path
807            actual_sha = get_sha256(local_source)
808            context.known_files[str(self.source)] = actual_sha
809
810        if self.sha256 == actual_sha:
811            pass
812        elif self.sha256 is None or context.update_hashes:
813            self.sha256 = actual_sha
814        elif self.sha256 != actual_sha:
815            raise ValueError(
816                f"Sha256 mismatch for {self.source}. Expected {self.sha256}, got "
817                + f"{actual_sha}. Update expected `sha256` or point to the matching "
818                + "file."
819            )
820
821        return
822
823    def download(self):
824
825        return download(self.source, sha256=self.sha256)
source: Annotated[Union[HttpUrl, RelativeFilePath, Annotated[pathlib.Path, PathType(path_type='file'), FieldInfo(annotation=NoneType, required=True, title='FilePath')]], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')]), AfterValidator(func=<function wo_special_file_name at 0x7f2602536ca0>), PlainSerializer(func=<function _package at 0x7f2602535e40>, return_type=PydanticUndefined, when_used='unless-none')]

∈📦 file source

sha256: Optional[Sha256]

SHA256 checksum of the source file

def validate_sha256(self):
801    def validate_sha256(self):
802        context = get_validation_context()
803        if (src_str := str(self.source)) in context.known_files:
804            actual_sha = context.known_files[src_str]
805        else:
806            local_source = download(self.source, sha256=self.sha256).path
807            actual_sha = get_sha256(local_source)
808            context.known_files[str(self.source)] = actual_sha
809
810        if self.sha256 == actual_sha:
811            pass
812        elif self.sha256 is None or context.update_hashes:
813            self.sha256 = actual_sha
814        elif self.sha256 != actual_sha:
815            raise ValueError(
816                f"Sha256 mismatch for {self.source}. Expected {self.sha256}, got "
817                + f"{actual_sha}. Update expected `sha256` or point to the matching "
818                + "file."
819            )
820
821        return
def download(self):
823    def download(self):
824
825        return download(self.source, sha256=self.sha256)
class GenericDescr(GenericDescrBase):
476class GenericDescr(GenericDescrBase, extra="ignore"):
477    """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).
478
479    An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook.
480    Note that those resources are described with a type-specific RDF.
481    Use this generic resource description, if none of the known specific types matches your resource.
482    """
483
484    type: Annotated[str, LowerCase] = Field("generic", frozen=True)
485    """The resource type assigns a broad category to the resource."""
486
487    id: Optional[
488        Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])]
489    ] = None
490    """bioimage.io-wide unique resource identifier
491    assigned by bioimage.io; version **un**specific."""
492
493    parent: Optional[ResourceId] = None
494    """The description from which this one is derived"""
495
496    source: Optional[HttpUrl] = None
497    """The primary source of the resource"""
498
499    @field_validator("type", mode="after")
500    @classmethod
501    def check_specific_types(cls, value: str) -> str:
502        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
503            raise ValueError(
504                f"Use the {value} description instead of this generic description for"
505                + f" your '{value}' resource."
506            )
507
508        return value

Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).

An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook. Note that those resources are described with a type-specific RDF. Use this generic resource description, if none of the known specific types matches your resource.

type: Annotated[str, Annotated[~_StrType, Predicate(str.islower)]]

The resource type assigns a broad category to the resource.

id: Optional[Annotated[ResourceId, FieldInfo(annotation=NoneType, required=True, examples=['affable-shark', 'ambitious-sloth'])]]

bioimage.io-wide unique resource identifier assigned by bioimage.io; version unspecific.

parent: Optional[ResourceId]

The description from which this one is derived

source: Optional[HttpUrl]

The primary source of the resource

@field_validator('type', mode='after')
@classmethod
def check_specific_types(cls, value: str) -> str:
499    @field_validator("type", mode="after")
500    @classmethod
501    def check_specific_types(cls, value: str) -> str:
502        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
503            raise ValueError(
504                f"Use the {value} description instead of this generic description for"
505                + f" your '{value}' resource."
506            )
507
508        return value
implemented_format_version_tuple: ClassVar[Tuple[int, int, int]] = (0, 3, 0)
def model_post_init(self: pydantic.main.BaseModel, context: Any, /) -> None:
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.

class HttpUrl(bioimageio.spec._internal.root_url.RootHttpUrl):
123class HttpUrl(RootHttpUrl):
124    """A URL with the HTTP or HTTPS scheme."""
125
126    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[pydantic.HttpUrl]
127    _exists: Optional[bool] = None
128
129    def _after_validator(self):
130        self = super()._after_validator()
131        context = get_validation_context()
132        if (
133            context.perform_io_checks
134            and str(self._validated) not in context.known_files
135        ):
136            self._validated = _validate_url(self._validated)
137            self._exists = True
138
139        return self
140
141    def exists(self):
142        """True if URL is available"""
143        if self._exists is None:
144            try:
145                self._validated = _validate_url(self._validated)
146            except Exception as e:
147                logger.info(e)
148                self._exists = False
149            else:
150                self._exists = True
151
152        return self._exists

A URL with the HTTP or HTTPS scheme.

root_model: ClassVar[Type[pydantic.root_model.RootModel[Any]]] = <class 'pydantic.root_model.RootModel[Annotated[Url, UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=None, default_host=None, default_port=None, default_path=None)]]'>

the pydantic root model to validate the string

def exists(self):
141    def exists(self):
142        """True if URL is available"""
143        if self._exists is None:
144            try:
145                self._validated = _validate_url(self._validated)
146            except Exception as e:
147                logger.info(e)
148                self._exists = False
149            else:
150                self._exists = True
151
152        return self._exists

True if URL is available

KNOWN_SPECIFIC_RESOURCE_TYPES = ('application', 'collection', 'dataset', 'model', 'notebook')
class LicenseId(bioimageio.spec._internal.validated_string.ValidatedString):
20class LicenseId(ValidatedString):
21    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[LicenseIdLiteral]

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

root_model: ClassVar[Type[pydantic.root_model.RootModel[Any]]] = <class 'pydantic.root_model.RootModel[Literal['0BSD', 'AAL', 'Abstyles', 'AdaCore-doc', 'Adobe-2006', 'Adobe-Display-PostScript', 'Adobe-Glyph', 'Adobe-Utopia', 'ADSL', 'AFL-1.1', 'AFL-1.2', 'AFL-2.0', 'AFL-2.1', 'AFL-3.0', 'Afmparse', 'AGPL-1.0-only', 'AGPL-1.0-or-later', 'AGPL-3.0-only', 'AGPL-3.0-or-later', 'Aladdin', 'AMDPLPA', 'AML', 'AML-glslang', 'AMPAS', 'ANTLR-PD', 'ANTLR-PD-fallback', 'Apache-1.0', 'Apache-1.1', 'Apache-2.0', 'APAFML', 'APL-1.0', 'App-s2p', 'APSL-1.0', 'APSL-1.1', 'APSL-1.2', 'APSL-2.0', 'Arphic-1999', 'Artistic-1.0', 'Artistic-1.0-cl8', 'Artistic-1.0-Perl', 'Artistic-2.0', 'ASWF-Digital-Assets-1.0', 'ASWF-Digital-Assets-1.1', 'Baekmuk', 'Bahyph', 'Barr', 'bcrypt-Solar-Designer', 'Beerware', 'Bitstream-Charter', 'Bitstream-Vera', 'BitTorrent-1.0', 'BitTorrent-1.1', 'blessing', 'BlueOak-1.0.0', 'Boehm-GC', 'Borceux', 'Brian-Gladman-2-Clause', 'Brian-Gladman-3-Clause', 'BSD-1-Clause', 'BSD-2-Clause', 'BSD-2-Clause-Darwin', 'BSD-2-Clause-Patent', 'BSD-2-Clause-Views', 'BSD-3-Clause', 'BSD-3-Clause-acpica', 'BSD-3-Clause-Attribution', 'BSD-3-Clause-Clear', 'BSD-3-Clause-flex', 'BSD-3-Clause-HP', 'BSD-3-Clause-LBNL', 'BSD-3-Clause-Modification', 'BSD-3-Clause-No-Military-License', 'BSD-3-Clause-No-Nuclear-License', 'BSD-3-Clause-No-Nuclear-License-2014', 'BSD-3-Clause-No-Nuclear-Warranty', 'BSD-3-Clause-Open-MPI', 'BSD-3-Clause-Sun', 'BSD-4-Clause', 'BSD-4-Clause-Shortened', 'BSD-4-Clause-UC', 'BSD-4.3RENO', 'BSD-4.3TAHOE', 'BSD-Advertising-Acknowledgement', 'BSD-Attribution-HPND-disclaimer', 'BSD-Inferno-Nettverk', 'BSD-Protection', 'BSD-Source-beginning-file', 'BSD-Source-Code', 'BSD-Systemics', 'BSD-Systemics-W3Works', 'BSL-1.0', 'BUSL-1.1', 'bzip2-1.0.6', 'C-UDA-1.0', 'CAL-1.0', 'CAL-1.0-Combined-Work-Exception', 'Caldera', 'Caldera-no-preamble', 'CATOSL-1.1', 'CC-BY-1.0', 'CC-BY-2.0', 'CC-BY-2.5', 'CC-BY-2.5-AU', 'CC-BY-3.0', 'CC-BY-3.0-AT', 'CC-BY-3.0-AU', 'CC-BY-3.0-DE', 'CC-BY-3.0-IGO', 'CC-BY-3.0-NL', 'CC-BY-3.0-US', 'CC-BY-4.0', 'CC-BY-NC-1.0', 'CC-BY-NC-2.0', 'CC-BY-NC-2.5', 'CC-BY-NC-3.0', 'CC-BY-NC-3.0-DE', 'CC-BY-NC-4.0', 'CC-BY-NC-ND-1.0', 'CC-BY-NC-ND-2.0', 'CC-BY-NC-ND-2.5', 'CC-BY-NC-ND-3.0', 'CC-BY-NC-ND-3.0-DE', 'CC-BY-NC-ND-3.0-IGO', 'CC-BY-NC-ND-4.0', 'CC-BY-NC-SA-1.0', 'CC-BY-NC-SA-2.0', 'CC-BY-NC-SA-2.0-DE', 'CC-BY-NC-SA-2.0-FR', 'CC-BY-NC-SA-2.0-UK', 'CC-BY-NC-SA-2.5', 'CC-BY-NC-SA-3.0', 'CC-BY-NC-SA-3.0-DE', 'CC-BY-NC-SA-3.0-IGO', 'CC-BY-NC-SA-4.0', 'CC-BY-ND-1.0', 'CC-BY-ND-2.0', 'CC-BY-ND-2.5', 'CC-BY-ND-3.0', 'CC-BY-ND-3.0-DE', 'CC-BY-ND-4.0', 'CC-BY-SA-1.0', 'CC-BY-SA-2.0', 'CC-BY-SA-2.0-UK', 'CC-BY-SA-2.1-JP', 'CC-BY-SA-2.5', 'CC-BY-SA-3.0', 'CC-BY-SA-3.0-AT', 'CC-BY-SA-3.0-DE', 'CC-BY-SA-3.0-IGO', 'CC-BY-SA-4.0', 'CC-PDDC', 'CC0-1.0', 'CDDL-1.0', 'CDDL-1.1', 'CDL-1.0', 'CDLA-Permissive-1.0', 'CDLA-Permissive-2.0', 'CDLA-Sharing-1.0', 'CECILL-1.0', 'CECILL-1.1', 'CECILL-2.0', 'CECILL-2.1', 'CECILL-B', 'CECILL-C', 'CERN-OHL-1.1', 'CERN-OHL-1.2', 'CERN-OHL-P-2.0', 'CERN-OHL-S-2.0', 'CERN-OHL-W-2.0', 'CFITSIO', 'check-cvs', 'checkmk', 'ClArtistic', 'Clips', 'CMU-Mach', 'CMU-Mach-nodoc', 'CNRI-Jython', 'CNRI-Python', 'CNRI-Python-GPL-Compatible', 'COIL-1.0', 'Community-Spec-1.0', 'Condor-1.1', 'copyleft-next-0.3.0', 'copyleft-next-0.3.1', 'Cornell-Lossless-JPEG', 'CPAL-1.0', 'CPL-1.0', 'CPOL-1.02', 'Cronyx', 'Crossword', 'CrystalStacker', 'CUA-OPL-1.0', 'Cube', 'curl', 'D-FSL-1.0', 'DEC-3-Clause', 'diffmark', 'DL-DE-BY-2.0', 'DL-DE-ZERO-2.0', 'DOC', 'Dotseqn', 'DRL-1.0', 'DRL-1.1', 'DSDP', 'dtoa', 'dvipdfm', 'ECL-1.0', 'ECL-2.0', 'EFL-1.0', 'EFL-2.0', 'eGenix', 'Elastic-2.0', 'Entessa', 'EPICS', 'EPL-1.0', 'EPL-2.0', 'ErlPL-1.1', 'etalab-2.0', 'EUDatagrid', 'EUPL-1.0', 'EUPL-1.1', 'EUPL-1.2', 'Eurosym', 'Fair', 'FBM', 'FDK-AAC', 'Ferguson-Twofish', 'Frameworx-1.0', 'FreeBSD-DOC', 'FreeImage', 'FSFAP', 'FSFAP-no-warranty-disclaimer', 'FSFUL', 'FSFULLR', 'FSFULLRWD', 'FTL', 'Furuseth', 'fwlw', 'GCR-docs', 'GD', 'GFDL-1.1-invariants-only', 'GFDL-1.1-invariants-or-later', 'GFDL-1.1-no-invariants-only', 'GFDL-1.1-no-invariants-or-later', 'GFDL-1.1-only', 'GFDL-1.1-or-later', 'GFDL-1.2-invariants-only', 'GFDL-1.2-invariants-or-later', 'GFDL-1.2-no-invariants-only', 'GFDL-1.2-no-invariants-or-later', 'GFDL-1.2-only', 'GFDL-1.2-or-later', 'GFDL-1.3-invariants-only', 'GFDL-1.3-invariants-or-later', 'GFDL-1.3-no-invariants-only', 'GFDL-1.3-no-invariants-or-later', 'GFDL-1.3-only', 'GFDL-1.3-or-later', 'Giftware', 'GL2PS', 'Glide', 'Glulxe', 'GLWTPL', 'gnuplot', 'GPL-1.0-only', 'GPL-1.0-or-later', 'GPL-2.0-only', 'GPL-2.0-or-later', 'GPL-3.0-only', 'GPL-3.0-or-later', 'Graphics-Gems', 'gSOAP-1.3b', 'gtkbook', 'HaskellReport', 'hdparm', 'Hippocratic-2.1', 'HP-1986', 'HP-1989', 'HPND', 'HPND-DEC', 'HPND-doc', 'HPND-doc-sell', 'HPND-export-US', 'HPND-export-US-modify', 'HPND-Fenneberg-Livingston', 'HPND-INRIA-IMAG', 'HPND-Kevlin-Henney', 'HPND-Markus-Kuhn', 'HPND-MIT-disclaimer', 'HPND-Pbmplus', 'HPND-sell-MIT-disclaimer-xserver', 'HPND-sell-regexpr', 'HPND-sell-variant', 'HPND-sell-variant-MIT-disclaimer', 'HPND-UC', 'HTMLTIDY', 'IBM-pibs', 'ICU', 'IEC-Code-Components-EULA', 'IJG', 'IJG-short', 'ImageMagick', 'iMatix', 'Imlib2', 'Info-ZIP', 'Inner-Net-2.0', 'Intel', 'Intel-ACPI', 'Interbase-1.0', 'IPA', 'IPL-1.0', 'ISC', 'ISC-Veillard', 'Jam', 'JasPer-2.0', 'JPL-image', 'JPNIC', 'JSON', 'Kastrup', 'Kazlib', 'Knuth-CTAN', 'LAL-1.2', 'LAL-1.3', 'Latex2e', 'Latex2e-translated-notice', 'Leptonica', 'LGPL-2.0-only', 'LGPL-2.0-or-later', 'LGPL-2.1-only', 'LGPL-2.1-or-later', 'LGPL-3.0-only', 'LGPL-3.0-or-later', 'LGPLLR', 'Libpng', 'libpng-2.0', 'libselinux-1.0', 'libtiff', 'libutil-David-Nugent', 'LiLiQ-P-1.1', 'LiLiQ-R-1.1', 'LiLiQ-Rplus-1.1', 'Linux-man-pages-1-para', 'Linux-man-pages-copyleft', 'Linux-man-pages-copyleft-2-para', 'Linux-man-pages-copyleft-var', 'Linux-OpenIB', 'LOOP', 'LPD-document', 'LPL-1.0', 'LPL-1.02', 'LPPL-1.0', 'LPPL-1.1', 'LPPL-1.2', 'LPPL-1.3a', 'LPPL-1.3c', 'lsof', 'Lucida-Bitmap-Fonts', 'LZMA-SDK-9.11-to-9.20', 'LZMA-SDK-9.22', 'Mackerras-3-Clause', 'Mackerras-3-Clause-acknowledgment', 'magaz', 'mailprio', 'MakeIndex', 'Martin-Birgmeier', 'McPhee-slideshow', 'metamail', 'Minpack', 'MirOS', 'MIT', 'MIT-0', 'MIT-advertising', 'MIT-CMU', 'MIT-enna', 'MIT-feh', 'MIT-Festival', 'MIT-Modern-Variant', 'MIT-open-group', 'MIT-testregex', 'MIT-Wu', 'MITNFA', 'MMIXware', 'Motosoto', 'MPEG-SSG', 'mpi-permissive', 'mpich2', 'MPL-1.0', 'MPL-1.1', 'MPL-2.0', 'MPL-2.0-no-copyleft-exception', 'mplus', 'MS-LPL', 'MS-PL', 'MS-RL', 'MTLL', 'MulanPSL-1.0', 'MulanPSL-2.0', 'Multics', 'Mup', 'NAIST-2003', 'NASA-1.3', 'Naumen', 'NBPL-1.0', 'NCGL-UK-2.0', 'NCSA', 'Net-SNMP', 'NetCDF', 'Newsletr', 'NGPL', 'NICTA-1.0', 'NIST-PD', 'NIST-PD-fallback', 'NIST-Software', 'NLOD-1.0', 'NLOD-2.0', 'NLPL', 'Nokia', 'NOSL', 'Noweb', 'NPL-1.0', 'NPL-1.1', 'NPOSL-3.0', 'NRL', 'NTP', 'NTP-0', 'O-UDA-1.0', 'OCCT-PL', 'OCLC-2.0', 'ODbL-1.0', 'ODC-By-1.0', 'OFFIS', 'OFL-1.0', 'OFL-1.0-no-RFN', 'OFL-1.0-RFN', 'OFL-1.1', 'OFL-1.1-no-RFN', 'OFL-1.1-RFN', 'OGC-1.0', 'OGDL-Taiwan-1.0', 'OGL-Canada-2.0', 'OGL-UK-1.0', 'OGL-UK-2.0', 'OGL-UK-3.0', 'OGTSL', 'OLDAP-1.1', 'OLDAP-1.2', 'OLDAP-1.3', 'OLDAP-1.4', 'OLDAP-2.0', 'OLDAP-2.0.1', 'OLDAP-2.1', 'OLDAP-2.2', 'OLDAP-2.2.1', 'OLDAP-2.2.2', 'OLDAP-2.3', 'OLDAP-2.4', 'OLDAP-2.5', 'OLDAP-2.6', 'OLDAP-2.7', 'OLDAP-2.8', 'OLFL-1.3', 'OML', 'OpenPBS-2.3', 'OpenSSL', 'OpenSSL-standalone', 'OpenVision', 'OPL-1.0', 'OPL-UK-3.0', 'OPUBL-1.0', 'OSET-PL-2.1', 'OSL-1.0', 'OSL-1.1', 'OSL-2.0', 'OSL-2.1', 'OSL-3.0', 'PADL', 'Parity-6.0.0', 'Parity-7.0.0', 'PDDL-1.0', 'PHP-3.0', 'PHP-3.01', 'Pixar', 'Plexus', 'pnmstitch', 'PolyForm-Noncommercial-1.0.0', 'PolyForm-Small-Business-1.0.0', 'PostgreSQL', 'PSF-2.0', 'psfrag', 'psutils', 'Python-2.0', 'Python-2.0.1', 'python-ldap', 'Qhull', 'QPL-1.0', 'QPL-1.0-INRIA-2004', 'radvd', 'Rdisc', 'RHeCos-1.1', 'RPL-1.1', 'RPL-1.5', 'RPSL-1.0', 'RSA-MD', 'RSCPL', 'Ruby', 'SAX-PD', 'SAX-PD-2.0', 'Saxpath', 'SCEA', 'SchemeReport', 'Sendmail', 'Sendmail-8.23', 'SGI-B-1.0', 'SGI-B-1.1', 'SGI-B-2.0', 'SGI-OpenGL', 'SGP4', 'SHL-0.5', 'SHL-0.51', 'SimPL-2.0', 'SISSL', 'SISSL-1.2', 'SL', 'Sleepycat', 'SMLNJ', 'SMPPL', 'SNIA', 'snprintf', 'softSurfer', 'Soundex', 'Spencer-86', 'Spencer-94', 'Spencer-99', 'SPL-1.0', 'ssh-keyscan', 'SSH-OpenSSH', 'SSH-short', 'SSLeay-standalone', 'SSPL-1.0', 'SugarCRM-1.1.3', 'Sun-PPP', 'SunPro', 'SWL', 'swrule', 'Symlinks', 'TAPR-OHL-1.0', 'TCL', 'TCP-wrappers', 'TermReadKey', 'TGPPL-1.0', 'TMate', 'TORQUE-1.1', 'TOSL', 'TPDL', 'TPL-1.0', 'TTWL', 'TTYP0', 'TU-Berlin-1.0', 'TU-Berlin-2.0', 'UCAR', 'UCL-1.0', 'ulem', 'UMich-Merit', 'Unicode-3.0', 'Unicode-DFS-2015', 'Unicode-DFS-2016', 'Unicode-TOU', 'UnixCrypt', 'Unlicense', 'UPL-1.0', 'URT-RLE', 'Vim', 'VOSTROM', 'VSL-1.0', 'W3C', 'W3C-19980720', 'W3C-20150513', 'w3m', 'Watcom-1.0', 'Widget-Workshop', 'Wsuipa', 'WTFPL', 'X11', 'X11-distribute-modifications-variant', 'Xdebug-1.03', 'Xerox', 'Xfig', 'XFree86-1.1', 'xinetd', 'xkeyboard-config-Zinoviev', 'xlock', 'Xnet', 'xpp', 'XSkat', 'YPL-1.0', 'YPL-1.1', 'Zed', 'Zeeff', 'Zend-2.0', 'Zimbra-1.3', 'Zimbra-1.4', 'Zlib', 'zlib-acknowledgement', 'ZPL-1.1', 'ZPL-2.0', 'ZPL-2.1']]'>

the pydantic root model to validate the string

class LinkedResource(LinkedResourceBase):
218class LinkedResource(LinkedResourceBase):
219    """Reference to a bioimage.io resource"""
220
221    id: ResourceId
222    """A valid resource `id` from the official bioimage.io collection."""

Reference to a bioimage.io resource

A valid resource id from the official bioimage.io collection.

Inherited Members
LinkedResourceBase
version
class Maintainer(bioimageio.spec.generic.v0_2.Maintainer):
149class Maintainer(_Maintainer_v0_2):
150    name: Optional[Annotated[str, Predicate(_has_no_slash)]] = None
151    github_user: str
152
153    @field_validator("github_user", mode="after")
154    def validate_gh_user(cls, value: str):
155        return validate_gh_user(value)
name: Optional[Annotated[str, Predicate(func=<function _has_no_slash at 0x7f26001e9e40>)]]
github_user: str
@field_validator('github_user', mode='after')
def validate_gh_user(cls, value: str):
153    @field_validator("github_user", mode="after")
154    def validate_gh_user(cls, value: str):
155        return validate_gh_user(value)
class OrcidId(bioimageio.spec._internal.validated_string.ValidatedString):
142class OrcidId(ValidatedString):
143    """An ORCID identifier, see https://orcid.org/"""
144
145    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
146        Annotated[str, AfterValidator(_validate_orcid_id)]
147    ]

An ORCID identifier, see https://orcid.org/

root_model: ClassVar[Type[pydantic.root_model.RootModel[Any]]] = <class 'pydantic.root_model.RootModel[Annotated[str, AfterValidator]]'>

the pydantic root model to validate the string

class RelativeFilePath(pydantic.root_model.RootModel[PurePath], typing.Generic[~AbsolutePathT]):
184class RelativeFilePath(
185    RelativePathBase[Union[AbsoluteFilePath, HttpUrl, ZipPath]], frozen=True
186):
187    """A path relative to the `rdf.yaml` file (also if the RDF source is a URL)."""
188
189    def model_post_init(self, __context: Any) -> None:
190        """add validation @private"""
191        if not self.root.parts:  # an empty path can only be a directory
192            raise ValueError(f"{self.root} is not a valid file path.")
193
194        super().model_post_init(__context)
195
196    def get_absolute(
197        self, root: "RootHttpUrl | Path | AnyUrl | ZipFile"
198    ) -> "AbsoluteFilePath | HttpUrl | ZipPath":
199        absolute = self._get_absolute_impl(root)
200        if (
201            isinstance(absolute, Path)
202            and (context := get_validation_context()).perform_io_checks
203            and str(self.root) not in context.known_files
204            and not absolute.is_file()
205        ):
206            raise ValueError(f"{absolute} does not point to an existing file")
207
208        return absolute

A path relative to the rdf.yaml file (also if the RDF source is a URL).

def model_post_init(self: pydantic.main.BaseModel, context: Any, /) -> None:
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.

def get_absolute( self, root: bioimageio.spec._internal.root_url.RootHttpUrl | pathlib.Path | pydantic_core._pydantic_core.Url | zipfile.ZipFile) -> Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(is_absolute), FieldInfo(annotation=NoneType, required=True, title='AbsoluteFilePath')], HttpUrl, zipp.Path]:
196    def get_absolute(
197        self, root: "RootHttpUrl | Path | AnyUrl | ZipFile"
198    ) -> "AbsoluteFilePath | HttpUrl | ZipPath":
199        absolute = self._get_absolute_impl(root)
200        if (
201            isinstance(absolute, Path)
202            and (context := get_validation_context()).perform_io_checks
203            and str(self.root) not in context.known_files
204            and not absolute.is_file()
205        ):
206            raise ValueError(f"{absolute} does not point to an existing file")
207
208        return absolute
class ResourceId(bioimageio.spec._internal.validated_string.ValidatedString):
 93class ResourceId(ValidatedString):
 94    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
 95        Annotated[
 96            NotEmpty[str],
 97            RestrictCharacters(string.ascii_lowercase + string.digits + "_-/."),
 98            annotated_types.Predicate(
 99                lambda s: not (s.startswith("/") or s.endswith("/"))
100            ),
101        ]
102    ]

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

root_model: ClassVar[Type[pydantic.root_model.RootModel[Any]]] = <class 'pydantic.root_model.RootModel[Annotated[str, MinLen, RestrictCharacters, Predicate]]'>

the pydantic root model to validate the string

class Sha256(bioimageio.spec._internal.validated_string.ValidatedString):
33class Sha256(ValidatedString):
34    """A SHA-256 hash value"""
35
36    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
37        Annotated[
38            str,
39            StringConstraints(
40                strip_whitespace=True, to_lower=True, min_length=64, max_length=64
41            ),
42        ]
43    ]

A SHA-256 hash value

root_model: ClassVar[Type[pydantic.root_model.RootModel[Any]]] = <class 'pydantic.root_model.RootModel[Annotated[str, StringConstraints]]'>

the pydantic root model to validate the string

class Uploader(bioimageio.spec._internal.node.Node):
110class Uploader(Node):
111    email: EmailStr
112    """Email"""
113    name: Optional[Annotated[str, AfterValidator(_remove_slashes)]] = None
114    """name"""
email: pydantic.networks.EmailStr

Email

name: Optional[Annotated[str, AfterValidator(func=<function _remove_slashes at 0x7f260131f9c0>)]]

name

VALID_COVER_IMAGE_EXTENSIONS = ('.gif', '.jpeg', '.jpg', '.png', '.svg')
class Version(pydantic.main.BaseModel, typing.Generic[~RootModelRootType]):
 10class Version(RootModel[Union[str, int, float]]):
 11    """wraps a packaging.version.Version instance for validation in pydantic models"""
 12
 13    _version: packaging.version.Version = PrivateAttr()
 14
 15    def __str__(self):
 16        return str(self._version)
 17
 18    def model_post_init(self, __context: Any) -> None:
 19        """set `_version` attribute @private"""
 20        self._version = packaging.version.Version(str(self.root))
 21        return super().model_post_init(__context)
 22
 23    def __lt__(self, other: Version):
 24        return self._version < other._version
 25
 26    def __eq__(self, other: Version):
 27        return self._version == other._version
 28
 29    # the properties below are adopted from and mirror properties of packaging.version.Version
 30    @property
 31    def epoch(self) -> int:
 32        """The epoch of the version.
 33
 34        >>> Version("2.0.0").epoch
 35        0
 36        >>> Version("1!2.0.0").epoch
 37        1
 38        """
 39        return self._version.epoch
 40
 41    @property
 42    def release(self) -> Tuple[int, ...]:
 43        """The components of the "release" segment of the version.
 44
 45        >>> Version("1.2.3").release
 46        (1, 2, 3)
 47        >>> Version("2.0.0").release
 48        (2, 0, 0)
 49        >>> Version("1!2.0.0.post0").release
 50        (2, 0, 0)
 51
 52        Includes trailing zeroes but not the epoch or any pre-release / development /
 53        post-release suffixes.
 54        """
 55        return self._version.release
 56
 57    @property
 58    def pre(self) -> Optional[Tuple[str, int]]:
 59        """The pre-release segment of the version.
 60
 61        >>> print(Version("1.2.3").pre)
 62        None
 63        >>> Version("1.2.3a1").pre
 64        ('a', 1)
 65        >>> Version("1.2.3b1").pre
 66        ('b', 1)
 67        >>> Version("1.2.3rc1").pre
 68        ('rc', 1)
 69        """
 70        return self._version.pre
 71
 72    @property
 73    def post(self) -> Optional[int]:
 74        """The post-release number of the version.
 75
 76        >>> print(Version("1.2.3").post)
 77        None
 78        >>> Version("1.2.3.post1").post
 79        1
 80        """
 81        return self._version.post
 82
 83    @property
 84    def dev(self) -> Optional[int]:
 85        """The development number of the version.
 86
 87        >>> print(Version("1.2.3").dev)
 88        None
 89        >>> Version("1.2.3.dev1").dev
 90        1
 91        """
 92        return self._version.dev
 93
 94    @property
 95    def local(self) -> Optional[str]:
 96        """The local version segment of the version.
 97
 98        >>> print(Version("1.2.3").local)
 99        None
100        >>> Version("1.2.3+abc").local
101        'abc'
102        """
103        return self._version.local
104
105    @property
106    def public(self) -> str:
107        """The public portion of the version.
108
109        >>> Version("1.2.3").public
110        '1.2.3'
111        >>> Version("1.2.3+abc").public
112        '1.2.3'
113        >>> Version("1.2.3+abc.dev1").public
114        '1.2.3'
115        """
116        return self._version.public
117
118    @property
119    def base_version(self) -> str:
120        """The "base version" of the version.
121
122        >>> Version("1.2.3").base_version
123        '1.2.3'
124        >>> Version("1.2.3+abc").base_version
125        '1.2.3'
126        >>> Version("1!1.2.3+abc.dev1").base_version
127        '1!1.2.3'
128
129        The "base version" is the public version of the project without any pre or post
130        release markers.
131        """
132        return self._version.base_version
133
134    @property
135    def is_prerelease(self) -> bool:
136        """Whether this version is a pre-release.
137
138        >>> Version("1.2.3").is_prerelease
139        False
140        >>> Version("1.2.3a1").is_prerelease
141        True
142        >>> Version("1.2.3b1").is_prerelease
143        True
144        >>> Version("1.2.3rc1").is_prerelease
145        True
146        >>> Version("1.2.3dev1").is_prerelease
147        True
148        """
149        return self._version.is_prerelease
150
151    @property
152    def is_postrelease(self) -> bool:
153        """Whether this version is a post-release.
154
155        >>> Version("1.2.3").is_postrelease
156        False
157        >>> Version("1.2.3.post1").is_postrelease
158        True
159        """
160        return self._version.is_postrelease
161
162    @property
163    def is_devrelease(self) -> bool:
164        """Whether this version is a development release.
165
166        >>> Version("1.2.3").is_devrelease
167        False
168        >>> Version("1.2.3.dev1").is_devrelease
169        True
170        """
171        return self._version.is_devrelease
172
173    @property
174    def major(self) -> int:
175        """The first item of :attr:`release` or ``0`` if unavailable.
176
177        >>> Version("1.2.3").major
178        1
179        """
180        return self._version.major
181
182    @property
183    def minor(self) -> int:
184        """The second item of :attr:`release` or ``0`` if unavailable.
185
186        >>> Version("1.2.3").minor
187        2
188        >>> Version("1").minor
189        0
190        """
191        return self._version.minor
192
193    @property
194    def micro(self) -> int:
195        """The third item of :attr:`release` or ``0`` if unavailable.
196
197        >>> Version("1.2.3").micro
198        3
199        >>> Version("1").micro
200        0
201        """
202        return self._version.micro

wraps a packaging.version.Version instance for validation in pydantic models

epoch: int
30    @property
31    def epoch(self) -> int:
32        """The epoch of the version.
33
34        >>> Version("2.0.0").epoch
35        0
36        >>> Version("1!2.0.0").epoch
37        1
38        """
39        return self._version.epoch

The epoch of the version.

>>> Version("2.0.0").epoch
0
>>> Version("1!2.0.0").epoch
1
release: Tuple[int, ...]
41    @property
42    def release(self) -> Tuple[int, ...]:
43        """The components of the "release" segment of the version.
44
45        >>> Version("1.2.3").release
46        (1, 2, 3)
47        >>> Version("2.0.0").release
48        (2, 0, 0)
49        >>> Version("1!2.0.0.post0").release
50        (2, 0, 0)
51
52        Includes trailing zeroes but not the epoch or any pre-release / development /
53        post-release suffixes.
54        """
55        return self._version.release

The components of the "release" segment of the version.

>>> Version("1.2.3").release
(1, 2, 3)
>>> Version("2.0.0").release
(2, 0, 0)
>>> Version("1!2.0.0.post0").release
(2, 0, 0)

Includes trailing zeroes but not the epoch or any pre-release / development / post-release suffixes.

pre: Optional[Tuple[str, int]]
57    @property
58    def pre(self) -> Optional[Tuple[str, int]]:
59        """The pre-release segment of the version.
60
61        >>> print(Version("1.2.3").pre)
62        None
63        >>> Version("1.2.3a1").pre
64        ('a', 1)
65        >>> Version("1.2.3b1").pre
66        ('b', 1)
67        >>> Version("1.2.3rc1").pre
68        ('rc', 1)
69        """
70        return self._version.pre

The pre-release segment of the version.

>>> print(Version("1.2.3").pre)
None
>>> Version("1.2.3a1").pre
('a', 1)
>>> Version("1.2.3b1").pre
('b', 1)
>>> Version("1.2.3rc1").pre
('rc', 1)
post: Optional[int]
72    @property
73    def post(self) -> Optional[int]:
74        """The post-release number of the version.
75
76        >>> print(Version("1.2.3").post)
77        None
78        >>> Version("1.2.3.post1").post
79        1
80        """
81        return self._version.post

The post-release number of the version.

>>> print(Version("1.2.3").post)
None
>>> Version("1.2.3.post1").post
1
dev: Optional[int]
83    @property
84    def dev(self) -> Optional[int]:
85        """The development number of the version.
86
87        >>> print(Version("1.2.3").dev)
88        None
89        >>> Version("1.2.3.dev1").dev
90        1
91        """
92        return self._version.dev

The development number of the version.

>>> print(Version("1.2.3").dev)
None
>>> Version("1.2.3.dev1").dev
1
local: Optional[str]
 94    @property
 95    def local(self) -> Optional[str]:
 96        """The local version segment of the version.
 97
 98        >>> print(Version("1.2.3").local)
 99        None
100        >>> Version("1.2.3+abc").local
101        'abc'
102        """
103        return self._version.local

The local version segment of the version.

>>> print(Version("1.2.3").local)
None
>>> Version("1.2.3+abc").local
'abc'
public: str
105    @property
106    def public(self) -> str:
107        """The public portion of the version.
108
109        >>> Version("1.2.3").public
110        '1.2.3'
111        >>> Version("1.2.3+abc").public
112        '1.2.3'
113        >>> Version("1.2.3+abc.dev1").public
114        '1.2.3'
115        """
116        return self._version.public

The public portion of the version.

>>> Version("1.2.3").public
'1.2.3'
>>> Version("1.2.3+abc").public
'1.2.3'
>>> Version("1.2.3+abc.dev1").public
'1.2.3'
base_version: str
118    @property
119    def base_version(self) -> str:
120        """The "base version" of the version.
121
122        >>> Version("1.2.3").base_version
123        '1.2.3'
124        >>> Version("1.2.3+abc").base_version
125        '1.2.3'
126        >>> Version("1!1.2.3+abc.dev1").base_version
127        '1!1.2.3'
128
129        The "base version" is the public version of the project without any pre or post
130        release markers.
131        """
132        return self._version.base_version

The "base version" of the version.

>>> Version("1.2.3").base_version
'1.2.3'
>>> Version("1.2.3+abc").base_version
'1.2.3'
>>> Version("1!1.2.3+abc.dev1").base_version
'1!1.2.3'

The "base version" is the public version of the project without any pre or post release markers.

is_prerelease: bool
134    @property
135    def is_prerelease(self) -> bool:
136        """Whether this version is a pre-release.
137
138        >>> Version("1.2.3").is_prerelease
139        False
140        >>> Version("1.2.3a1").is_prerelease
141        True
142        >>> Version("1.2.3b1").is_prerelease
143        True
144        >>> Version("1.2.3rc1").is_prerelease
145        True
146        >>> Version("1.2.3dev1").is_prerelease
147        True
148        """
149        return self._version.is_prerelease

Whether this version is a pre-release.

>>> Version("1.2.3").is_prerelease
False
>>> Version("1.2.3a1").is_prerelease
True
>>> Version("1.2.3b1").is_prerelease
True
>>> Version("1.2.3rc1").is_prerelease
True
>>> Version("1.2.3dev1").is_prerelease
True
is_postrelease: bool
151    @property
152    def is_postrelease(self) -> bool:
153        """Whether this version is a post-release.
154
155        >>> Version("1.2.3").is_postrelease
156        False
157        >>> Version("1.2.3.post1").is_postrelease
158        True
159        """
160        return self._version.is_postrelease

Whether this version is a post-release.

>>> Version("1.2.3").is_postrelease
False
>>> Version("1.2.3.post1").is_postrelease
True
is_devrelease: bool
162    @property
163    def is_devrelease(self) -> bool:
164        """Whether this version is a development release.
165
166        >>> Version("1.2.3").is_devrelease
167        False
168        >>> Version("1.2.3.dev1").is_devrelease
169        True
170        """
171        return self._version.is_devrelease

Whether this version is a development release.

>>> Version("1.2.3").is_devrelease
False
>>> Version("1.2.3.dev1").is_devrelease
True
major: int
173    @property
174    def major(self) -> int:
175        """The first item of :attr:`release` or ``0`` if unavailable.
176
177        >>> Version("1.2.3").major
178        1
179        """
180        return self._version.major

The first item of release or 0 if unavailable.

>>> Version("1.2.3").major
1
minor: int
182    @property
183    def minor(self) -> int:
184        """The second item of :attr:`release` or ``0`` if unavailable.
185
186        >>> Version("1.2.3").minor
187        2
188        >>> Version("1").minor
189        0
190        """
191        return self._version.minor

The second item of release or 0 if unavailable.

>>> Version("1.2.3").minor
2
>>> Version("1").minor
0
micro: int
193    @property
194    def micro(self) -> int:
195        """The third item of :attr:`release` or ``0`` if unavailable.
196
197        >>> Version("1.2.3").micro
198        3
199        >>> Version("1").micro
200        0
201        """
202        return self._version.micro

The third item of release or 0 if unavailable.

>>> Version("1.2.3").micro
3
>>> Version("1").micro
0