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    @model_validator(mode="before")
190    def _remove_version_number(cls, value: Any):
191        if is_dict(value):
192            vn = value.pop("version_number", None)
193            if vn is not None and value.get("version") is None:
194                value["version"] = vn
195
196        return value
197
198    version: Optional[Version] = None
199    """The version of the linked resource following SemVer 2.0."""
200
201
202class LinkedResource(LinkedResourceBase):
203    """Reference to a bioimage.io resource"""
204
205    id: ResourceId
206    """A valid resource `id` from the official bioimage.io collection."""
207
208
209class BioimageioConfig(Node, extra="allow"):
210    """bioimage.io internal metadata."""
211
212
213class Config(Node, extra="allow"):
214    """A place to store additional metadata (often tool specific).
215
216    Such additional metadata is typically set programmatically by the respective tool
217    or by people with specific insights into the tool.
218    If you want to store additional metadata that does not match any of the other
219    fields, think of a key unlikely to collide with anyone elses use-case/tool and save
220    it here.
221
222    Please consider creating [an issue in the bioimageio.spec repository](https://github.com/bioimage-io/spec-bioimage-io/issues/new?template=Blank+issue)
223    if you are not sure if an existing field could cover your use case
224    or if you think such a field should exist.
225    """
226
227    bioimageio: BioimageioConfig = Field(default_factory=BioimageioConfig)
228    """bioimage.io internal metadata."""
229
230    @model_validator(mode="after")
231    def _validate_extra_fields(self):
232        if self.model_extra:
233            for k, v in self.model_extra.items():
234                if not isinstance(v, Node) and not is_yaml_value(v):
235                    raise ValueError(
236                        f"config.{k} is not a valid YAML value or `Node` instance"
237                    )
238
239        return self
240
241    def __getitem__(self, key: str) -> Any:
242        """Allows to access the config as a dictionary."""
243        return getattr(self, key)
244
245    def __setitem__(self, key: str, value: Any) -> None:
246        """Allows to set the config as a dictionary."""
247        setattr(self, key, value)
248
249
250class GenericModelDescrBase(ResourceDescrBase):
251    """Base for all resource descriptions including of model descriptions"""
252
253    name: Annotated[
254        Annotated[
255            str, RestrictCharacters(string.ascii_letters + string.digits + "_+- ()")
256        ],
257        MinLen(5),
258        MaxLen(128),
259        warn(MaxLen(64), "Name longer than 64 characters.", INFO),
260    ]
261    """A human-friendly name of the resource description.
262    May only contains letters, digits, underscore, minus, parentheses and spaces."""
263
264    description: FAIR[
265        Annotated[
266            str,
267            MaxLen(1024),
268            warn(MaxLen(512), "Description longer than 512 characters."),
269        ]
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: FAIR[List[Author]] = Field(
290        default_factory=cast(Callable[[], List[Author]], list)
291    )
292    """The authors are the creators of this resource description and the primary points of contact."""
293
294    attachments: List[FileDescr_] = Field(
295        default_factory=cast(Callable[[], List[FileDescr_]], list)
296    )
297    """file attachments"""
298
299    cite: FAIR[List[CiteEntry]] = Field(
300        default_factory=cast(Callable[[], List[CiteEntry]], list)
301    )
302    """citations"""
303
304    license: FAIR[
305        Annotated[
306            Annotated[
307                Union[LicenseId, DeprecatedLicenseId, None],
308                Field(union_mode="left_to_right"),
309            ],
310            warn(
311                Optional[LicenseId],
312                "{value} is deprecated, see https://spdx.org/licenses/{value}.html",
313            ),
314            Field(examples=["CC0-1.0", "MIT", "BSD-2-Clause"]),
315        ]
316    ] = None
317    """A [SPDX license identifier](https://spdx.org/licenses/).
318    We do not support custom license beyond the SPDX license list, if you need that please
319    [open a GitHub issue](https://github.com/bioimage-io/spec-bioimage-io/issues/new/choose)
320    to discuss your intentions with the community."""
321
322    git_repo: Annotated[
323        Optional[HttpUrl],
324        Field(
325            examples=[
326                "https://github.com/bioimage-io/spec-bioimage-io/tree/main/example_descriptions/models/unet2d_nuclei_broad"
327            ],
328        ),
329    ] = None
330    """A URL to the Git repository where the resource is being developed."""
331
332    icon: Union[Annotated[str, Len(min_length=1, max_length=2)], FileSource_, None] = (
333        None
334    )
335    """An icon for illustration, e.g. on bioimage.io"""
336
337    links: Annotated[
338        List[str],
339        Field(
340            examples=[
341                (
342                    "ilastik/ilastik",
343                    "deepimagej/deepimagej",
344                    "zero/notebook_u-net_3d_zerocostdl4mic",
345                )
346            ],
347        ),
348    ] = Field(default_factory=list)
349    """IDs of other bioimage.io resources"""
350
351    uploader: Optional[Uploader] = None
352    """The person who uploaded the model (e.g. to bioimage.io)"""
353
354    maintainers: List[Maintainer] = Field(
355        default_factory=cast(Callable[[], List[Maintainer]], list)
356    )
357    """Maintainers of this resource.
358    If not specified, `authors` are maintainers and at least some of them has to specify their `github_user` name"""
359
360    @model_validator(mode="after")
361    def _check_maintainers_exist(self):
362        if not self.maintainers and self.authors:
363            if all(a.github_user is None for a in self.authors):
364                issue_warning(
365                    "Missing `maintainers` or any author in `authors` with a specified"
366                    + " `github_user` name.",
367                    value=self.authors,
368                    field="authors",
369                    severity=ALERT,
370                )
371
372        return self
373
374    tags: FAIR[
375        Annotated[
376            List[str],
377            Field(
378                examples=[("unet2d", "pytorch", "nucleus", "segmentation", "dsb2018")]
379            ),
380        ]
381    ] = Field(default_factory=list)
382    """Associated tags"""
383
384    @as_warning
385    @field_validator("tags")
386    @classmethod
387    def warn_about_tag_categories(
388        cls, value: List[str], info: ValidationInfo
389    ) -> List[str]:
390        categories = TAG_CATEGORIES.get(info.data["type"], {})
391        missing_categories: List[Dict[str, Sequence[str]]] = []
392        for cat, entries in categories.items():
393            if not any(e in value for e in entries):
394                missing_categories.append({cat: entries})
395
396        if missing_categories:
397            raise ValueError(
398                f"Missing tags from bioimage.io categories: {missing_categories}"
399            )
400
401        return value
402
403    version: Optional[Version] = None
404    """The version of the resource following SemVer 2.0."""
405
406    @model_validator(mode="before")
407    def _remove_version_number(cls, value: Any):
408        if is_dict(value):
409            vn = value.pop("version_number", None)
410            if vn is not None and value.get("version") is None:
411                value["version"] = vn
412
413        return value
414
415    version_comment: Optional[Annotated[str, MaxLen(512)]] = None
416    """A comment on the version of the resource."""
417
418
419FileSource_documentation = Annotated[
420    FileSource_,
421    WithSuffix(".md", case_sensitive=True),
422    Field(
423        examples=[
424            "https://raw.githubusercontent.com/bioimage-io/spec-bioimage-io/main/example_descriptions/models/unet2d_nuclei_broad/README.md",
425            "README.md",
426        ],
427    ),
428]
429
430
431class GenericDescrBase(GenericModelDescrBase):
432    """Base for all resource descriptions except for the model descriptions"""
433
434    implemented_format_version: ClassVar[Literal["0.3.0"]] = "0.3.0"
435    if TYPE_CHECKING:
436        format_version: Literal["0.3.0"] = "0.3.0"
437    else:
438        format_version: Literal["0.3.0"]
439        """The **format** version of this resource specification"""
440
441    @model_validator(mode="before")
442    @classmethod
443    def _convert_from_older_format(
444        cls, data: BioimageioYamlContent, /
445    ) -> BioimageioYamlContent:
446        cls.convert_from_old_format_wo_validation(data)
447        return data
448
449    @classmethod
450    def convert_from_old_format_wo_validation(cls, data: BioimageioYamlContent) -> None:
451        """Convert metadata following an older format version to this classes' format
452        without validating the result.
453        """
454        convert_from_older_format(data)
455
456    documentation: FAIR[Optional[FileSource_documentation]] = None
457    """URL or relative path to a markdown file encoded in UTF-8 with additional documentation.
458    The recommended documentation file name is `README.md`. An `.md` suffix is mandatory."""
459
460    badges: List[BadgeDescr] = Field(  # pyright: ignore[reportUnknownVariableType]
461        default_factory=list
462    )
463    """badges associated with this resource"""
464
465    config: Config = Field(default_factory=Config.model_construct)
466    """A field for custom configuration that can contain any keys not present in the RDF spec.
467    This means you should not store, for example, a GitHub repo URL in `config` since there is a `git_repo` field.
468    Keys in `config` may be very specific to a tool or consumer software. To avoid conflicting definitions,
469    it is recommended to wrap added configuration into a sub-field named with the specific domain or tool name,
470    for example:
471    ```yaml
472    config:
473        giraffe_neckometer:  # here is the domain name
474            length: 3837283
475            address:
476                home: zoo
477        imagej:              # config specific to ImageJ
478            macro_dir: path/to/macro/file
479    ```
480    If possible, please use [`snake_case`](https://en.wikipedia.org/wiki/Snake_case) for keys in `config`.
481    You may want to list linked files additionally under `attachments` to include them when packaging a resource.
482    (Packaging a resource means downloading/copying important linked files and creating a ZIP archive that contains
483    an altered rdf.yaml file with local references to the downloaded files.)"""
484
485
486ResourceDescrType = TypeVar("ResourceDescrType", bound=GenericDescrBase)
487
488
489class GenericDescr(GenericDescrBase, extra="ignore"):
490    """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).
491
492    An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook.
493    Note that those resources are described with a type-specific RDF.
494    Use this generic resource description, if none of the known specific types matches your resource.
495    """
496
497    implemented_type: ClassVar[Literal["generic"]] = "generic"
498    if TYPE_CHECKING:
499        type: Annotated[str, LowerCase] = "generic"
500        """The resource type assigns a broad category to the resource."""
501    else:
502        type: Annotated[str, LowerCase]
503        """The resource type assigns a broad category to the resource."""
504
505    id: Optional[
506        Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])]
507    ] = None
508    """bioimage.io-wide unique resource identifier
509    assigned by bioimage.io; version **un**specific."""
510
511    parent: Optional[ResourceId] = None
512    """The description from which this one is derived"""
513
514    source: Optional[HttpUrl] = None
515    """The primary source of the resource"""
516
517    @field_validator("type", mode="after")
518    @classmethod
519    def check_specific_types(cls, value: str) -> str:
520        if value in KNOWN_SPECIFIC_RESOURCE_TYPES:
521            raise ValueError(
522                f"Use the {value} description instead of this generic description for"
523                + f" your '{value}' resource."
524            )
525
526        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 0x7fe58df5e5c0>)]
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 0x7fe59c528d60>), PlainSerializer(func=<function _package_serializer at 0x7fe58e0b3060>, 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):
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

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:
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
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.
138class HttpUrl(RootHttpUrl):
139    """A URL with the HTTP or HTTPS scheme."""
140
141    root_model: ClassVar[Type[RootModel[Any]]] = RootModel[pydantic.HttpUrl]
142    _exists: Optional[bool] = None
143
144    def _after_validator(self):
145        self = super()._after_validator()
146        context = get_validation_context()
147        if context.perform_io_checks:
148            _ = self.exists()
149
150        return self
151
152    def exists(self):
153        """True if URL is available"""
154        if self._exists is None:
155            ctxt = get_validation_context()
156            try:
157                with ctxt.replace(warning_level=warning_levels.WARNING):
158                    self._validated = _validate_url(self._validated)
159            except Exception as e:
160                if ctxt.log_warnings:
161                    logger.info(e)
162
163                self._exists = False
164            else:
165                self._exists = True
166
167        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):
152    def exists(self):
153        """True if URL is available"""
154        if self._exists is None:
155            ctxt = get_validation_context()
156            try:
157                with ctxt.replace(warning_level=warning_levels.WARNING):
158                    self._validated = _validate_url(self._validated)
159            except Exception as e:
160                if ctxt.log_warnings:
161                    logger.info(e)
162
163                self._exists = False
164            else:
165                self._exists = True
166
167        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):
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."""

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 0x7fe58df5e5c0>)]]
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 0x7fe58df25b20>)]]

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