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

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class BadgeDescr(bioimageio.spec._internal.node.Node):
145class BadgeDescr(Node):
146    """A custom badge"""
147
148    label: Annotated[str, Field(examples=["Open in Colab"])]
149    """badge label to display on hover"""
150
151    icon: Annotated[
152        Optional[
153            Union[
154                Annotated[
155                    Union[FilePath, RelativeFilePath],
156                    AfterValidator(wo_special_file_name),
157                    include_in_package,
158                ],
159                Union[HttpUrl, pydantic.HttpUrl],
160            ]
161        ],
162        Field(examples=["https://colab.research.google.com/assets/colab-badge.svg"]),
163    ] = None
164    """badge icon (included in bioimage.io package if not a URL)"""
165
166    url: Annotated[
167        HttpUrl,
168        Field(
169            examples=[
170                "https://colab.research.google.com/github/HenriquesLab/ZeroCostDL4Mic/blob/master/Colab_notebooks/U-net_2D_ZeroCostDL4Mic.ipynb"
171            ]
172        ),
173    ]
174    """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 0x7ff2e362f920>), PlainSerializer(func=<function _package_serializer at 0x7ff2e33298a0>, return_type=PydanticUndefined, when_used='unless-none')], HttpUrl, pydantic.networks.HttpUrl, NoneType], FieldInfo(annotation=NoneType, required=True, examples=['https://colab.research.google.com/assets/colab-badge.svg'])]

badge icon (included in bioimage.io package if not a URL)

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

model_config: ClassVar[pydantic.config.ConfigDict] = {'extra': 'forbid', '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>, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class CiteEntry(bioimageio.spec._internal.node.Node):
164class CiteEntry(Node):
165    """A citation that should be referenced in work using this resource."""
166
167    text: str
168    """free text description"""
169
170    doi: Optional[Doi] = None
171    """A digital object identifier (DOI) is the prefered citation reference.
172    See https://www.doi.org/ for details.
173    Note:
174        Either **doi** or **url** have to be specified.
175    """
176
177    url: Optional[HttpUrl] = None
178    """URL to cite (preferably specify a **doi** instead/also).
179    Note:
180        Either **doi** or **url** have to be specified.
181    """
182
183    @model_validator(mode="after")
184    def _check_doi_or_url(self):
185        if not self.doi and not self.url:
186            raise ValueError("Either 'doi' or 'url' is required")
187
188        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.

model_config: ClassVar[pydantic.config.ConfigDict] = {'extra': 'forbid', '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>, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

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):
120class Doi(ValidatedString):
121    """A digital object identifier, see https://www.doi.org/"""
122
123    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
124        Annotated[str, StringConstraints(pattern=DOI_REGEX)]
125    ]

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):
255class FileDescr(Node):
256    """A file description"""
257
258    source: FileSource
259    """File source"""
260
261    sha256: Optional[Sha256] = None
262    """SHA256 hash value of the **source** file."""
263
264    @model_validator(mode="after")
265    def _validate_sha256(self) -> Self:
266        if get_validation_context().perform_io_checks:
267            self.validate_sha256()
268
269        return self
270
271    def validate_sha256(self, force_recompute: bool = False) -> None:
272        """validate the sha256 hash value of the **source** file"""
273        context = get_validation_context()
274        src_str = str(self.source)
275        if not force_recompute and src_str in context.known_files:
276            actual_sha = context.known_files[src_str]
277        else:
278            reader = get_reader(self.source, sha256=self.sha256)
279            if force_recompute:
280                actual_sha = get_sha256(reader)
281            else:
282                actual_sha = reader.sha256
283
284            context.known_files[src_str] = actual_sha
285
286        if actual_sha is None:
287            return
288        elif self.sha256 == actual_sha:
289            pass
290        elif self.sha256 is None or context.update_hashes:
291            self.sha256 = actual_sha
292        elif self.sha256 != actual_sha:
293            raise ValueError(
294                f"Sha256 mismatch for {self.source}. Expected {self.sha256}, got "
295                + f"{actual_sha}. Update expected `sha256` or point to the matching "
296                + "file."
297            )
298
299    def get_reader(
300        self, *, progressbar: Union[Progressbar, Callable[[], Progressbar], bool] = True
301    ):
302        """open the file source (download if needed)"""
303        return get_reader(self.source, progressbar=progressbar, sha256=self.sha256)
304
305    download = get_reader
306    """alias for get_reader() method"""

A file description

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')])]

File source

sha256: Optional[Sha256]

SHA256 hash value of the source file.

