diff --git a/bioimageio/spec.html b/bioimageio/spec.html index 6d149bbde..3e2da37c5 100644 --- a/bioimageio/spec.html +++ b/bioimageio/spec.html @@ -21,6 +21,22 @@ +
+ +
+ +This repository contains specifications defined by the bioimage.io community. These specifications are used for defining fields in YAML 1.2 files which should be named rdf.yaml
. Such a rdf.yaml --- along with files referenced in it --- can be downloaded from or uploaded to the bioimage.io website and may be produced or consumed by bioimage.io-compatible consumers (e.g. image analysis software like ilastik).
bioimage.io-compatible resources must fulfill the following rules:
+ +Note that the Python package PyYAML does not support YAML 1.2 . +We therefore use and recommend ruyaml. +For differences see https://ruamelyaml.readthedocs.io/en/latest/pyyaml.
+ +Please also note that the best way to check whether your rdf.yaml
file is bioimage.io-compliant is to call bioimageio.core.validate
from the bioimageio.core Python package.
+The bioimageio.core Python package also provides the bioimageio command line interface (CLI) with the validate
command:
bioimageio validate path/to/your/rdf.yaml
+
+
+All bioimage.io description formats are defined as Pydantic models.
+ +type | +format version | +documentation | +
---|---|---|
model | +0.5 0.4 | +model_descr_v0-5.md model_descr_v0-4.md | +
dataset | +0.3 0.2 | +dataset_descr_v0-3.md dataset_descr_v0-2.md | +
notebook | +0.3 0.2 | +notebook_descr_v0-3.md notebook_descr_v0-2.md | +
application | +0.3 0.2 | +application_descr_v0-3.md application_descr_v0-2.md | +
collection | +0.3 0.2 | +collection_descr_v0-3.md collection_descr_v0-2.md | +
generic | +0.3 0.2 | +generic_descr_v0-3.md generic_descr_v0-2.md | +
Simplified descriptions are available as JSON schema:
+ +bioimageio.spec version | +JSON schema | +
---|---|
latest | +bioimageio_schema_latest.json | +
0.5 | +bioimageio_schema_v0-5.json | +
These are primarily intended for syntax highlighting and form generation.
+ +We provide some examples for using rdf.yaml files to describe models, applications, notebooks and datasets.
+ +rdf.yaml
file and try to avoid using subdirectories.rdf.yaml
file.The bioimageio CLI has moved entirely to bioimageio.core.
+ +bioimageio.spec can be installed with either conda
or pip
, we recommend to install bioimageio.core
instead:
conda install -c conda-forge bioimageio.core
+
+or
+ +pip install -U bioimageio.core
+
++ bioimageio.spec contributors" src="https://contrib.rocks/image?repo=bioimage-io/spec-bioimage-io" /> +
+ +Made with contrib.rocks.
+ +_internal.io_utils.identify_bioimageio_yaml_file()
bioimageio.spec.load_description
(replaces load_raw_resource_description
, interface changed)bioimageio.spec.validate_format
(new)bioimageio.spec.dump_description
(replaces serialize_raw_resource_description_to_dict
, interface changed)bioimageio.spec.update_format
(interface changed)axes
and eps
to scale_mean_var
Make CLI output more readable
find redirected URLs when checking for URL availability
Improve error message for non-existing RDF file path given as string
Improve documentation for model description's documentation
field
resolve_collection_entries()
enrich_partial_rdf
arg of resolve_collection_entries()
ResourceDescrption.root_path
as URI for remote resources. This fixes the collection description as the collection entries are resolved after the collection description has been loaded.new env var BIOIMAGEIO_CACHE_WARNINGS_LIMIT
(default: 3) to avoid spam from cache hit warnings
more robust conversion of ImportableSourceFile for absolute paths to relative paths (don't fail on non-path source file)
any field previously expecting a local relative path is now also accepting an absolute path
load_raw_resource_description returns a raw resource description which has no relative paths (any relative paths are converted to absolute paths).
commands.update_rdf()
/update-rdf
(cli)fix to shape validation for model description 0.4: output shape now needs to be bigger than halo
moved objects from bioimageio.spec.shared.utils to bioimageio.spec.shared[.node_transformer]
root_path
if present in yaml. This field is used internally and always present in RDF nodes.fixed missing field icon
in generic description's raw node
fixes to collection description:
+ +links
is no longer an explicit collection entry field ("moved" to unknown)load_raw_resource_description
no longer accepts update_to_current_format
kwarg (use update_to_format
instead)load_raw_resource_description
accepts update_to_format
kwargdownload_url
attachments.files
moved to attachments.i.source
parent
fieldall generic 0.3.0 changes (except models already have the parent
field) plus:
inputs.i.axes
are now defined in more detail (same for outputs.i.axes
)inputs.i.shape
moved per axes to inputs.i.axes.size
(same for outputs.i.shape
)mode=fixed
is no longer valid.
+(for scalar values this is auto-convertible.)weights.pytorch_state_dict.architecture
+weights.pytorch_state_dict.architecture.source_file
to ...architecture.source
weights.pytorch_state_dict.dependencies
+weights.pytorch_state_dict.dependencies.source
weights.pytorch_state_dict.dependencies.sha256
weights.tensorflow_model_bundle.dependencies
+weights.pytorch_state_dict.dependencies
test_inputs
to inputs.i.test_tensor
test_outputs
to outputs.i.test_tensor
sample_inputs
to inputs.i.sample_tensor
sample_outputs
to outputs.i.sample_tensor
inputs.i.name
to inputs.i.id
outputs.i.name
to outputs.i.id
inputs.i.preprocessing.name
to inputs.i.preprocessing.id
outputs.i.postprocessing.name
to outputs.i.postprocessing.id
id
='ensure_dtype' with kwarg dtype
id
overwritten with value from config.bioimageio.nickname
if availableversion_number
is a new, optional field indicating that an RDF is the nth published version with a given id
id_emoji
is a new, optional field (set from config.bioimageio.nickname_icon
if available)uploader
is a new, optional field with email
and an optional name
subfieldsmode
and axes
always optional for model description 0.3 and 0.4cite
field is now optionalnull
into shape:scale
and indicating length of new dimension D in the offset
field. Keep in mind that D=2*'offset'
.parent
field changed to hold a string that is a bioimage.io ID, a URL or a local relative path (and not subfields uri
and sha256
)training_data
download_url
dependencies
to all weight formats (not only pytorch_state_dict)pytorch_version
to the pytorch_state_dict and torchscript weight formatspytorch_state_dict
weight entry architecture
is no longer optional.Non-breaking changes
+ +authors
, cite
, documentation
and tags
optionalBreaking changes that are fully auto-convertible
+ +collection
field,
+holindg a list of all resources in the specified collection.rdf_source
new optional fieldid
new optional fieldapplication
, model
, dataset
, notebook
and (nested)
+collection
, which hold lists linking to respective resources.email
and github_user
fields to entries in authors
maintainers
field (entries like in authors
but github_user
is required (and name
is not))Breaking changes that are fully auto-convertible
+ +dependencies
to weights:pytorch_state_dict:dependencies
Non-breaking changes
+ +documentation
field accepts URLs as welldocumentation
field accepts URLs as wellBreaking changes
+ +sha256
is required if pytorch_state_dict
weights are defined.
+and is now moved to the pytroch_state_dict
entry as architecture_sha256
.Breaking changes that are fully auto-convertible
+ +source
is renamed architecture
and is moved together with kwargs
to the pytorch_state_dict
+weights entry (if it exists, otherwise they are removed).pytorch_script
was renamed to torchscript
.scale
ing and offset
ing a reference_tensor
maintainers
field was added to the model description.authors
field may now additionally contain email
or github_user
.validate
command now also contains a list of warnings.update_format
command was added to aid with updating older RDFs by applying auto-conversion.eps
to scale_range
postprocessing.reference_input
for implicit output tensor shape was renamed to reference_tensor
Breaking changes
+ +rdf.yaml
for all the RDF (not model.yaml
);authors
and packaged_by
fields from List[str] to List[Author] with Author consisting of a dictionary {name: '<Full name>', affiliation: '<Affiliation>', orcid: 'optional orcid id'}
;type
field to comply with the generic description. Only valid value is 'model' for model description;license
identifier from the SPDX license list;Non-breaking changes
+ +version
field (default 0.1.0) to keep track of model changes;attachments
list to be any values besides URI;1# """ - 2# .. include:: ../../README.md - 3# """ +1""" + 2.. include:: ../../README.md + 3""" 4 5from . import application as application 6from . import collection as collection diff --git a/bioimageio/spec/_description.html b/bioimageio/spec/_description.html index ac8054897..e88443706 100644 --- a/bioimageio/spec/_description.html +++ b/bioimageio/spec/_description.html @@ -54,6 +54,9 @@API Documentation
- validate_format
+- + update_format +
@@ -75,170 +78,182 @@-
-1from types import MappingProxyType - 2from typing import Any, Literal, Optional, TypeVar, Union - 3 - 4from pydantic import Discriminator - 5from typing_extensions import Annotated - 6 - 7from ._build_description import DISCOVER, build_description_impl, get_rd_class_impl - 8from ._internal.common_nodes import InvalidDescr - 9from ._internal.io import BioimageioYamlContent - 10from ._internal.types import FormatVersionPlaceholder - 11from ._internal.validation_context import ValidationContext, validation_context_var - 12from .application import AnyApplicationDescr, ApplicationDescr - 13from .application.v0_2 import ApplicationDescr as ApplicationDescr02 - 14from .application.v0_3 import ApplicationDescr as ApplicationDescr03 - 15from .collection import AnyCollectionDescr, CollectionDescr - 16from .collection.v0_2 import CollectionDescr as CollectionDescr02 - 17from .collection.v0_3 import CollectionDescr as CollectionDescr03 - 18from .dataset import AnyDatasetDescr, DatasetDescr - 19from .dataset.v0_2 import DatasetDescr as DatasetDescr02 - 20from .dataset.v0_3 import DatasetDescr as DatasetDescr03 - 21from .generic import AnyGenericDescr, GenericDescr - 22from .generic.v0_2 import GenericDescr as GenericDescr02 - 23from .generic.v0_3 import GenericDescr as GenericDescr03 - 24from .model import AnyModelDescr, ModelDescr - 25from .model.v0_4 import ModelDescr as ModelDescr04 - 26from .model.v0_5 import ModelDescr as ModelDescr05 - 27from .notebook import AnyNotebookDescr, NotebookDescr - 28from .notebook.v0_2 import NotebookDescr as NotebookDescr02 - 29from .notebook.v0_3 import NotebookDescr as NotebookDescr03 - 30from .summary import ValidationSummary - 31 - 32LATEST: FormatVersionPlaceholder = "latest" - 33"""placeholder for the latest available format version""" - 34 +@@ -313,11 +328,11 @@1from pathlib import Path + 2from types import MappingProxyType + 3from typing import Any, Literal, Optional, TypeVar, Union + 4 + 5from pydantic import Discriminator + 6from typing_extensions import Annotated + 7 + 8from ._build_description import DISCOVER, build_description_impl, get_rd_class_impl + 9from ._internal.common_nodes import InvalidDescr + 10from ._internal.io import BioimageioYamlContent, BioimageioYamlSource + 11from ._internal.types import FormatVersionPlaceholder + 12from ._internal.validation_context import ValidationContext, validation_context_var + 13from .application import AnyApplicationDescr, ApplicationDescr + 14from .application.v0_2 import ApplicationDescr as ApplicationDescr02 + 15from .application.v0_3 import ApplicationDescr as ApplicationDescr03 + 16from .collection import AnyCollectionDescr, CollectionDescr + 17from .collection.v0_2 import CollectionDescr as CollectionDescr02 + 18from .collection.v0_3 import CollectionDescr as CollectionDescr03 + 19from .dataset import AnyDatasetDescr, DatasetDescr + 20from .dataset.v0_2 import DatasetDescr as DatasetDescr02 + 21from .dataset.v0_3 import DatasetDescr as DatasetDescr03 + 22from .generic import AnyGenericDescr, GenericDescr + 23from .generic.v0_2 import GenericDescr as GenericDescr02 + 24from .generic.v0_3 import GenericDescr as GenericDescr03 + 25from .model import AnyModelDescr, ModelDescr + 26from .model.v0_4 import ModelDescr as ModelDescr04 + 27from .model.v0_5 import ModelDescr as ModelDescr05 + 28from .notebook import AnyNotebookDescr, NotebookDescr + 29from .notebook.v0_2 import NotebookDescr as NotebookDescr02 + 30from .notebook.v0_3 import NotebookDescr as NotebookDescr03 + 31from .summary import ValidationSummary + 32 + 33LATEST: FormatVersionPlaceholder = "latest" + 34"""placeholder for the latest available format version""" 35 - 36LatestResourceDescr = Union[ - 37 Annotated[ - 38 Union[ - 39 ApplicationDescr, - 40 CollectionDescr, - 41 DatasetDescr, - 42 ModelDescr, - 43 NotebookDescr, - 44 ], - 45 Discriminator("type"), - 46 ], - 47 GenericDescr, - 48] - 49"""A resource description following the latest specification format""" - 50 + 36 + 37LatestResourceDescr = Union[ + 38 Annotated[ + 39 Union[ + 40 ApplicationDescr, + 41 CollectionDescr, + 42 DatasetDescr, + 43 ModelDescr, + 44 NotebookDescr, + 45 ], + 46 Discriminator("type"), + 47 ], + 48 GenericDescr, + 49] + 50"""A resource description following the latest specification format""" 51 - 52SpecificResourceDescr = Annotated[ - 53 Union[ - 54 AnyApplicationDescr, - 55 AnyCollectionDescr, - 56 AnyDatasetDescr, - 57 AnyModelDescr, - 58 AnyNotebookDescr, - 59 ], - 60 Discriminator("type"), - 61] - 62"""Any of the implemented, non-generic resource descriptions""" - 63 - 64ResourceDescr = Union[SpecificResourceDescr, AnyGenericDescr] - 65"""Any of the implemented resource descriptions""" - 66 + 52 + 53SpecificResourceDescr = Annotated[ + 54 Union[ + 55 AnyApplicationDescr, + 56 AnyCollectionDescr, + 57 AnyDatasetDescr, + 58 AnyModelDescr, + 59 AnyNotebookDescr, + 60 ], + 61 Discriminator("type"), + 62] + 63"""Any of the implemented, non-generic resource descriptions""" + 64 + 65ResourceDescr = Union[SpecificResourceDescr, AnyGenericDescr] + 66"""Any of the implemented resource descriptions""" 67 - 68def dump_description( - 69 rd: Union[ResourceDescr, InvalidDescr], exclude_unset: bool = True - 70) -> BioimageioYamlContent: - 71 """Converts a resource to a dictionary containing only simple types that can directly be serialzed to YAML.""" - 72 return rd.model_dump(mode="json", exclude_unset=exclude_unset) - 73 + 68 + 69def dump_description( + 70 rd: Union[ResourceDescr, InvalidDescr], exclude_unset: bool = True + 71) -> BioimageioYamlContent: + 72 """Converts a resource to a dictionary containing only simple types that can directly be serialzed to YAML.""" + 73 return rd.model_dump(mode="json", exclude_unset=exclude_unset) 74 - 75RD = TypeVar("RD", bound=ResourceDescr) - 76 + 75 + 76RD = TypeVar("RD", bound=ResourceDescr) 77 - 78DESCRIPTIONS_MAP = MappingProxyType( - 79 { - 80 None: MappingProxyType( - 81 { - 82 "0.2": GenericDescr02, - 83 "0.3": GenericDescr03, - 84 None: GenericDescr, - 85 } - 86 ), - 87 "generic": MappingProxyType( - 88 { - 89 "0.2": GenericDescr02, - 90 "0.3": GenericDescr03, - 91 None: GenericDescr, - 92 } - 93 ), - 94 "application": MappingProxyType( - 95 { - 96 "0.2": ApplicationDescr02, - 97 "0.3": ApplicationDescr03, - 98 None: ApplicationDescr, - 99 } -100 ), -101 "collection": MappingProxyType( -102 { -103 "0.2": CollectionDescr02, -104 "0.3": CollectionDescr03, -105 None: CollectionDescr, -106 } -107 ), -108 "dataset": MappingProxyType( -109 { -110 "0.2": DatasetDescr02, -111 "0.3": DatasetDescr03, -112 None: DatasetDescr, -113 } -114 ), -115 "notebook": MappingProxyType( -116 { -117 "0.2": NotebookDescr02, -118 "0.3": NotebookDescr03, -119 None: NotebookDescr, -120 } -121 ), -122 "model": MappingProxyType( -123 { -124 "0.3": ModelDescr04, -125 "0.4": ModelDescr04, -126 "0.5": ModelDescr05, -127 None: ModelDescr, -128 } -129 ), -130 } -131) -132 + 78 + 79DESCRIPTIONS_MAP = MappingProxyType( + 80 { + 81 None: MappingProxyType( + 82 { + 83 "0.2": GenericDescr02, + 84 "0.3": GenericDescr03, + 85 None: GenericDescr, + 86 } + 87 ), + 88 "generic": MappingProxyType( + 89 { + 90 "0.2": GenericDescr02, + 91 "0.3": GenericDescr03, + 92 None: GenericDescr, + 93 } + 94 ), + 95 "application": MappingProxyType( + 96 { + 97 "0.2": ApplicationDescr02, + 98 "0.3": ApplicationDescr03, + 99 None: ApplicationDescr, +100 } +101 ), +102 "collection": MappingProxyType( +103 { +104 "0.2": CollectionDescr02, +105 "0.3": CollectionDescr03, +106 None: CollectionDescr, +107 } +108 ), +109 "dataset": MappingProxyType( +110 { +111 "0.2": DatasetDescr02, +112 "0.3": DatasetDescr03, +113 None: DatasetDescr, +114 } +115 ), +116 "notebook": MappingProxyType( +117 { +118 "0.2": NotebookDescr02, +119 "0.3": NotebookDescr03, +120 None: NotebookDescr, +121 } +122 ), +123 "model": MappingProxyType( +124 { +125 "0.3": ModelDescr04, +126 "0.4": ModelDescr04, +127 "0.5": ModelDescr05, +128 None: ModelDescr, +129 } +130 ), +131 } +132) 133 -134def _get_rd_class(typ: Any, format_version: Any): -135 return get_rd_class_impl(typ, format_version, DESCRIPTIONS_MAP) -136 +134 +135def _get_rd_class(typ: Any, format_version: Any): +136 return get_rd_class_impl(typ, format_version, DESCRIPTIONS_MAP) 137 -138def build_description( -139 content: BioimageioYamlContent, -140 /, -141 *, -142 context: Optional[ValidationContext] = None, -143 format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, -144) -> Union[ResourceDescr, InvalidDescr]: -145 return build_description_impl( -146 content, -147 context=context, -148 format_version=format_version, -149 get_rd_class=_get_rd_class, -150 ) -151 +138 +139def build_description( +140 content: BioimageioYamlContent, +141 /, +142 *, +143 context: Optional[ValidationContext] = None, +144 format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, +145) -> Union[ResourceDescr, InvalidDescr]: +146 return build_description_impl( +147 content, +148 context=context, +149 format_version=format_version, +150 get_rd_class=_get_rd_class, +151 ) 152 -153def validate_format( -154 data: BioimageioYamlContent, -155 /, -156 *, -157 format_version: Union[Literal["discover", "latest"], str] = DISCOVER, -158 context: Optional[ValidationContext] = None, -159) -> ValidationSummary: -160 with context or validation_context_var.get(): -161 rd = build_description(data, format_version=format_version) -162 -163 assert rd.validation_summary is not None -164 return rd.validation_summary +153 +154def validate_format( +155 data: BioimageioYamlContent, +156 /, +157 *, +158 format_version: Union[Literal["discover", "latest"], str] = DISCOVER, +159 context: Optional[ValidationContext] = None, +160) -> ValidationSummary: +161 """validate a bioimageio.yaml file (RDF)""" +162 with context or validation_context_var.get(): +163 rd = build_description(data, format_version=format_version) +164 +165 assert rd.validation_summary is not None +166 return rd.validation_summary +167 +168 +169def update_format( +170 source: BioimageioYamlSource, +171 *, +172 output_path: Optional[Path] = None, +173 target_format_version: Union[Literal["latest"], str] = LATEST, +174) -> BioimageioYamlContent: +175 """update a bioimageio.yaml file without validating it""" +176 raise NotImplementedError("Oh no! This feature is not yet implemented")
-69def dump_description( -70 rd: Union[ResourceDescr, InvalidDescr], exclude_unset: bool = True -71) -> BioimageioYamlContent: -72 """Converts a resource to a dictionary containing only simple types that can directly be serialzed to YAML.""" -73 return rd.model_dump(mode="json", exclude_unset=exclude_unset) +@@ -350,19 +365,19 @@70def dump_description( +71 rd: Union[ResourceDescr, InvalidDescr], exclude_unset: bool = True +72) -> BioimageioYamlContent: +73 """Converts a resource to a dictionary containing only simple types that can directly be serialzed to YAML.""" +74 return rd.model_dump(mode="json", exclude_unset=exclude_unset)
-139def build_description( -140 content: BioimageioYamlContent, -141 /, -142 *, -143 context: Optional[ValidationContext] = None, -144 format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, -145) -> Union[ResourceDescr, InvalidDescr]: -146 return build_description_impl( -147 content, -148 context=context, -149 format_version=format_version, -150 get_rd_class=_get_rd_class, -151 ) +@@ -380,22 +395,52 @@140def build_description( +141 content: BioimageioYamlContent, +142 /, +143 *, +144 context: Optional[ValidationContext] = None, +145 format_version: Union[FormatVersionPlaceholder, str] = DISCOVER, +146) -> Union[ResourceDescr, InvalidDescr]: +147 return build_description_impl( +148 content, +149 context=context, +150 format_version=format_version, +151 get_rd_class=_get_rd_class, +152 )
154def validate_format( -155 data: BioimageioYamlContent, -156 /, -157 *, -158 format_version: Union[Literal["discover", "latest"], str] = DISCOVER, -159 context: Optional[ValidationContext] = None, -160) -> ValidationSummary: -161 with context or validation_context_var.get(): -162 rd = build_description(data, format_version=format_version) -163 -164 assert rd.validation_summary is not None -165 return rd.validation_summary +- +155def validate_format( +156 data: BioimageioYamlContent, +157 /, +158 *, +159 format_version: Union[Literal["discover", "latest"], str] = DISCOVER, +160 context: Optional[ValidationContext] = None, +161) -> ValidationSummary: +162 """validate a bioimageio.yaml file (RDF)""" +163 with context or validation_context_var.get(): +164 rd = build_description(data, format_version=format_version) +165 +166 assert rd.validation_summary is not None +167 return rd.validation_summary+ + + +validate a bioimageio.yaml file (RDF)
++ + diff --git a/bioimageio/spec/_internal.html b/bioimageio/spec/_internal.html index dd36f9177..142b2f8b2 100644 --- a/bioimageio/spec/_internal.html +++ b/bioimageio/spec/_internal.html @@ -46,6 +46,7 @@+ + def + update_format( source: Union[Annotated[pathlib.Path, PathType(path_type='file')], bioimageio.spec._internal.io.RelativeFilePath, bioimageio.spec._internal.url.HttpUrl, Annotated[pydantic_core._pydantic_core.Url, UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=None, default_host=None, default_port=None, default_path=None)], str, Dict[str, YamlValue]], *, output_path: Optional[pathlib.Path] = None, target_format_version: Union[Literal['latest'], str] = 'latest') -> Dict[str, YamlValue]: + + + ++ ++ + +170def update_format( +171 source: BioimageioYamlSource, +172 *, +173 output_path: Optional[Path] = None, +174 target_format_version: Union[Literal["latest"], str] = LATEST, +175) -> BioimageioYamlContent: +176 """update a bioimageio.yaml file without validating it""" +177 raise NotImplementedError("Oh no! This feature is not yet implemented") ++update a bioimageio.yaml file without validating it
+Submodules
- utils
- validated_string
- validation_context
+- validator_annotations
- version_type
- warning_levels
diff --git a/bioimageio/spec/_internal/common_nodes.html b/bioimageio/spec/_internal/common_nodes.html index 7161e24db..f2716c675 100644 --- a/bioimageio/spec/_internal/common_nodes.html +++ b/bioimageio/spec/_internal/common_nodes.html @@ -1418,7 +1418,7 @@Inherited Members
fields_to_set_explicitly: ClassVar[FrozenSet[LiteralString]] = -frozenset({'type', 'format_version'}) +frozenset({'format_version', 'type'})diff --git a/bioimageio/spec/_internal/constants.html b/bioimageio/spec/_internal/constants.html index 4bcd8f159..e990acf6c 100644 --- a/bioimageio/spec/_internal/constants.html +++ b/bioimageio/spec/_internal/constants.html @@ -338,7 +338,7 @@Inherited Members
KNOWN_GH_USERS: Set[str] = - {'danifranco', 'jansanrom', 'lenkaback', 'ctr26', 'k-dominik', 'iarganda', 'fynnbe', 'pedgomgal1', 'githubuser2', 'ivanhcenalmor', 'carlosuc3m', 'esgomezm', 'aaitorg', 'bioimageiobot', 'clementcaporal', 'cfusterbarcelo', 'constantinpape', 'oeway', 'donglaiw'} + {'lenkaback', 'k-dominik', 'constantinpape', 'aaitorg', 'danifranco', 'bioimageiobot', 'ctr26', 'iarganda', 'donglaiw', 'esgomezm', 'fynnbe', 'jansanrom', 'clementcaporal', 'githubuser2', 'ivanhcenalmor', 'pedgomgal1', 'cfusterbarcelo', 'oeway', 'carlosuc3m'}diff --git a/bioimageio/spec/_internal/field_validation.html b/bioimageio/spec/_internal/field_validation.html index fe6862540..5569dd32e 100644 --- a/bioimageio/spec/_internal/field_validation.html +++ b/bioimageio/spec/_internal/field_validation.html @@ -30,21 +30,6 @@API Documentation
-
- - RestrictCharacters -
-
- -- - RestrictCharacters -
-- - alphabet -
-- - validate -
-- is_valid_yaml_leaf_value
@@ -63,33 +48,6 @@API Documentation
- validate_unique_entries
-- - AfterValidator -
--
- -- - AfterValidator -
-- - BeforeValidator -
--
- -- - BeforeValidator -
-- - Predicate -
-
- -- - Predicate -
-- validate_gh_user
@@ -114,241 +72,99 @@-
1from __future__ import annotations - 2 - 3import collections.abc - 4import dataclasses - 5import sys - 6from dataclasses import dataclass - 7from datetime import date, datetime - 8from typing import ( - 9 Any, - 10 Dict, - 11 Hashable, - 12 Mapping, - 13 Sequence, - 14 Type, - 15 Union, - 16) - 17 - 18import annotated_types - 19import requests - 20from pydantic import GetCoreSchemaHandler, functional_validators - 21from pydantic_core.core_schema import CoreSchema, no_info_after_validator_function - 22 - 23from bioimageio.spec._internal._settings import settings - 24from bioimageio.spec._internal.constants import KNOWN_GH_USERS, KNOWN_INVALID_GH_USERS - 25from bioimageio.spec._internal.field_warning import issue_warning - 26from bioimageio.spec._internal.validation_context import validation_context_var - 27 - 28if sys.version_info < (3, 10): - 29 SLOTS: Dict[str, bool] = {} - 30 KW_ONLY: Dict[str, bool] = {} - 31else: - 32 SLOTS = {"slots": True} - 33 KW_ONLY = {"kw_only": True} - 34 - 35 - 36@dataclasses.dataclass(frozen=True, **SLOTS) - 37class RestrictCharacters: - 38 alphabet: str - 39 - 40 def __get_pydantic_core_schema__( - 41 self, source: Type[Any], handler: GetCoreSchemaHandler - 42 ) -> CoreSchema: - 43 if not self.alphabet: - 44 raise ValueError("Alphabet may not be empty") - 45 schema = handler(source) # get the CoreSchema from the type / inner constraints - 46 if schema["type"] != "str": - 47 raise TypeError("RestrictCharacters can only be applied to strings") - 48 return no_info_after_validator_function( - 49 self.validate, - 50 schema, - 51 ) - 52 - 53 def validate(self, value: str) -> str: - 54 if any(c not in self.alphabet for c in value): - 55 raise ValueError(f"{value!r} is not restricted to {self.alphabet!r}") - 56 return value - 57 - 58 - 59def is_valid_yaml_leaf_value(value: Any) -> bool: - 60 return value is None or isinstance(value, (bool, date, datetime, int, float, str)) - 61 - 62 - 63def is_valid_yaml_key(value: Union[Any, Sequence[Any]]) -> bool: - 64 return ( - 65 is_valid_yaml_leaf_value(value) - 66 or isinstance(value, tuple) - 67 and all(is_valid_yaml_leaf_value(v) for v in value) - 68 ) - 69 - 70 - 71def is_valid_yaml_mapping(value: Union[Any, Mapping[Any, Any]]) -> bool: - 72 return isinstance(value, collections.abc.Mapping) and all( - 73 is_valid_yaml_key(k) and is_valid_yaml_value(v) for k, v in value.items() - 74 ) - 75 - 76 - 77def is_valid_yaml_sequence(value: Union[Any, Sequence[Any]]) -> bool: - 78 return isinstance(value, collections.abc.Sequence) and all( - 79 is_valid_yaml_value(v) for v in value - 80 ) - 81 - 82 - 83def is_valid_yaml_value(value: Any) -> bool: - 84 return any( - 85 is_valid(value) - 86 for is_valid in ( - 87 is_valid_yaml_key, - 88 is_valid_yaml_mapping, - 89 is_valid_yaml_sequence, - 90 ) - 91 ) - 92 - 93 - 94def validate_unique_entries(seq: Sequence[Hashable]): - 95 if len(seq) != len(set(seq)): - 96 raise ValueError("Entries are not unique.") - 97 return seq - 98 - 99 -100# TODO: make sure we use this one everywhere and not the vanilla pydantic one -101@dataclass(frozen=True, **SLOTS) -102class AfterValidator(functional_validators.AfterValidator): -103 def __str__(self): -104 return f"AfterValidator({self.func.__name__})" -105 -106 -107# TODO: make sure we use this one everywhere and not the vanilla pydantic one -108@dataclass(frozen=True, **SLOTS) -109class BeforeValidator(functional_validators.BeforeValidator): -110 def __str__(self): -111 return f"BeforeValidator({self.func.__name__})" -112 -113 -114# TODO: make sure we use this one everywhere and not the vanilla pydantic one -115@dataclass(frozen=True, **SLOTS) -116class Predicate(annotated_types.Predicate): -117 def __str__(self): -118 return f"Predicate({self.func.__name__})" -119 -120 -121def validate_gh_user(username: str, hotfix_known_errorenous_names: bool = True) -> str: -122 if hotfix_known_errorenous_names: -123 if username == "Constantin Pape": -124 return "constantinpape" -125 -126 if ( -127 username.lower() in KNOWN_GH_USERS -128 or not validation_context_var.get().perform_io_checks -129 ): -130 return username -131 -132 if username.lower() in KNOWN_INVALID_GH_USERS: -133 raise ValueError(f"Known invalid GitHub user '{username}'") -134 -135 r = requests.get( -136 f"https://api.github.com/users/{username}", auth=settings.github_auth -137 ) -138 if r.status_code == 403 and r.reason == "rate limit exceeded": -139 issue_warning( -140 "Could not verify GitHub user '{value}' due to GitHub API rate limit", -141 value=username, -142 ) -143 elif r.status_code != 200: -144 KNOWN_INVALID_GH_USERS.add(username.lower()) -145 raise ValueError(f"Could not find GitHub user '{username}'") -146 -147 KNOWN_GH_USERS.add(username.lower()) -148 return username +-1from __future__ import annotations + 2 + 3import collections.abc + 4from datetime import date, datetime + 5from typing import ( + 6 Any, + 7 Hashable, + 8 Mapping, + 9 Sequence, +10 Union, +11) +12 +13import requests +14 +15from bioimageio.spec._internal._settings import settings +16from bioimageio.spec._internal.constants import KNOWN_GH_USERS, KNOWN_INVALID_GH_USERS +17from bioimageio.spec._internal.field_warning import issue_warning +18from bioimageio.spec._internal.validation_context import validation_context_var +19 +20 +21def is_valid_yaml_leaf_value(value: Any) -> bool: +22 return value is None or isinstance(value, (bool, date, datetime, int, float, str)) +23 +24 +25def is_valid_yaml_key(value: Union[Any, Sequence[Any]]) -> bool: +26 return ( +27 is_valid_yaml_leaf_value(value) +28 or isinstance(value, tuple) +29 and all(is_valid_yaml_leaf_value(v) for v in value) +30 ) +31 +32 +33def is_valid_yaml_mapping(value: Union[Any, Mapping[Any, Any]]) -> bool: +34 return isinstance(value, collections.abc.Mapping) and all( +35 is_valid_yaml_key(k) and is_valid_yaml_value(v) for k, v in value.items() +36 ) +37 +38 +39def is_valid_yaml_sequence(value: Union[Any, Sequence[Any]]) -> bool: +40 return isinstance(value, collections.abc.Sequence) and all( +41 is_valid_yaml_value(v) for v in value +42 ) +43 +44 +45def is_valid_yaml_value(value: Any) -> bool: +46 return any( +47 is_valid(value) +48 for is_valid in ( +49 is_valid_yaml_key, +50 is_valid_yaml_mapping, +51 is_valid_yaml_sequence, +52 ) +53 ) +54 +55 +56def validate_unique_entries(seq: Sequence[Hashable]): +57 if len(seq) != len(set(seq)): +58 raise ValueError("Entries are not unique.") +59 return seq +60 +61 +62def validate_gh_user(username: str, hotfix_known_errorenous_names: bool = True) -> str: +63 if hotfix_known_errorenous_names: +64 if username == "Constantin Pape": +65 return "constantinpape" +66 +67 if ( +68 username.lower() in KNOWN_GH_USERS +69 or not validation_context_var.get().perform_io_checks +70 ): +71 return username +72 +73 if username.lower() in KNOWN_INVALID_GH_USERS: +74 raise ValueError(f"Known invalid GitHub user '{username}'") +75 +76 r = requests.get( +77 f"https://api.github.com/users/{username}", auth=settings.github_auth +78 ) +79 if r.status_code == 403 and r.reason == "rate limit exceeded": +80 issue_warning( +81 "Could not verify GitHub user '{value}' due to GitHub API rate limit", +82 value=username, +83 ) +84 elif r.status_code != 200: +85 KNOWN_INVALID_GH_USERS.add(username.lower()) +86 raise ValueError(f"Could not find GitHub user '{username}'") +87 +88 KNOWN_GH_USERS.add(username.lower()) +89 return username- - -- -@dataclasses.dataclass(frozen=True, **SLOTS)- - class - RestrictCharacters: - - - -- - - - - - - -37@dataclasses.dataclass(frozen=True, **SLOTS) -38class RestrictCharacters: -39 alphabet: str -40 -41 def __get_pydantic_core_schema__( -42 self, source: Type[Any], handler: GetCoreSchemaHandler -43 ) -> CoreSchema: -44 if not self.alphabet: -45 raise ValueError("Alphabet may not be empty") -46 schema = handler(source) # get the CoreSchema from the type / inner constraints -47 if schema["type"] != "str": -48 raise TypeError("RestrictCharacters can only be applied to strings") -49 return no_info_after_validator_function( -50 self.validate, -51 schema, -52 ) -53 -54 def validate(self, value: str) -> str: -55 if any(c not in self.alphabet for c in value): -56 raise ValueError(f"{value!r} is not restricted to {self.alphabet!r}") -57 return value - @@ -360,8 +176,8 @@-
-60def is_valid_yaml_leaf_value(value: Any) -> bool: -61 return value is None or isinstance(value, (bool, date, datetime, int, float, str)) +@@ -379,12 +195,12 @@22def is_valid_yaml_leaf_value(value: Any) -> bool: +23 return value is None or isinstance(value, (bool, date, datetime, int, float, str))
-64def is_valid_yaml_key(value: Union[Any, Sequence[Any]]) -> bool: -65 return ( -66 is_valid_yaml_leaf_value(value) -67 or isinstance(value, tuple) -68 and all(is_valid_yaml_leaf_value(v) for v in value) -69 ) +@@ -402,10 +218,10 @@26def is_valid_yaml_key(value: Union[Any, Sequence[Any]]) -> bool: +27 return ( +28 is_valid_yaml_leaf_value(value) +29 or isinstance(value, tuple) +30 and all(is_valid_yaml_leaf_value(v) for v in value) +31 )
-72def is_valid_yaml_mapping(value: Union[Any, Mapping[Any, Any]]) -> bool: -73 return isinstance(value, collections.abc.Mapping) and all( -74 is_valid_yaml_key(k) and is_valid_yaml_value(v) for k, v in value.items() -75 ) +@@ -423,10 +239,10 @@34def is_valid_yaml_mapping(value: Union[Any, Mapping[Any, Any]]) -> bool: +35 return isinstance(value, collections.abc.Mapping) and all( +36 is_valid_yaml_key(k) and is_valid_yaml_value(v) for k, v in value.items() +37 )
-78def is_valid_yaml_sequence(value: Union[Any, Sequence[Any]]) -> bool: -79 return isinstance(value, collections.abc.Sequence) and all( -80 is_valid_yaml_value(v) for v in value -81 ) +@@ -444,15 +260,15 @@40def is_valid_yaml_sequence(value: Union[Any, Sequence[Any]]) -> bool: +41 return isinstance(value, collections.abc.Sequence) and all( +42 is_valid_yaml_value(v) for v in value +43 )
-84def is_valid_yaml_value(value: Any) -> bool: -85 return any( -86 is_valid(value) -87 for is_valid in ( -88 is_valid_yaml_key, -89 is_valid_yaml_mapping, -90 is_valid_yaml_sequence, -91 ) -92 ) +@@ -470,144 +286,15 @@46def is_valid_yaml_value(value: Any) -> bool: +47 return any( +48 is_valid(value) +49 for is_valid in ( +50 is_valid_yaml_key, +51 is_valid_yaml_mapping, +52 is_valid_yaml_sequence, +53 ) +54 )
-95def validate_unique_entries(seq: Sequence[Hashable]): -96 if len(seq) != len(set(seq)): -97 raise ValueError("Entries are not unique.") -98 return seq +- -57def validate_unique_entries(seq: Sequence[Hashable]): +58 if len(seq) != len(set(seq)): +59 raise ValueError("Entries are not unique.") +60 return seq- - --- -@dataclass(frozen=True, **SLOTS)- - class - AfterValidator(pydantic.functional_validators.AfterValidator): - - - - - - - - -102@dataclass(frozen=True, **SLOTS) -103class AfterValidator(functional_validators.AfterValidator): -104 def __str__(self): -105 return f"AfterValidator({self.func.__name__})" ---- - AfterValidator( func: 'core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction') - - -- - - - ---Inherited Members
--
--- pydantic.functional_validators.AfterValidator
-- func
- -- - --- -@dataclass(frozen=True, **SLOTS)- - class - BeforeValidator(pydantic.functional_validators.BeforeValidator): - - - - - - - - -109@dataclass(frozen=True, **SLOTS) -110class BeforeValidator(functional_validators.BeforeValidator): -111 def __str__(self): -112 return f"BeforeValidator({self.func.__name__})" ---- - BeforeValidator( func: 'core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction') - - -- - - - ---Inherited Members
--
--- pydantic.functional_validators.BeforeValidator
-- func
- -- - -- -@dataclass(frozen=True, **SLOTS)- - class - Predicate(annotated_types.Predicate): - - - - - - - - - -116@dataclass(frozen=True, **SLOTS) -117class Predicate(annotated_types.Predicate): -118 def __str__(self): -119 return f"Predicate({self.func.__name__})" --Inherited Members
--
--- annotated_types.Predicate
-- func
- -@@ -620,34 +307,34 @@ Inherited Members
122def validate_gh_user(username: str, hotfix_known_errorenous_names: bool = True) -> str: -123 if hotfix_known_errorenous_names: -124 if username == "Constantin Pape": -125 return "constantinpape" -126 -127 if ( -128 username.lower() in KNOWN_GH_USERS -129 or not validation_context_var.get().perform_io_checks -130 ): -131 return username -132 -133 if username.lower() in KNOWN_INVALID_GH_USERS: -134 raise ValueError(f"Known invalid GitHub user '{username}'") -135 -136 r = requests.get( -137 f"https://api.github.com/users/{username}", auth=settings.github_auth -138 ) -139 if r.status_code == 403 and r.reason == "rate limit exceeded": -140 issue_warning( -141 "Could not verify GitHub user '{value}' due to GitHub API rate limit", -142 value=username, -143 ) -144 elif r.status_code != 200: -145 KNOWN_INVALID_GH_USERS.add(username.lower()) -146 raise ValueError(f"Could not find GitHub user '{username}'") -147 -148 KNOWN_GH_USERS.add(username.lower()) -149 return username +diff --git a/bioimageio/spec/_internal/io.html b/bioimageio/spec/_internal/io.html index 5c73409b4..eda60c0dc 100644 --- a/bioimageio/spec/_internal/io.html +++ b/bioimageio/spec/_internal/io.html @@ -298,46 +298,46 @@63def validate_gh_user(username: str, hotfix_known_errorenous_names: bool = True) -> str: +64 if hotfix_known_errorenous_names: +65 if username == "Constantin Pape": +66 return "constantinpape" +67 +68 if ( +69 username.lower() in KNOWN_GH_USERS +70 or not validation_context_var.get().perform_io_checks +71 ): +72 return username +73 +74 if username.lower() in KNOWN_INVALID_GH_USERS: +75 raise ValueError(f"Known invalid GitHub user '{username}'") +76 +77 r = requests.get( +78 f"https://api.github.com/users/{username}", auth=settings.github_auth +79 ) +80 if r.status_code == 403 and r.reason == "rate limit exceeded": +81 issue_warning( +82 "Could not verify GitHub user '{value}' due to GitHub API rate limit", +83 value=username, +84 ) +85 elif r.status_code != 200: +86 KNOWN_INVALID_GH_USERS.add(username.lower()) +87 raise ValueError(f"Could not find GitHub user '{username}'") +88 +89 KNOWN_GH_USERS.add(username.lower()) +90 return username26import pooch 27import pydantic 28from pydantic import ( - 29 AfterValidator, - 30 AnyUrl, - 31 DirectoryPath, - 32 FilePath, - 33 GetCoreSchemaHandler, - 34 PlainSerializer, - 35 PrivateAttr, - 36 RootModel, - 37 SerializationInfo, - 38 StringConstraints, - 39 TypeAdapter, - 40 model_validator, - 41) - 42from pydantic_core import core_schema - 43from typing_extensions import ( - 44 Annotated, - 45 LiteralString, - 46 NotRequired, - 47 Self, - 48 Unpack, - 49 assert_never, - 50) - 51from typing_extensions import TypeAliasType as _TypeAliasType - 52 - 53from .._internal._settings import settings - 54from .._internal.io_basics import ( - 55 ALL_BIOIMAGEIO_YAML_NAMES, - 56 BIOIMAGEIO_YAML, - 57 AbsoluteDirectory, - 58 AbsoluteFilePath, - 59 FileName, - 60) - 61from .._internal.node import Node - 62from .._internal.packaging_context import packaging_context_var - 63from .._internal.root_url import RootHttpUrl - 64from .._internal.url import HttpUrl - 65from .._internal.validated_string import ValidatedString - 66from .._internal.validation_context import ( - 67 validation_context_var, - 68) + 29 AnyUrl, + 30 DirectoryPath, + 31 FilePath, + 32 GetCoreSchemaHandler, + 33 PlainSerializer, + 34 PrivateAttr, + 35 RootModel, + 36 SerializationInfo, + 37 StringConstraints, + 38 TypeAdapter, + 39 model_validator, + 40) + 41from pydantic_core import core_schema + 42from typing_extensions import ( + 43 Annotated, + 44 LiteralString, + 45 NotRequired, + 46 Self, + 47 Unpack, + 48 assert_never, + 49) + 50from typing_extensions import TypeAliasType as _TypeAliasType + 51 + 52from .._internal._settings import settings + 53from .._internal.io_basics import ( + 54 ALL_BIOIMAGEIO_YAML_NAMES, + 55 BIOIMAGEIO_YAML, + 56 AbsoluteDirectory, + 57 AbsoluteFilePath, + 58 FileName, + 59) + 60from .._internal.node import Node + 61from .._internal.packaging_context import packaging_context_var + 62from .._internal.root_url import RootHttpUrl + 63from .._internal.url import HttpUrl + 64from .._internal.validated_string import ValidatedString + 65from .._internal.validation_context import ( + 66 validation_context_var, + 67) + 68from .validator_annotations import AfterValidator 69 70if sys.version_info < (3, 10): 71 SLOTS: Dict[str, bool] = {} @@ -1237,7 +1237,7 @@
Inherited Members
def - get_absolute( self, root: bioimageio.spec._internal.root_url.RootHttpUrl | pathlib.Path | pydantic_core._pydantic_core.Url) -> Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(func=<function PurePath.is_absolute at 0x7f1c25245940>)], Annotated[pathlib.Path, PathType(path_type='dir'), Predicate(func=<function PurePath.is_absolute at 0x7f1c25245940>)], bioimageio.spec._internal.url.HttpUrl]: + get_absolute( self, root: bioimageio.spec._internal.root_url.RootHttpUrl | pathlib.Path | pydantic_core._pydantic_core.Url) -> Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(func=<function PurePath.is_absolute at 0x7afca4145940>)], Annotated[pathlib.Path, PathType(path_type='dir'), Predicate(func=<function PurePath.is_absolute at 0x7afca4145940>)], bioimageio.spec._internal.url.HttpUrl]: @@ -1355,7 +1355,7 @@Inherited Members
def - get_absolute( self, root: bioimageio.spec._internal.root_url.RootHttpUrl | pathlib.Path | pydantic_core._pydantic_core.Url) -> Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(func=<function PurePath.is_absolute at 0x7f1c25245940>)], bioimageio.spec._internal.url.HttpUrl]: + get_absolute( self, root: bioimageio.spec._internal.root_url.RootHttpUrl | pathlib.Path | pydantic_core._pydantic_core.Url) -> Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(func=<function PurePath.is_absolute at 0x7afca4145940>)], bioimageio.spec._internal.url.HttpUrl]: @@ -1475,7 +1475,7 @@Inherited Members
def - get_absolute( self, root: bioimageio.spec._internal.root_url.RootHttpUrl | pathlib.Path | pydantic_core._pydantic_core.Url) -> Union[Annotated[pathlib.Path, PathType(path_type='dir'), Predicate(func=<function PurePath.is_absolute at 0x7f1c25245940>)], bioimageio.spec._internal.url.HttpUrl]: + get_absolute( self, root: bioimageio.spec._internal.root_url.RootHttpUrl | pathlib.Path | pydantic_core._pydantic_core.Url) -> Union[Annotated[pathlib.Path, PathType(path_type='dir'), Predicate(func=<function PurePath.is_absolute at 0x7afca4145940>)], bioimageio.spec._internal.url.HttpUrl]: @@ -1997,7 +1997,7 @@Inherited Members
- original_root: Union[Annotated[pathlib.Path, PathType(path_type='dir'), Predicate(func=<function PurePath.is_absolute at 0x7f1c25245940>)], bioimageio.spec._internal.root_url.RootHttpUrl] + original_root: Union[Annotated[pathlib.Path, PathType(path_type='dir'), Predicate(func=<function PurePath.is_absolute at 0x7afca4145940>)], bioimageio.spec._internal.root_url.RootHttpUrl]@@ -2065,7 +2065,7 @@Inherited Members
- original_root: Union[Annotated[pathlib.Path, PathType(path_type='dir'), Predicate(func=<function PurePath.is_absolute at 0x7f1c25245940>)], bioimageio.spec._internal.root_url.RootHttpUrl] + original_root: Union[Annotated[pathlib.Path, PathType(path_type='dir'), Predicate(func=<function PurePath.is_absolute at 0x7afca4145940>)], bioimageio.spec._internal.root_url.RootHttpUrl]@@ -2284,7 +2284,7 @@Inherited Members
- -- source: Annotated[Union[Annotated[pathlib.Path, PathType(path_type='file')], RelativeFilePath, bioimageio.spec._internal.url.HttpUrl, Annotated[pydantic_core._pydantic_core.Url, UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=None, default_host=None, default_port=None, default_path=None)]], AfterValidator(func=<function wo_special_file_name at 0x7f1c21c3ef20>), PlainSerializer(func=<function _package at 0x7f1c21c782c0>, return_type=PydanticUndefined, when_used='unless-none')] + source: Annotated[Union[Annotated[pathlib.Path, PathType(path_type='file')], RelativeFilePath, bioimageio.spec._internal.url.HttpUrl, Annotated[pydantic_core._pydantic_core.Url, UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=None, default_host=None, default_port=None, default_path=None)]], AfterValidator(func=<function wo_special_file_name at 0x7afca0d90540>), PlainSerializer(func=<function _package at 0x7afca0d91760>, return_type=PydanticUndefined, when_used='unless-none')]diff --git a/bioimageio/spec/_internal/io_utils.html b/bioimageio/spec/_internal/io_utils.html index b6a95dc6a..964aef92a 100644 --- a/bioimageio/spec/_internal/io_utils.html +++ b/bioimageio/spec/_internal/io_utils.html @@ -43,10 +43,10 @@API Documentation
open_bioimageio_yaml- - identify_bioimageio_yaml_file + identify_bioimageio_yaml_file_name
- - find_description_file_name + find_bioimageio_yaml_file_name
- unzip @@ -167,14 +167,14 @@
84 85 if local_source.is_dir(): 86 root = local_source - 87 local_source = local_source / find_description_file_name(local_source) + 87 local_source = local_source / find_bioimageio_yaml_file_name(local_source) 88 89 content = _sanitize_bioimageio_yaml(read_yaml(local_source)) 90 91 return OpenedBioimageioYaml(content, root, downloaded.original_file_name) 92 93 - 94def identify_bioimageio_yaml_file(file_names: Iterable[FileName]) -> FileName: + 94def identify_bioimageio_yaml_file_name(file_names: Iterable[FileName]) -> FileName: 95 file_names = sorted(file_names) 96 for bioimageio_name in ALL_BIOIMAGEIO_YAML_NAMES: 97 for fname in file_names: @@ -189,17 +189,17 @@
106 ) 107 108 -109def find_description_file_name(path: Path) -> FileName: +109def find_bioimageio_yaml_file_name(path: Path) -> FileName: 110 if path.is_file(): 111 if not is_zipfile(path): 112 return path.name 113 114 with ZipFile(path, "r") as f: -115 file_names = identify_bioimageio_yaml_file(f.namelist()) +115 file_names = identify_bioimageio_yaml_file_name(f.namelist()) 116 else: 117 file_names = [p.name for p in path.glob("*")] 118 -119 return identify_bioimageio_yaml_file(file_names) +119 return identify_bioimageio_yaml_file_name(file_names) 120 121 122def unzip( @@ -383,7 +383,7 @@
85 86 if local_source.is_dir(): 87 root = local_source -88 local_source = local_source / find_description_file_name(local_source) +88 local_source = local_source / find_bioimageio_yaml_file_name(local_source) 89 90 content = _sanitize_bioimageio_yaml(read_yaml(local_source)) 91 @@ -394,58 +394,58 @@
-
- + + def - identify_bioimageio_yaml_file(file_names: Iterable[str]) -> str: + identify_bioimageio_yaml_file_name(file_names: Iterable[str]) -> str: - +- --95def identify_bioimageio_yaml_file(file_names: Iterable[FileName]) -> FileName: - 96 file_names = sorted(file_names) - 97 for bioimageio_name in ALL_BIOIMAGEIO_YAML_NAMES: - 98 for fname in file_names: - 99 if fname == bioimageio_name or fname.endswith(f".{bioimageio_name}"): -100 return fname -101 -102 raise ValueError( -103 f"No {BIOIMAGEIO_YAML} found in {file_names}. (Looking for '{BIOIMAGEIO_YAML}'" -104 + " or or any of the alterntive file names:" -105 + f" {ALTERNATIVE_BIOIMAGEIO_YAML_NAMES}, or any file with an extension of" -106 + f" those, e.g. 'anything.{BIOIMAGEIO_YAML}')." -107 ) + +-95def identify_bioimageio_yaml_file_name(file_names: Iterable[FileName]) -> FileName: + 96 file_names = sorted(file_names) + 97 for bioimageio_name in ALL_BIOIMAGEIO_YAML_NAMES: + 98 for fname in file_names: + 99 if fname == bioimageio_name or fname.endswith(f".{bioimageio_name}"): +100 return fname +101 +102 raise ValueError( +103 f"No {BIOIMAGEIO_YAML} found in {file_names}. (Looking for '{BIOIMAGEIO_YAML}'" +104 + " or or any of the alterntive file names:" +105 + f" {ALTERNATIVE_BIOIMAGEIO_YAML_NAMES}, or any file with an extension of" +106 + f" those, e.g. 'anything.{BIOIMAGEIO_YAML}')." +107 )- + + def - find_description_file_name(path: pathlib.Path) -> str: + find_bioimageio_yaml_file_name(path: pathlib.Path) -> str: - +- -110def find_description_file_name(path: Path) -> FileName: -111 if path.is_file(): -112 if not is_zipfile(path): -113 return path.name -114 -115 with ZipFile(path, "r") as f: -116 file_names = identify_bioimageio_yaml_file(f.namelist()) -117 else: -118 file_names = [p.name for p in path.glob("*")] -119 -120 return identify_bioimageio_yaml_file(file_names) + +diff --git a/bioimageio/spec/_internal/packaging_context.html b/bioimageio/spec/_internal/packaging_context.html index 9c2218716..788cb0d07 100644 --- a/bioimageio/spec/_internal/packaging_context.html +++ b/bioimageio/spec/_internal/packaging_context.html @@ -207,7 +207,7 @@110def find_bioimageio_yaml_file_name(path: Path) -> FileName: +111 if path.is_file(): +112 if not is_zipfile(path): +113 return path.name +114 +115 with ZipFile(path, "r") as f: +116 file_names = identify_bioimageio_yaml_file_name(f.namelist()) +117 else: +118 file_names = [p.name for p in path.glob("*")] +119 +120 return identify_bioimageio_yaml_file_name(file_names)
@@ -149,57 +150,57 @@- file_sources: Dict[str, Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(func=<function PurePath.is_absolute at 0x7f1c25245940>)], bioimageio.spec._internal.url.HttpUrl]] + file_sources: Dict[str, Union[Annotated[pathlib.Path, PathType(path_type='file'), Predicate(func=<function PurePath.is_absolute at 0x7afca4145940>)], bioimageio.spec._internal.url.HttpUrl]]diff --git a/bioimageio/spec/_internal/root_url.html b/bioimageio/spec/_internal/root_url.html index e44a3549b..eb1237c5f 100644 --- a/bioimageio/spec/_internal/root_url.html +++ b/bioimageio/spec/_internal/root_url.html @@ -75,65 +75,66 @@4from urllib.parse import urlsplit, urlunsplit 5 6import pydantic - 7from pydantic import AfterValidator, TypeAdapter + 7from pydantic import TypeAdapter 8from typing_extensions import Annotated 9 10from .validated_string import ValidatedString -11 -12_http_url_adapter = TypeAdapter(pydantic.HttpUrl) # pyright: ignore[reportCallIssue] -13 +11from .validator_annotations import AfterValidator +12 +13_http_url_adapter = TypeAdapter(pydantic.HttpUrl) # pyright: ignore[reportCallIssue] 14 -15class RootHttpUrl( -16 ValidatedString[ -17 Annotated[ -18 str, -19 AfterValidator(lambda value: str(_http_url_adapter.validate_python(value))), -20 ] -21 ], -22 frozen=True, -23): -24 """A 'URL folder', possibly an invalid http URL""" -25 -26 @property -27 def _url(self): -28 return pydantic.AnyUrl(str(self)) -29 -30 @property -31 def scheme(self) -> str: -32 return self._url.scheme -33 -34 @property -35 def host(self) -> Optional[str]: -36 return self._url.host -37 -38 @property -39 def path(self) -> Optional[str]: -40 return self._url.path -41 -42 @property -43 def parent(self) -> RootHttpUrl: -44 parsed = urlsplit(str(self)) -45 path = list(parsed.path.split("/")) -46 if ( -47 parsed.netloc == "zenodo.org" -48 and parsed.path.startswith("/api/records/") -49 and parsed.path.endswith("/content") -50 ): -51 path[-2:-1] = [] -52 else: -53 path = path[:-1] -54 -55 return RootHttpUrl( -56 urlunsplit( -57 ( -58 parsed.scheme, -59 parsed.netloc, -60 "/".join(path), -61 parsed.query, -62 parsed.fragment, -63 ) -64 ) -65 ) +15 +16class RootHttpUrl( +17 ValidatedString[ +18 Annotated[ +19 str, +20 AfterValidator(lambda value: str(_http_url_adapter.validate_python(value))), +21 ] +22 ], +23 frozen=True, +24): +25 """A 'URL folder', possibly an invalid http URL""" +26 +27 @property +28 def _url(self): +29 return pydantic.AnyUrl(str(self)) +30 +31 @property +32 def scheme(self) -> str: +33 return self._url.scheme +34 +35 @property +36 def host(self) -> Optional[str]: +37 return self._url.host +38 +39 @property +40 def path(self) -> Optional[str]: +41 return self._url.path +42 +43 @property +44 def parent(self) -> RootHttpUrl: +45 parsed = urlsplit(str(self)) +46 path = list(parsed.path.split("/")) +47 if ( +48 parsed.netloc == "zenodo.org" +49 and parsed.path.startswith("/api/records/") +50 and parsed.path.endswith("/content") +51 ): +52 path[-2:-1] = [] +53 else: +54 path = path[:-1] +55 +56 return RootHttpUrl( +57 urlunsplit( +58 ( +59 parsed.scheme, +60 parsed.netloc, +61 "/".join(path), +62 parsed.query, +63 parsed.fragment, +64 ) +65 ) +66 )
- - - -16class RootHttpUrl( -17 ValidatedString[ -18 Annotated[ -19 str, -20 AfterValidator(lambda value: str(_http_url_adapter.validate_python(value))), -21 ] -22 ], -23 frozen=True, -24): -25 """A 'URL folder', possibly an invalid http URL""" -26 -27 @property -28 def _url(self): -29 return pydantic.AnyUrl(str(self)) -30 -31 @property -32 def scheme(self) -> str: -33 return self._url.scheme -34 -35 @property -36 def host(self) -> Optional[str]: -37 return self._url.host -38 -39 @property -40 def path(self) -> Optional[str]: -41 return self._url.path -42 -43 @property -44 def parent(self) -> RootHttpUrl: -45 parsed = urlsplit(str(self)) -46 path = list(parsed.path.split("/")) -47 if ( -48 parsed.netloc == "zenodo.org" -49 and parsed.path.startswith("/api/records/") -50 and parsed.path.endswith("/content") -51 ): -52 path[-2:-1] = [] -53 else: -54 path = path[:-1] -55 -56 return RootHttpUrl( -57 urlunsplit( -58 ( -59 parsed.scheme, -60 parsed.netloc, -61 "/".join(path), -62 parsed.query, -63 parsed.fragment, -64 ) -65 ) -66 ) +@@ -216,9 +217,9 @@17class RootHttpUrl( +18 ValidatedString[ +19 Annotated[ +20 str, +21 AfterValidator(lambda value: str(_http_url_adapter.validate_python(value))), +22 ] +23 ], +24 frozen=True, +25): +26 """A 'URL folder', possibly an invalid http URL""" +27 +28 @property +29 def _url(self): +30 return pydantic.AnyUrl(str(self)) +31 +32 @property +33 def scheme(self) -> str: +34 return self._url.scheme +35 +36 @property +37 def host(self) -> Optional[str]: +38 return self._url.host +39 +40 @property +41 def path(self) -> Optional[str]: +42 return self._url.path +43 +44 @property +45 def parent(self) -> RootHttpUrl: +46 parsed = urlsplit(str(self)) +47 path = list(parsed.path.split("/")) +48 if ( +49 parsed.netloc == "zenodo.org" +50 and parsed.path.startswith("/api/records/") +51 and parsed.path.endswith("/content") +52 ): +53 path[-2:-1] = [] +54 else: +55 path = path[:-1] +56 +57 return RootHttpUrl( +58 urlunsplit( +59 ( +60 parsed.scheme, +61 parsed.netloc, +62 "/".join(path), +63 parsed.query, +64 parsed.fragment, +65 ) +66 ) +67 )
43 @property -44 def parent(self) -> RootHttpUrl: -45 parsed = urlsplit(str(self)) -46 path = list(parsed.path.split("/")) -47 if ( -48 parsed.netloc == "zenodo.org" -49 and parsed.path.startswith("/api/records/") -50 and parsed.path.endswith("/content") -51 ): -52 path[-2:-1] = [] -53 else: -54 path = path[:-1] -55 -56 return RootHttpUrl( -57 urlunsplit( -58 ( -59 parsed.scheme, -60 parsed.netloc, -61 "/".join(path), -62 parsed.query, -63 parsed.fragment, -64 ) -65 ) -66 ) +diff --git a/bioimageio/spec/_internal/types.html b/bioimageio/spec/_internal/types.html index 34b9d514b..84415a3ae 100644 --- a/bioimageio/spec/_internal/types.html +++ b/bioimageio/spec/_internal/types.html @@ -114,19 +114,19 @@44 @property +45 def parent(self) -> RootHttpUrl: +46 parsed = urlsplit(str(self)) +47 path = list(parsed.path.split("/")) +48 if ( +49 parsed.netloc == "zenodo.org" +50 and parsed.path.startswith("/api/records/") +51 and parsed.path.endswith("/content") +52 ): +53 path[-2:-1] = [] +54 else: +55 path = path[:-1] +56 +57 return RootHttpUrl( +58 urlunsplit( +59 ( +60 parsed.scheme, +61 parsed.netloc, +62 "/".join(path), +63 parsed.query, +64 parsed.fragment, +65 ) +66 ) +67 )10from typing_extensions import Annotated, Literal 11 12from .constants import DOI_REGEX, SI_UNIT_REGEX - 13from .field_validation import AfterValidator, BeforeValidator - 14from .io import FileSource as FileSource - 15from .io import ImportantFileSource as ImportantFileSource - 16from .io import PermissiveFileSource as PermissiveFileSource - 17from .io import RelativeFilePath as RelativeFilePath - 18from .io import Sha256 as Sha256 - 19from .io_basics import AbsoluteDirectory as AbsoluteDirectory - 20from .io_basics import AbsoluteFilePath as AbsoluteFilePath - 21from .io_basics import FileName as FileName - 22from .license_id import DeprecatedLicenseId as DeprecatedLicenseId - 23from .license_id import LicenseId as LicenseId - 24from .url import HttpUrl as HttpUrl - 25from .validated_string import ValidatedString + 13from .io import FileSource as FileSource + 14from .io import ImportantFileSource as ImportantFileSource + 15from .io import PermissiveFileSource as PermissiveFileSource + 16from .io import RelativeFilePath as RelativeFilePath + 17from .io import Sha256 as Sha256 + 18from .io_basics import AbsoluteDirectory as AbsoluteDirectory + 19from .io_basics import AbsoluteFilePath as AbsoluteFilePath + 20from .io_basics import FileName as FileName + 21from .license_id import DeprecatedLicenseId as DeprecatedLicenseId + 22from .license_id import LicenseId as LicenseId + 23from .url import HttpUrl as HttpUrl + 24from .validated_string import ValidatedString + 25from .validator_annotations import AfterValidator, BeforeValidator 26from .version_type import Version as Version 27 28S = TypeVar("S", bound=Sequence[Any]) diff --git a/bioimageio/spec/_internal/validated_string.html b/bioimageio/spec/_internal/validated_string.html index 14d90ef4c..734e48965 100644 --- a/bioimageio/spec/_internal/validated_string.html +++ b/bioimageio/spec/_internal/validated_string.html @@ -90,9 +90,6 @@
API Documentation
-- - ValidatedString[Annotated[str, MinLen, AfterValidator, AfterValidator, Annotated[TypeVar, Predicate], MaxLen]]_ -
@@ -735,19 +732,6 @@Inherited Members
- - ValidatedString[Annotated[str, MinLen, AfterValidator, AfterValidator, Annotated[TypeVar, Predicate], MaxLen]]_ = - - <class 'ValidatedString[Annotated[str, MinLen, AfterValidator, AfterValidator, Annotated[TypeVar, Predicate], MaxLen]]'> - - -- - - -