bioimageio.spec.generic.v0_2

  1import string
  2from typing import (
  3    TYPE_CHECKING,
  4    Any,
  5    ClassVar,
  6    Dict,
  7    List,
  8    Literal,
  9    Mapping,
 10    Optional,
 11    Sequence,
 12    Type,
 13    TypeVar,
 14    Union,
 15)
 16
 17import annotated_types
 18from annotated_types import Len, LowerCase, MaxLen
 19from pydantic import (
 20    EmailStr,
 21    Field,
 22    RootModel,
 23    ValidationInfo,
 24    field_validator,
 25    model_validator,
 26)
 27from typing_extensions import Annotated, Self, assert_never
 28
 29from .._internal.common_nodes import Node, ResourceDescrBase
 30from .._internal.constants import TAG_CATEGORIES
 31from .._internal.field_warning import as_warning, issue_warning, warn
 32from .._internal.io import (
 33    BioimageioYamlContent,
 34    InPackageIfLocalFileSource,
 35    WithSuffix,
 36    YamlValue,
 37    include_in_package_serializer,
 38)
 39from .._internal.io_basics import AbsoluteFilePath as AbsoluteFilePath
 40from .._internal.type_guards import is_sequence
 41from .._internal.types import (
 42    DeprecatedLicenseId,
 43    FileSource,
 44    ImportantFileSource,
 45    LicenseId,
 46    NotEmpty,
 47)
 48from .._internal.types import Doi as Doi
 49from .._internal.types import OrcidId as OrcidId
 50from .._internal.types import RelativeFilePath as RelativeFilePath
 51from .._internal.url import HttpUrl as HttpUrl
 52from .._internal.validated_string import ValidatedString
 53from .._internal.validator_annotations import AfterValidator, RestrictCharacters
 54from .._internal.version_type import Version as Version
 55from ._v0_2_converter import convert_from_older_format as _convert_from_older_format
 56
 57
 58class ResourceId(ValidatedString):
 59    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
 60        Annotated[
 61            NotEmpty[str],
 62            AfterValidator(str.lower),  # convert upper case on the fly
 63            RestrictCharacters(string.ascii_lowercase + string.digits + "_-/."),
 64            annotated_types.Predicate(
 65                lambda s: not (s.startswith("/") or s.endswith("/"))
 66            ),
 67        ]
 68    ]
 69
 70
 71KNOWN_SPECIFIC_RESOURCE_TYPES = (
 72    "application",
 73    "collection",
 74    "dataset",
 75    "model",
 76    "notebook",
 77)
 78
 79VALID_COVER_IMAGE_EXTENSIONS = (
 80    ".gif",
 81    ".jpeg",
 82    ".jpg",
 83    ".png",
 84    ".svg",
 85    ".tif",
 86    ".tiff",
 87)
 88
 89_WithImageSuffix = WithSuffix(VALID_COVER_IMAGE_EXTENSIONS, case_sensitive=False)
 90CoverImageSource = Annotated[
 91    Union[AbsoluteFilePath, RelativeFilePath, HttpUrl],
 92    Field(union_mode="left_to_right"),
 93    _WithImageSuffix,
 94    include_in_package_serializer,
 95]
 96
 97
 98class AttachmentsDescr(Node):
 99    model_config = {**Node.model_config, "extra": "allow"}