def validate_sha256(self, force_recompute: bool = False) -> None:
271    def validate_sha256(self, force_recompute: bool = False) -> None:
272        """validate the sha256 hash value of the **source** file"""
273        context = get_validation_context()
274        src_str = str(self.source)
275        if not force_recompute and src_str in context.known_files:
276            actual_sha = context.known_files[src_str]
277        else:
278            reader = get_reader(self.source, sha256=self.sha256)
279            if force_recompute:
280                actual_sha = get_sha256(reader)
281            else:
282                actual_sha = reader.sha256
283
284            context.known_files[src_str] = actual_sha
285
286        if actual_sha is None:
287            return
288        elif self.sha256 == actual_sha:
289            pass
290        elif self.sha256 is None or context.update_hashes:
291            self.sha256 = actual_sha
292        elif self.sha256 != actual_sha:
293            raise ValueError(
294                f"Sha256 mismatch for {self.source}. Expected {self.sha256}, got "
295                + f"{actual_sha}. Update expected `sha256` or point to the matching "
296                + "file."
297            )

validate the sha256 hash value of the source file

def get_reader( self, *, progressbar: Union[bioimageio.spec._internal.progress.Progressbar, Callable[[], bioimageio.spec._internal.progress.Progressbar], bool] = True):
299    def get_reader(
300        self, *, progressbar: Union[Progressbar, Callable[[], Progressbar], bool] = True
301    ):
302        """open the file source (download if needed)"""
303        return get_reader(self.source, progressbar=progressbar, sha256=self.sha256)

open the file source (download if needed)

def download( self, *, progressbar: Union[bioimageio.spec._internal.progress.Progressbar, Callable[[], bioimageio.spec._internal.progress.Progressbar], bool] = True):
299    def get_reader(
300        self, *, progressbar: Union[Progressbar, Callable[[], Progressbar], bool] = True
301    ):
302        """open the file source (download if needed)"""
303        return get_reader(self.source, progressbar=progressbar, sha256=self.sha256)

alias for get_reader() method

model_config: ClassVar[pydantic.config.ConfigDict] = {'extra': 'forbid', '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>, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class GenericDescr(GenericDescrBase):
478class GenericDescr(GenericDescrBase, extra="ignore"):
479    """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).
480
481    An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook.
482    Note that those resources are described with a type-specific RDF.
483    Use this generic resource description, if none of the known specific types matches your resource.
484    """
485
486    implemented_type: ClassVar[Literal["generic"]] = "generic"
487    if TYPE_CHECKING:
488        type: Annotated[str, LowerCase] = "generic"
489        """The resource type assigns a broad category to the resource."""
490    else:
491        type: Annotated[str, LowerCase]
492        """The resource type assigns a broad category to the resource."""
493
494    id: Optional[
495        Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])]
496    ] = None
497    """bioimage.io-wide unique resource identifier
498    assigned by bioimage.io; version **un**specific."""
499
500    parent: Optional[ResourceId] = None
501    """The description from which this one is derived"""
502
503    source: Optional[HttpUrl] = None
504    """The primary source of the resource"""
505
506    @field_validator("type", mode="after")
507    @classmethod
508    def check_specific_types(cls, value: str) -> str:
509        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
510            raise ValueError(
511                f"Use the {value} description instead of this generic description for"
512                + f" your '{value}' resource."
513            )
514
515        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.

