bioimageio.spec.generic.v0_3

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

138class Doi(ValidatedString):
139    """A digital object identifier, see https://www.doi.org/"""
140
141    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
142        Annotated[str, StringConstraints(pattern=DOI_REGEX)]
143    ]

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] = {'allow_inf_nan': False, 'extra': 'forbid', 'frozen': False, 'model_title_generator': <function _node_title_generator>, 'populate_by_name': True, 'revalidate_instances': 'always', 'use_attribute_docstrings': True, 'validate_assignment': True, 'validate_default': True, 'validate_return': True, '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):
491class GenericDescr(GenericDescrBase, extra="ignore"):
492    """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).
493
494    An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook.
495    Note that those resources are described with a type-specific RDF.
496    Use this generic resource description, if none of the known specific types matches your resource.
497    """
498
499    implemented_type: ClassVar[Literal["generic"]] = "generic"
500    if TYPE_CHECKING:
501        type: Annotated[str, LowerCase] = "generic"
502        """The resource type assigns a broad category to the resource."""
503    else:
504        type: Annotated[str, LowerCase]
505        """The resource type assigns a broad category to the resource."""
506
507    id: Optional[
508        Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])]
509    ] = None
510    """bioimage.io-wide unique resource identifier
511    assigned by bioimage.io; version **un**specific."""
512
513    parent: Optional[ResourceId] = None
514    """The description from which this one is derived"""
515
516    source: Optional[HttpUrl] = None
517    """The primary source of the resource"""
518
519    @field_validator("type", mode="after")
520    @classmethod
521    def check_specific_types(cls, value: str) -> str:
522        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
523            raise ValueError(
524                f"Use the {value} description instead of this generic description for"
525                + f" your '{value}' resource."
526            )
527
528        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:
519    @field_validator("type", mode="after")
520    @classmethod
521    def check_specific_types(cls, value: str) -> str:
522        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
523            raise ValueError(
524                f"Use the {value} description instead of this generic description for"
525                + f" your '{value}' resource."
526            )
527
528        return value
implemented_format_version_tuple: ClassVar[Tuple[int, int, int]] = (0, 3, 0)
model_config: ClassVar[pydantic.config.ConfigDict] = {'allow_inf_nan': False, 'extra': 'ignore', 'frozen': False, 'model_title_generator': <function _node_title_generator>, 'populate_by_name': True, 'revalidate_instances': 'always', 'use_attribute_docstrings': True, 'validate_assignment': True, 'validate_default': True, 'validate_return': True, '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.
139class HttpUrl(RootHttpUrl):
140    """A URL with the HTTP or HTTPS scheme."""
141
142    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[pydantic.HttpUrl]
143    _exists: Optional[bool] = None
144
145    def _after_validator(self):
146        self = super()._after_validator()
147        context = get_validation_context()
148        if context.perform_io_checks:
149            _ = self.exists()
150
151        return self
152
153    def exists(self):
154        """True if URL is available"""
155        if self._exists is None:
156            ctxt = get_validation_context()
157            try:
158                with ctxt.replace(warning_level=warning_levels.WARNING):
159                    self._validated = _validate_url(self._validated)
160            except Exception as e:
161                if ctxt.log_warnings:
162                    logger.info(e)
163
164                self._exists = False
165            else:
166                self._exists = True
167
168        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):
153    def exists(self):
154        """True if URL is available"""
155        if self._exists is None:
156            ctxt = get_validation_context()
157            try:
158                with ctxt.replace(warning_level=warning_levels.WARNING):
159                    self._validated = _validate_url(self._validated)
160            except Exception as e:
161                if ctxt.log_warnings:
162                    logger.info(e)
163
164                self._exists = False
165            else:
166                self._exists = True
167
168        return self._exists

True if URL is available

KNOWN_SPECIFIC_RESOURCE_TYPES = ('application', 'collection', 'dataset', 'model', 'notebook')
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):
204class LinkedResource(LinkedResourceBase):
205    """Reference to a bioimage.io resource"""
206
207    id: ResourceId
208    """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] = {'allow_inf_nan': False, 'extra': 'forbid', 'frozen': False, 'model_title_generator': <function _node_title_generator>, 'populate_by_name': True, 'revalidate_instances': 'always', 'use_attribute_docstrings': True, 'validate_assignment': True, 'validate_default': True, 'validate_return': True, 'validate_by_alias': True, 'validate_by_name': True}

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

class Maintainer(bioimageio.spec.generic.v0_2.Maintainer):
137class Maintainer(_Maintainer_v0_2):
138    name: Optional[Annotated[str, Predicate(_has_no_slash)]] = None
139    github_user: str
140
141    @field_validator("github_user", mode="after")
142    def validate_github_user(cls, value: str):
143        return validate_github_user(value)
name: Optional[Annotated[str, Predicate(func=<function _has_no_slash at 0x7f83b7b5a0c0>)]]
github_user: str
@field_validator('github_user', mode='after')
def validate_github_user(cls, value: str):
141    @field_validator("github_user", mode="after")
142    def validate_github_user(cls, value: str):
143        return validate_github_user(value)
model_config: ClassVar[pydantic.config.ConfigDict] = {'allow_inf_nan': False, 'extra': 'forbid', 'frozen': False, 'model_title_generator': <function _node_title_generator>, 'populate_by_name': True, 'revalidate_instances': 'always', 'use_attribute_docstrings': True, 'validate_assignment': True, 'validate_default': True, 'validate_return': True, 'validate_by_alias': True, 'validate_by_name': True}

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

165class OrcidId(ValidatedString):
166    """An ORCID identifier, see https://orcid.org/"""
167
168    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
169        Annotated[str, AfterValidator(_validate_orcid_id)]
170    ]

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
 93class ResourceId(ValidatedString):
 94    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
 95        Annotated[
 96            NotEmpty[str],
 97            RestrictCharacters(string.ascii_lowercase + string.digits + "_-/."),
 98            annotated_types.Predicate(
 99                lambda s: not (s.startswith("/") or s.endswith("/"))
100            ),
101        ]
102    ]

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

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

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

the pydantic root model to validate the string

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 0x7f83b7b1de40>)]]

name

model_config: ClassVar[pydantic.config.ConfigDict] = {'allow_inf_nan': False, 'extra': 'forbid', 'frozen': False, 'model_title_generator': <function _node_title_generator>, 'populate_by_name': True, 'revalidate_instances': 'always', 'use_attribute_docstrings': True, 'validate_assignment': True, 'validate_default': True, 'validate_return': True, '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