100    """update pydantic model config to allow additional unknown keys"""
101    files: List[ImportantFileSource] = Field(default_factory=list)
102    """∈📦 File attachments"""
103
104
105def _remove_slashes(s: str):
106    return s.replace("/", "").replace("\\", "")
107
108
109class Uploader(Node):
110    email: EmailStr
111    """Email"""
112    name: Optional[Annotated[str, AfterValidator(_remove_slashes)]] = None
113    """name"""
114
115
116class _Person(Node):
117    affiliation: Optional[str] = None
118    """Affiliation"""
119
120    email: Optional[EmailStr] = None
121    """Email"""
122
123    orcid: Annotated[Optional[OrcidId], Field(examples=["0000-0001-2345-6789"])] = None
124    """An [ORCID iD](https://support.orcid.org/hc/en-us/sections/360001495313-What-is-ORCID
125    ) in hyphenated groups of 4 digits, (and [valid](
126    https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier
127    ) as per ISO 7064 11,2.)
128    """
129
130
131class Author(_Person):
132    name: Annotated[str, AfterValidator(_remove_slashes)]
133    github_user: Optional[str] = None  # TODO: validate github_user
134
135
136class Maintainer(_Person):
137    name: Optional[Annotated[str, AfterValidator(_remove_slashes)]] = None
138    github_user: str
139
140
141class BadgeDescr(Node):
142    """A custom badge"""
143
144    label: Annotated[str, Field(examples=["Open in Colab"])]
145    """badge label to display on hover"""
146
147    icon: Annotated[
148        Optional[InPackageIfLocalFileSource],
149        Field(examples=["https://colab.research.google.com/assets/colab-badge.svg"]),
150    ] = None
151    """badge icon"""
152
153    url: Annotated[
154        HttpUrl,
155        Field(
156            examples=[
157                "https://colab.research.google.com/github/HenriquesLab/ZeroCostDL4Mic/blob/master/Colab_notebooks/U-net_2D_ZeroCostDL4Mic.ipynb"
158            ]
159        ),
160    ]
161    """target URL"""
162
163
164class CiteEntry(Node):
165    text: str
166    """free text description"""
167
168    doi: Optional[Doi] = None
169    """A digital object identifier (DOI) is the prefered citation reference.
170    See https://www.doi.org/ for details. (alternatively specify `url`)"""
171
172    @field_validator("doi", mode="before")
173    @classmethod
174    def accept_prefixed_doi(cls, doi: Any) -> Any:
175        if isinstance(doi, str):
176            for doi_prefix in ("https://doi.org/", "http://dx.doi.org/"):
177                if doi.startswith(doi_prefix):
178                    doi = doi[len(doi_prefix) :]
179                    break
180
181        return doi
182
183    url: Optional[str] = None
184    """URL to cite (preferably specify a `doi` instead)"""
185
186    @model_validator(mode="after")
187    def _check_doi_or_url(self) -> Self:
188        if not self.doi and not self.url:
189            raise ValueError("Either 'doi' or 'url' is required")
190
191        return self
192
193
194class LinkedResource(Node):
195    """Reference to a bioimage.io resource"""
196
197    id: ResourceId
198    """A valid resource `id` from the bioimage.io collection."""
199
200    version_number: Optional[int] = None
201    """version number (n-th published version, not the semantic version) of linked resource"""
202
203
204class GenericModelDescrBase(ResourceDescrBase):
205    """Base for all resource descriptions including of model descriptions"""
206
207    name: Annotated[NotEmpty[str], warn(MaxLen(128), "Longer than 128 characters.")]
208    """A human-friendly name of the resource description"""
209
210    description: str
211
212    covers: Annotated[
213        List[CoverImageSource],
214        Field(
215            examples=["cover.png"],
216            description=(
217                "Cover images. Please use an image smaller than 500KB and an aspect"
218                " ratio width to height of 2:1.\nThe supported image formats are:"
219                f" {VALID_COVER_IMAGE_EXTENSIONS}"
220            ),
221        ),
222    ] = Field(
223        default_factory=list,
224    )
225    """∈📦 Cover images. Please use an image smaller than 500KB and an aspect ratio width to height of 2:1."""
226
227    id_emoji: Optional[
228        Annotated[str, Len(min_length=1, max_length=1), Field(examples=["🦈", "🦥"])]
229    ] = None
230    """UTF-8 emoji for display alongside the `id`."""
231
232    authors: List[Author] = Field(default_factory=list)
233    """The authors are the creators of the RDF and the primary points of contact."""
234
235    @field_validator("authors", mode="before")
236    @classmethod
237    def accept_author_strings(cls, authors: Union[Any, Sequence[Any]]) -> Any:
238        """we unofficially accept strings as author entries"""
239        if is_sequence(authors):
240            authors = [{"name": a} if isinstance(a, str) else a for a in authors]
241
242        if not authors:
243            issue_warning("missing", value=authors, field="authors")
244
245        return authors
246
247    attachments: Optional[AttachmentsDescr] = None
248    """file and other attachments"""
249
250    cite: List[CiteEntry] = Field(default_factory=list)
251    """citations"""
252
253    @field_validator("cite", mode="after")
254    @classmethod
255    def _warn_empty_cite(cls, value: Any):
256        if not value:
257            issue_warning("missing", value=value, field="cite")
258
259        return value
260
261    config: Annotated[
262        Dict[str, YamlValue],
263        Field(
264            examples=[
265                dict(
266                    bioimageio={
267                        "my_custom_key": 3837283,
268                        "another_key": {"nested": "value"},
269                    },
270                    imagej={"macro_dir": "path/to/macro/file"},
271                )
272            ],
273        ),
274    ] = Field(default_factory=dict)
275    """A field for custom configuration that can contain any keys not present in the RDF spec.
276    This means you should not store, for example, a github repo URL in `config` since we already have the
277    `git_repo` field defined in the spec.
278    Keys in `config` may be very specific to a tool or consumer software. To avoid conflicting definitions,
279    it is recommended to wrap added configuration into a sub-field named with the specific domain or tool name,
280    for example:
281    ```yaml
282    config:
283        bioimageio:  # here is the domain name
284            my_custom_key: 3837283
285            another_key:
286                nested: value
287        imagej:       # config specific to ImageJ
288            macro_dir: path/to/macro/file
289    ```
290    If possible, please use [`snake_case`](https://en.wikipedia.org/wiki/Snake_case) for keys in `config`.
291    You may want to list linked files additionally under `attachments` to include them when packaging a resource
292    (packaging a resource means downloading/copying important linked files and creating a ZIP archive that contains
293    an altered rdf.yaml file with local references to the downloaded files)"""
294
295    download_url: Optional[HttpUrl] = None
296    """URL to download the resource from (deprecated)"""
297
298    git_repo: Annotated[
299        Optional[str],
300        Field(
301            examples=[
302                "https://github.com/bioimage-io/spec-bioimage-io/tree/main/example_descriptions/models/unet2d_nuclei_broad"
303            ],
304        ),
305    ] = None
306    """A URL to the Git repository where the resource is being developed."""
307
308    icon: Union[
309        Annotated[str, Len(min_length=1, max_length=2)], ImportantFileSource, None
310    ] = None
311    """An icon for illustration"""
312
313    links: Annotated[
314        List[str],
315        Field(
316            examples=[
317                (
318                    "ilastik/ilastik",
319                    "deepimagej/deepimagej",
320                    "zero/notebook_u-net_3d_zerocostdl4mic",
321                )
322            ],
323        ),
324    ] = Field(default_factory=list)
325    """IDs of other bioimage.io resources"""
326
327    uploader: Optional[Uploader] = None
328    """The person who uploaded the model (e.g. to bioimage.io)"""
329
330    maintainers: List[Maintainer] = Field(default_factory=list)
331    """Maintainers of this resource.
332    If not specified `authors` are maintainers and at least some of them should specify their `github_user` name"""
333
334    rdf_source: Optional[FileSource] = None
335    """Resource description file (RDF) source; used to keep track of where an rdf.yaml was loaded from.
336    Do not set this field in a YAML file."""
337
338    tags: Annotated[
339        List[str],
340        Field(examples=[("unet2d", "pytorch", "nucleus", "segmentation", "dsb2018")]),
341    ] = Field(default_factory=list)
342    """Associated tags"""
343
344    @as_warning
345    @field_validator("tags")
346    @classmethod
347    def warn_about_tag_categories(
348        cls, value: List[str], info: ValidationInfo
349    ) -> List[str]:
350        categories = TAG_CATEGORIES.get(info.data["type"], {})
351        missing_categories: List[Mapping[str, Sequence[str]]] = []
352        for cat, entries in categories.items():
353            if not any(e in value for e in entries):
354                missing_categories.append({cat: entries})
355
356        if missing_categories:
357            raise ValueError(
358                "Missing tags from bioimage.io categories: {missing_categories}"
359            )
360
361        return value
362
363    version: Optional[Version] = None
364    """The version of the resource following SemVer 2.0."""
365
366    version_number: Optional[int] = None
367    """version number (n-th published version, not the semantic version)"""
368
369
370class GenericDescrBase(GenericModelDescrBase):
371    """Base for all resource descriptions except for the model descriptions"""
372
373    implemented_format_version: ClassVar[Literal["0.2.4"]] = "0.2.4"
374    if TYPE_CHECKING:
375        format_version: Literal["0.2.4"] = "0.2.4"
376    else:
377        format_version: Literal["0.2.4"]
378        """The format version of this resource specification
379        (not the `version` of the resource description)
380        When creating a new resource always use the latest micro/patch version described here.
381        The `format_version` is important for any consumer software to understand how to parse the fields.
382        """
383
384    @model_validator(mode="before")
385    @classmethod
386    def _convert_from_older_format(
387        cls, data: BioimageioYamlContent, /
388    ) -> BioimageioYamlContent:
389        _convert_from_older_format(data)
390        return data
391
392    badges: List[BadgeDescr] = Field(default_factory=list)
393    """badges associated with this resource"""
394
395    documentation: Annotated[
396        Optional[ImportantFileSource],
397        Field(
398            examples=[
399                "https://raw.githubusercontent.com/bioimage-io/spec-bioimage-io/main/example_descriptions/models/unet2d_nuclei_broad/README.md",
400                "README.md",
401            ],
402        ),
403    ] = None
404    """∈📦 URL or relative path to a markdown file with additional documentation.
405    The recommended documentation file name is `README.md`. An `.md` suffix is mandatory."""
406
407    license: Annotated[
408        Union[LicenseId, DeprecatedLicenseId, str, None],
409        Field(union_mode="left_to_right", examples=["CC0-1.0", "MIT", "BSD-2-Clause"]),
410    ] = None
411    """A [SPDX license identifier](https://spdx.org/licenses/).
412    We do not support custom license beyond the SPDX license list, if you need that please
413    [open a GitHub issue](https://github.com/bioimage-io/spec-bioimage-io/issues/new/choose
414    ) to discuss your intentions with the community."""
415
416    @field_validator("license", mode="after")
417    @classmethod
418    def deprecated_spdx_license(
419        cls, value: Optional[Union[LicenseId, DeprecatedLicenseId, str]]
420    ):
421        if isinstance(value, LicenseId):
422            pass
423        elif value is None:
424            issue_warning("missing", value=value, field="license")
425        elif isinstance(value, DeprecatedLicenseId):
426            issue_warning(
427                "'{value}' is a deprecated license identifier.",
428                value=value,
429                field="license",
430            )
431        elif isinstance(value, str):
432            issue_warning(
433                "'{value}' is an unknown license identifier.",
434                value=value,
435                field="license",
436            )
437        else:
438            assert_never(value)
439
440        return value
441
442
443ResourceDescrType = TypeVar("ResourceDescrType", bound=GenericDescrBase)
444
445
446class GenericDescr(GenericDescrBase, extra="ignore"):
447    """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).
448
449    An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook.
450    Note that those resources are described with a type-specific RDF.
451    Use this generic resource description, if none of the known specific types matches your resource.
452    """
453
454    type: Annotated[str, LowerCase, Field(frozen=True)] = "generic"
455    """The resource type assigns a broad category to the resource."""
456
457    id: Optional[
458        Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])]
459    ] = None
460    """bioimage.io-wide unique resource identifier
461    assigned by bioimage.io; version **un**specific."""
462
463    source: Optional[HttpUrl] = None
464    """The primary source of the resource"""
465
466    @field_validator("type", mode="after")
467    @classmethod
468    def check_specific_types(cls, value: str) -> str:
469        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
470            raise ValueError(
471                f"Use the {value} description instead of this generic description for"
472                + f" your '{value}' resource."
473            )
474
475        return value
class ResourceId(bioimageio.spec._internal.validated_string.ValidatedString):
59class ResourceId(ValidatedString):
60    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
61        Annotated[
62            NotEmpty[str],
63            AfterValidator(str.lower),  # convert upper case on the fly
64            RestrictCharacters(string.ascii_lowercase + string.digits + "_-/."),
65            annotated_types.Predicate(
66                lambda s: not (s.startswith("/") or s.endswith("/"))
67            ),
68        ]
69    ]

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, AfterValidator, RestrictCharacters, Predicate]]'>