implemented_type: ClassVar[Literal['generic']] = 'generic'
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:
506    @field_validator("type", mode="after")
507    @classmethod
508    def check_specific_types(cls, value: str) -> str:
509        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
510            raise ValueError(
511                f"Use the {value} description instead of this generic description for"
512                + f" your '{value}' resource."
513            )
514
515        return value
implemented_format_version_tuple: ClassVar[Tuple[int, int, int]] = (0, 3, 0)
model_config: ClassVar[pydantic.config.ConfigDict] = {'extra': 'ignore', '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>, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

def model_post_init(self: pydantic.main.BaseModel, context: Any, /) -> None:
337def init_private_attributes(self: BaseModel, context: Any, /) -> None:
338    """This function is meant to behave like a BaseModel method to initialise private attributes.
339
340    It takes context as an argument since that's what pydantic-core passes when calling it.
341
342    Args:
343        self: The BaseModel instance.
344        context: The context.
345    """
346    if getattr(self, '__pydantic_private__', None) is None:
347        pydantic_private = {}
348        for name, private_attr in self.__private_attributes__.items():
349            default = private_attr.get_default()
350            if default is not PydanticUndefined:
351                pydantic_private[name] = default
352        object_setattr(self, '__pydantic_private__', pydantic_private)

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that's what pydantic-core passes when calling it.

Arguments:
  • self: The BaseModel instance.
  • context: The context.
class HttpUrl(bioimageio.spec._internal.root_url.RootHttpUrl):
124class HttpUrl(RootHttpUrl):
125    """A URL with the HTTP or HTTPS scheme."""
126
127    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[pydantic.HttpUrl]
128    _exists: Optional[bool] = None
129
130    def _after_validator(self):
131        self = super()._after_validator()
132        context = get_validation_context()
133        if context.perform_io_checks:
134            _ = self.exists()
135
136        return self
137
138    def exists(self):
139        """True if URL is available"""
140        if self._exists is None:
141            ctxt = get_validation_context()
142            try:
143                with ctxt.replace(warning_level=warning_levels.WARNING):
144                    self._validated = _validate_url(self._validated)
145            except Exception as e:
146                if ctxt.log_warnings:
147                    logger.info(e)
148
149                self._exists = False
150            else:
151                self._exists = True
152
153        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[HttpUrl]'>

the pydantic root model to validate the string

def exists(self):
138    def exists(self):
139        """True if URL is available"""
140        if self._exists is None:
141            ctxt = get_validation_context()
142            try:
143                with ctxt.replace(warning_level=warning_levels.WARNING):
144                    self._validated = _validate_url(self._validated)
145            except Exception as e:
146                if ctxt.log_warnings:
147                    logger.info(e)
148
149                self._exists = False
150            else:
151                self._exists = True
152
153        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):
206class LinkedResource(LinkedResourceBase):
207    """Reference to a bioimage.io resource"""
208
209    id: ResourceId
210    """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.

model_config: ClassVar[pydantic.config.ConfigDict] = {'extra': 'forbid', '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>, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Inherited Members
LinkedResourceBase
version
class Maintainer(bioimageio.spec.generic.v0_2.Maintainer):
139class Maintainer(_Maintainer_v0_2):
140    name: Optional[Annotated[str, Predicate(_has_no_slash)]] = None
141    github_user: str
142
143    @field_validator("github_user", mode="after")
144    def validate_gh_user(cls, value: str):
145        return validate_gh_user(value)
name: Optional[Annotated[str, Predicate(func=<function _has_no_slash at 0x7ff2e323f7e0>)]]
github_user: str
@field_validator('github_user', mode='after')
def validate_gh_user(cls, value: str):
143    @field_validator("github_user", mode="after")
144    def validate_gh_user(cls, value: str):
145        return validate_gh_user(value)
model_config: ClassVar[pydantic.config.ConfigDict] = {'extra': 'forbid', '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>, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class OrcidId(bioimageio.spec._internal.validated_string.ValidatedString):
147class OrcidId(ValidatedString):
148    """An ORCID identifier, see https://orcid.org/"""
149
150    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
151        Annotated[str, AfterValidator(_validate_orcid_id)]
152    ]

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]):
204class RelativeFilePath(
205    RelativePathBase[Union[AbsoluteFilePath, HttpUrl, ZipPath]], frozen=True
206):
207    """A path relative to the `rdf.yaml` file (also if the RDF source is a URL)."""
208
209    def model_post_init(self, __context: Any) -> None:
210        """add validation @private"""
211        if not self.root.parts:  # an empty path can only be a directory
212            raise ValueError(f"{self.root} is not a valid file path.")
213
214        super().model_post_init(__context)
215
216    def get_absolute(
217        self, root: "RootHttpUrl | Path | AnyUrl | ZipFile"
218    ) -> "AbsoluteFilePath | HttpUrl | ZipPath":
219        absolute = self._get_absolute_impl(root)
220        if (
221            isinstance(absolute, Path)
222            and (context := get_validation_context()).perform_io_checks
223            and str(self.root) not in context.known_files
224            and not absolute.is_file()
225        ):
226            raise ValueError(f"{absolute} does not point to an existing file")
227
228        return absolute

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

def get_absolute( self, root: bioimageio.spec._internal.root_url.RootHttpUrl | pathlib.Path | pydantic.networks.AnyUrl | zipfile.ZipFile) -> Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(is_absolute), FieldInfo(annotation=NoneType, required=True, title='AbsoluteFilePath')], HttpUrl, zipp.Path]:
216    def get_absolute(
217        self, root: "RootHttpUrl | Path | AnyUrl | ZipFile"
218    ) -> "AbsoluteFilePath | HttpUrl | ZipPath":
219        absolute = self._get_absolute_impl(root)
220        if (
221            isinstance(absolute, Path)
222            and (context := get_validation_context()).perform_io_checks
223            and str(self.root) not in context.known_files
224            and not absolute.is_file()
225        ):
226            raise ValueError(f"{absolute} does not point to an existing file")
227
228        return absolute
class ResourceId(bioimageio.spec._internal.validated_string.ValidatedString):
 95class ResourceId(ValidatedString):
 96    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
 97        Annotated[
 98            NotEmpty[str],
 99            RestrictCharacters(string.ascii_lowercase + string.digits + "_-/."),
100            annotated_types.Predicate(
101                lambda s: not (s.startswith("/") or s.endswith("/"))
102            ),
103        ]
104    ]

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):
40class Sha256(ValidatedString):
41    """A SHA-256 hash value"""
42
43    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
44        Annotated[
45            str,
46            StringConstraints(
47                strip_whitespace=True, to_lower=True, min_length=64, max_length=64
48            ),
49        ]
50    ]

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):
113class Uploader(Node):
114    email: EmailStr
115    """Email"""
116    name: Optional[Annotated[str, AfterValidator(_remove_slashes)]] = None
117    """name"""
email: pydantic.networks.EmailStr

Email

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

name

model_config: ClassVar[pydantic.config.ConfigDict] = {'extra': 'forbid', '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>, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

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