the pydantic root model to validate the string

KNOWN_SPECIFIC_RESOURCE_TYPES = ('application', 'collection', 'dataset', 'model', 'notebook')
VALID_COVER_IMAGE_EXTENSIONS = ('.gif', '.jpeg', '.jpg', '.png', '.svg', '.tif', '.tiff')
CoverImageSource = typing.Annotated[typing.Union[typing.Annotated[pathlib.Path, PathType(path_type='file'), Predicate(is_absolute), FieldInfo(annotation=NoneType, required=True, title='AbsoluteFilePath')], bioimageio.spec._internal.io.RelativeFilePath, bioimageio.spec._internal.url.HttpUrl], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')]), WithSuffix(suffix=('.gif', '.jpeg', '.jpg', '.png', '.svg', '.tif', '.tiff'), case_sensitive=False), PlainSerializer(func=<function _package>, return_type=PydanticUndefined, when_used='unless-none')]
class AttachmentsDescr(bioimageio.spec._internal.node.Node):
 99class AttachmentsDescr(Node):
100    model_config = {**Node.model_config, "extra": "allow"}
101    """update pydantic model config to allow additional unknown keys"""
102    files: List[ImportantFileSource] = Field(default_factory=list)
103    """∈📦 File attachments"""
model_config = {'extra': 'allow', 'frozen': False, 'populate_by_name': True, 'revalidate_instances': 'never', 'validate_assignment': True, 'validate_default': False, 'validate_return': True, 'use_attribute_docstrings': True, 'model_title_generator': <function _node_title_generator>}

update pydantic model config to allow additional unknown keys

files: List[Annotated[Union[bioimageio.spec._internal.url.HttpUrl, bioimageio.spec._internal.io.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 attachments

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

class Author(_Person):
132class Author(_Person):
133    name: Annotated[str, AfterValidator(_remove_slashes)]
134    github_user: Optional[str] = None  # TODO: validate github_user
name: Annotated[str, AfterValidator(func=<function _remove_slashes at 0x7f260131f9c0>)]
github_user: Optional[str]
Inherited Members
_Person
affiliation
email
orcid
class Maintainer(_Person):
137class Maintainer(_Person):
138    name: Optional[Annotated[str, AfterValidator(_remove_slashes)]] = None
139    github_user: str
name: Optional[Annotated[str, AfterValidator(func=<function _remove_slashes at 0x7f260131f9c0>)]]
github_user: str
Inherited Members
_Person
affiliation
email
orcid
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')], bioimageio.spec._internal.io.RelativeFilePath], AfterValidator(func=<function wo_special_file_name at 0x7f2602536ca0>), PlainSerializer(func=<function _package at 0x7f2602535e40>, return_type=PydanticUndefined, when_used='unless-none')], bioimageio.spec._internal.url.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[bioimageio.spec._internal.url.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):
165class CiteEntry(Node):
166    text: str
167    """free text description"""
168
169    doi: Optional[Doi] = None
170    """A digital object identifier (DOI) is the prefered citation reference.
171    See https://www.doi.org/ for details. (alternatively specify `url`)"""
172
173    @field_validator("doi", mode="before")
174    @classmethod
175    def accept_prefixed_doi(cls, doi: Any) -> Any:
176        if isinstance(doi, str):
177            for doi_prefix in ("https://doi.org/", "http://dx.doi.org/"):
178                if doi.startswith(doi_prefix):
179                    doi = doi[len(doi_prefix) :]
180                    break
181
182        return doi
183
184    url: Optional[str] = None
185    """URL to cite (preferably specify a `doi` instead)"""
186
187    @model_validator(mode="after")
188    def _check_doi_or_url(self) -> Self:
189        if not self.doi and not self.url:
190            raise ValueError("Either 'doi' or 'url' is required")
191
192        return self
text: str

free text description

doi: Optional[bioimageio.spec._internal.types.Doi]

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

@field_validator('doi', mode='before')
@classmethod
def accept_prefixed_doi(cls, doi: Any) -> Any:
173    @field_validator("doi", mode="before")
174    @classmethod
175    def accept_prefixed_doi(cls, doi: Any) -> Any:
176        if isinstance(doi, str):
177            for doi_prefix in ("https://doi.org/", "http://dx.doi.org/"):
178                if doi.startswith(doi_prefix):
179                    doi = doi[len(doi_prefix) :]
180                    break
181
182        return doi
url: Optional[str]

URL to cite (preferably specify a doi instead)

class LinkedResource(bioimageio.spec._internal.node.Node):
195class LinkedResource(Node):
196    """Reference to a bioimage.io resource"""
197
198    id: ResourceId
199    """A valid resource `id` from the bioimage.io collection."""
200
201    version_number: Optional[int] = None
202    """version number (n-th published version, not the semantic version) of linked resource"""

Reference to a bioimage.io resource

A valid resource id from the bioimage.io collection.

version_number: Optional[int]

version number (n-th published version, not the semantic version) of linked resource

class GenericModelDescrBase(bioimageio.spec._internal.common_nodes.ResourceDescrBase):
205class GenericModelDescrBase(ResourceDescrBase):
206    """Base for all resource descriptions including of model descriptions"""
207
208    name: Annotated[NotEmpty[str], warn(MaxLen(128), "Longer than 128 characters.")]
209    """A human-friendly name of the resource description"""
210
211    description: str
212
213    covers: Annotated[
214        List[CoverImageSource],
215        Field(
216            examples=["cover.png"],
217            description=(
218                "Cover images. Please use an image smaller than 500KB and an aspect"
219                " ratio width to height of 2:1.\nThe supported image formats are:"
220                f" {VALID_COVER_IMAGE_EXTENSIONS}"
221            ),
222        ),
223    ] = Field(
224        default_factory=list,
225    )
226    """∈📦 Cover images. Please use an image smaller than 500KB and an aspect ratio width to height of 2:1."""
227
228    id_emoji: Optional[
229        Annotated[str, Len(min_length=1, max_length=1), Field(examples=["🦈", "🦥"])]
230    ] = None
231    """UTF-8 emoji for display alongside the `id`."""
232
233    authors: List[Author] = Field(default_factory=list)
234    """The authors are the creators of the RDF and the primary points of contact."""
235
236    @field_validator("authors", mode="before")
237    @classmethod
238    def accept_author_strings(cls, authors: Union[Any, Sequence[Any]]) -> Any:
239        """we unofficially accept strings as author entries"""
240        if is_sequence(authors):
241            authors = [{"name": a} if isinstance(a, str) else a for a in authors]
242
243        if not authors:
244            issue_warning("missing", value=authors, field="authors")
245
246        return authors
247
248    attachments: Optional[AttachmentsDescr] = None
249    """file and other attachments"""
250
251    cite: List[CiteEntry] = Field(default_factory=list)
252    """citations"""
253
254    @field_validator("cite", mode="after")
255    @classmethod
256    def _warn_empty_cite(cls, value: Any):
257        if not value:
258            issue_warning("missing", value=value, field="cite")
259
260        return value
261
262    config: Annotated[
263        Dict[str, YamlValue],
264        Field(
265            examples=[
266                dict(
267                    bioimageio={
268                        "my_custom_key": 3837283,
269                        "another_key": {"nested": "value"},
270                    },
271                    imagej={"macro_dir": "path/to/macro/file"},
272                )
273            ],
274        ),
275    ] = Field(default_factory=dict)
276    """A field for custom configuration that can contain any keys not present in the RDF spec.
277    This means you should not store, for example, a github repo URL in `config` since we already have the
278    `git_repo` field defined in the spec.
279    Keys in `config` may be very specific to a tool or consumer software. To avoid conflicting definitions,
280    it is recommended to wrap added configuration into a sub-field named with the specific domain or tool name,
281    for example:
282    ```yaml
283    config:
284        bioimageio:  # here is the domain name
285            my_custom_key: 3837283
286            another_key:
287                nested: value
288        imagej:       # config specific to ImageJ
289            macro_dir: path/to/macro/file
290    ```
291    If possible, please use [`snake_case`](https://en.wikipedia.org/wiki/Snake_case) for keys in `config`.
292    You may want to list linked files additionally under `attachments` to include them when packaging a resource
293    (packaging a resource means downloading/copying important linked files and creating a ZIP archive that contains
294    an altered rdf.yaml file with local references to the downloaded files)"""
295
296    download_url: Optional[HttpUrl] = None
297    """URL to download the resource from (deprecated)"""
298
299    git_repo: Annotated[
300        Optional[str],
301        Field(
302            examples=[
303                "https://github.com/bioimage-io/spec-bioimage-io/tree/main/example_descriptions/models/unet2d_nuclei_broad"
304            ],
305        ),
306    ] = None
307    """A URL to the Git repository where the resource is being developed."""
308
309    icon: Union[
310        Annotated[str, Len(min_length=1, max_length=2)], ImportantFileSource, None
311    ] = None
312    """An icon for illustration"""
313
314    links: Annotated[
315        List[str],
316        Field(
317            examples=[
318                (
319                    "ilastik/ilastik",
320                    "deepimagej/deepimagej",
321                    "zero/notebook_u-net_3d_zerocostdl4mic",
322                )
323            ],
324        ),
325    ] = Field(default_factory=list)
326    """IDs of other bioimage.io resources"""
327
328    uploader: Optional[Uploader] = None
329    """The person who uploaded the model (e.g. to bioimage.io)"""
330
331    maintainers: List[Maintainer] = Field(default_factory=list)
332    """Maintainers of this resource.
333    If not specified `authors` are maintainers and at least some of them should specify their `github_user` name"""
334
335    rdf_source: Optional[FileSource] = None
336    """Resource description file (RDF) source; used to keep track of where an rdf.yaml was loaded from.
337    Do not set this field in a YAML file."""
338
339    tags: Annotated[
340        List[str],
341        Field(examples=[("unet2d", "pytorch", "nucleus", "segmentation", "dsb2018")]),
342    ] = Field(default_factory=list)
343    """Associated tags"""
344
345    @as_warning
346    @field_validator("tags")
347    @classmethod
348    def warn_about_tag_categories(
349        cls, value: List[str], info: ValidationInfo
350    ) -> List[str]:
351        categories = TAG_CATEGORIES.get(info.data["type"], {})
352        missing_categories: List[Mapping[str, Sequence[str]]] = []
353        for cat, entries in categories.items():
354            if not any(e in value for e in entries):
355                missing_categories.append({cat: entries})
356
357        if missing_categories:
358            raise ValueError(
359                "Missing tags from bioimage.io categories: {missing_categories}"
360            )
361
362        return value
363
364    version: Optional[Version] = None
365    """The version of the resource following SemVer 2.0."""
366
367    version_number: Optional[int] = None
368    """version number (n-th published version, not the semantic version)"""

Base for all resource descriptions including of model descriptions

name: Annotated[str, MinLen(min_length=1), AfterWarner(func=<function as_warning.<locals>.wrapper at 0x7f26013cb6a0>, severity=30, msg='Longer than 128 characters.', context={'typ': Annotated[Any, MaxLen(max_length=128)]})]

A human-friendly name of the resource description

description: str
covers: Annotated[List[Annotated[Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(is_absolute), FieldInfo(annotation=NoneType, required=True, title='AbsoluteFilePath')], bioimageio.spec._internal.io.RelativeFilePath, bioimageio.spec._internal.url.HttpUrl], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')]), WithSuffix(suffix=('.gif', '.jpeg', '.jpg', '.png', '.svg', '.tif', '.tiff'), case_sensitive=False), PlainSerializer(func=<function _package at 0x7f2602535e40>, return_type=PydanticUndefined, when_used='unless-none')]], FieldInfo(annotation=NoneType, required=True, description="Cover images. Please use an image smaller than 500KB and an aspect ratio width to height of 2:1.\nThe supported image formats are: ('.gif', '.jpeg', '.jpg', '.png', '.svg', '.tif', '.tiff')", examples=['cover.png'])]

∈📦 Cover images. Please use an image smaller than 500KB and an aspect ratio width to height of 2:1.

id_emoji: Optional[Annotated[str, Len(min_length=1, max_length=1), FieldInfo(annotation=NoneType, required=True, examples=['🦈', '🦥'])]]

UTF-8 emoji for display alongside the id.

authors: List[Author]

The authors are the creators of the RDF and the primary points of contact.

@field_validator('authors', mode='before')
@classmethod
def accept_author_strings(cls, authors: Union[Any, Sequence[Any]]) -> Any:
236    @field_validator("authors", mode="before")
237    @classmethod
238    def accept_author_strings(cls, authors: Union[Any, Sequence[Any]]) -> Any:
239        """we unofficially accept strings as author entries"""
240        if is_sequence(authors):
241            authors = [{"name": a} if isinstance(a, str) else a for a in authors]
242
243        if not authors:
244            issue_warning("missing", value=authors, field="authors")
245
246        return authors

we unofficially accept strings as author entries

attachments: Optional[AttachmentsDescr]

file and other attachments

cite: List[CiteEntry]

citations

config: Annotated[Dict[str, YamlValue], FieldInfo(annotation=NoneType, required=True, examples=[{'bioimageio': {'my_custom_key': 3837283, 'another_key': {'nested': 'value'}}, 'imagej': {'macro_dir': 'path/to/macro/file'}}])]

A field for custom configuration that can contain any keys not present in the RDF spec. This means you should not store, for example, a github repo URL in config since we already have the git_repo field defined in the spec. Keys in config may be very specific to a tool or consumer software. To avoid conflicting definitions, it is recommended to wrap added configuration into a sub-field named with the specific domain or tool name, for example:

config:
    bioimageio:  # here is the domain name
        my_custom_key: 3837283
        another_key:
            nested: value
    imagej:       # config specific to ImageJ
        macro_dir: path/to/macro/file

If possible, please use snake_case for keys in config. You may want to list linked files additionally under attachments to include them when packaging a resource (packaging a resource means downloading/copying important linked files and creating a ZIP archive that contains an altered rdf.yaml file with local references to the downloaded files)

download_url: Optional[bioimageio.spec._internal.url.HttpUrl]

URL to download the resource from (deprecated)

git_repo: Annotated[Optional[str], FieldInfo(annotation=NoneType, required=True, examples=['https://github.com/bioimage-io/spec-bioimage-io/tree/main/example_descriptions/models/unet2d_nuclei_broad'])]

A URL to the Git repository where the resource is being developed.

icon: Union[Annotated[str, Len(min_length=1, max_length=2)], Annotated[Union[bioimageio.spec._internal.url.HttpUrl, bioimageio.spec._internal.io.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')], NoneType]

An icon for illustration

uploader: Optional[Uploader]

The person who uploaded the model (e.g. to bioimage.io)

maintainers: List[Maintainer]

Maintainers of this resource. If not specified authors are maintainers and at least some of them should specify their github_user name

rdf_source: Optional[Annotated[Union[bioimageio.spec._internal.url.HttpUrl, bioimageio.spec._internal.io.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')])]]

Resource description file (RDF) source; used to keep track of where an rdf.yaml was loaded from. Do not set this field in a YAML file.

tags: Annotated[List[str], FieldInfo(annotation=NoneType, required=True, examples=[('unet2d', 'pytorch', 'nucleus', 'segmentation', 'dsb2018')])]

Associated tags

def warn_about_tag_categories(value: Any, info: pydantic_core.core_schema.ValidationInfo) -> Any:
75    def wrapper(value: Any, info: ValidationInfo) -> Any:
76        try:
77            call_validator_func(func, mode, value, info)
78        except (AssertionError, ValueError) as e:
79            issue_warning(
80                msg or ",".join(e.args),
81                value=value,
82                severity=severity,
83                msg_context=msg_context,
84            )
85
86        return value
version: Optional[bioimageio.spec._internal.version_type.Version]

The version of the resource following SemVer 2.0.

version_number: Optional[int]

version number (n-th published version, not the semantic version)

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 GenericDescrBase(GenericModelDescrBase):
371class GenericDescrBase(GenericModelDescrBase):
372    """Base for all resource descriptions except for the model descriptions"""
373
374    implemented_format_version: ClassVar[Literal["0.2.4"]] = "0.2.4"
375    if TYPE_CHECKING:
376        format_version: Literal["0.2.4"] = "0.2.4"
377    else:
378        format_version: Literal["0.2.4"]
379        """The format version of this resource specification
380        (not the `version` of the resource description)
381        When creating a new resource always use the latest micro/patch version described here.
382        The `format_version` is important for any consumer software to understand how to parse the fields.
383        """
384
385    @model_validator(mode="before")
386    @classmethod
387    def _convert_from_older_format(
388        cls, data: BioimageioYamlContent, /
389    ) -> BioimageioYamlContent:
390        _convert_from_older_format(data)
391        return data
392
393    badges: List[BadgeDescr] = Field(default_factory=list)
394    """badges associated with this resource"""
395
396    documentation: Annotated[
397        Optional[ImportantFileSource],
398        Field(
399            examples=[
400                "https://raw.githubusercontent.com/bioimage-io/spec-bioimage-io/main/example_descriptions/models/unet2d_nuclei_broad/README.md",
401                "README.md",
402            ],
403        ),
404    ] = None
405    """∈📦 URL or relative path to a markdown file with additional documentation.
406    The recommended documentation file name is `README.md`. An `.md` suffix is mandatory."""
407
408    license: Annotated[
409        Union[LicenseId, DeprecatedLicenseId, str, None],
410        Field(union_mode="left_to_right", examples=["CC0-1.0", "MIT", "BSD-2-Clause"]),
411    ] = None
412    """A [SPDX license identifier](https://spdx.org/licenses/).
413    We do not support custom license beyond the SPDX license list, if you need that please
414    [open a GitHub issue](https://github.com/bioimage-io/spec-bioimage-io/issues/new/choose
415    ) to discuss your intentions with the community."""
416
417    @field_validator("license", mode="after")
418    @classmethod
419    def deprecated_spdx_license(
420        cls, value: Optional[Union[LicenseId, DeprecatedLicenseId, str]]
421    ):
422        if isinstance(value, LicenseId):
423            pass
424        elif value is None:
425            issue_warning("missing", value=value, field="license")
426        elif isinstance(value, DeprecatedLicenseId):
427            issue_warning(
428                "'{value}' is a deprecated license identifier.",
429                value=value,
430                field="license",
431            )
432        elif isinstance(value, str):
433            issue_warning(
434                "'{value}' is an unknown license identifier.",
435                value=value,
436                field="license",
437            )
438        else:
439            assert_never(value)
440
441        return value

Base for all resource descriptions except for the model descriptions

implemented_format_version: ClassVar[Literal['0.2.4']] = '0.2.4'
badges: List[BadgeDescr]

badges associated with this resource

documentation: Annotated[Optional[Annotated[Union[bioimageio.spec._internal.url.HttpUrl, bioimageio.spec._internal.io.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')]], FieldInfo(annotation=NoneType, required=True, examples=['https://raw.githubusercontent.com/bioimage-io/spec-bioimage-io/main/example_descriptions/models/unet2d_nuclei_broad/README.md', 'README.md'])]

∈📦 URL or relative path to a markdown file with additional documentation. The recommended documentation file name is README.md. An .md suffix is mandatory.

license: Annotated[Union[bioimageio.spec._internal.license_id.LicenseId, bioimageio.spec._internal.license_id.DeprecatedLicenseId, str, NoneType], FieldInfo(annotation=NoneType, required=True, examples=['CC0-1.0', 'MIT', 'BSD-2-Clause'], metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])]

A SPDX license identifier. We do not support custom license beyond the SPDX license list, if you need that please open a GitHub issue to discuss your intentions with the community.

@field_validator('license', mode='after')
@classmethod
def deprecated_spdx_license( cls, value: Union[bioimageio.spec._internal.license_id.LicenseId, bioimageio.spec._internal.license_id.DeprecatedLicenseId, str, NoneType]):
417    @field_validator("license", mode="after")
418    @classmethod
419    def deprecated_spdx_license(
420        cls, value: Optional[Union[LicenseId, DeprecatedLicenseId, str]]
421    ):
422        if isinstance(value, LicenseId):
423            pass
424        elif value is None:
425            issue_warning("missing", value=value, field="license")
426        elif isinstance(value, DeprecatedLicenseId):
427            issue_warning(
428                "'{value}' is a deprecated license identifier.",
429                value=value,
430                field="license",
431            )
432        elif isinstance(value, str):
433            issue_warning(
434                "'{value}' is an unknown license identifier.",
435                value=value,
436                field="license",
437            )
438        else:
439            assert_never(value)
440
441        return value
implemented_format_version_tuple: ClassVar[Tuple[int, int, int]] = (0, 2, 4)
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 GenericDescr(GenericDescrBase):
447class GenericDescr(GenericDescrBase, extra="ignore"):
448    """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).
449
450    An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook.
451    Note that those resources are described with a type-specific RDF.
452    Use this generic resource description, if none of the known specific types matches your resource.
453    """
454
455    type: Annotated[str, LowerCase, Field(frozen=True)] = "generic"
456    """The resource type assigns a broad category to the resource."""
457
458    id: Optional[
459        Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])]
460    ] = None
461    """bioimage.io-wide unique resource identifier
462    assigned by bioimage.io; version **un**specific."""
463
464    source: Optional[HttpUrl] = None
465    """The primary source of the resource"""
466
467    @field_validator("type", mode="after")
468    @classmethod
469    def check_specific_types(cls, value: str) -> str:
470        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
471            raise ValueError(
472                f"Use the {value} description instead of this generic description for"
473                + f" your '{value}' resource."
474            )
475
476        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)], FieldInfo(annotation=NoneType, required=True, frozen=True)]

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.

source: Optional[bioimageio.spec._internal.url.HttpUrl]

The primary source of the resource

@field_validator('type', mode='after')
@classmethod
def check_specific_types(cls, value: str) -> str:
467    @field_validator("type", mode="after")
468    @classmethod
469    def check_specific_types(cls, value: str) -> str:
470        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
471            raise ValueError(
472                f"Use the {value} description instead of this generic description for"
473                + f" your '{value}' resource."
474            )
475
476        return value
implemented_format_version_tuple: ClassVar[Tuple[int, int, int]] = (0, 2, 4)
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.