Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.5.1 #567

Merged
merged 42 commits into from
Mar 21, 2024
Merged

0.5.1 #567

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f869c2b
add default insertion of ensure_dtype procs
FynnBe Mar 18, 2024
ffdf91d
bump patch version
FynnBe Mar 18, 2024
ce6ee00
Merge branch 'main' into ensure_dtype
FynnBe Mar 18, 2024
55a0104
remove wasm32 specific code
FynnBe Mar 18, 2024
3974ba5
reformat long line
FynnBe Mar 18, 2024
80a40f3
get_tensor_sizes -> get_axis_sizes
FynnBe Mar 18, 2024
b96190a
split return of `get_axis_sizes` into input and output tensors
FynnBe Mar 18, 2024
0c944d9
add ensure_dtype in example to make roundtrip test pass
FynnBe Mar 18, 2024
caefb30
Update bioimageio/spec/model/v0_5.py
FynnBe Mar 19, 2024
618a434
Merge branch 'main' into ensure_dtype
FynnBe Mar 19, 2024
557fc25
add BinarizeAlongAxisKwargs
FynnBe Mar 19, 2024
2b46614
refactor ScaleLinearKwargs and FixedZeroMeanUnitVarianceKwargs
FynnBe Mar 19, 2024
1949ba5
update changelog
FynnBe Mar 19, 2024
d1dc684
check bioimageio_cache_path env var
FynnBe Mar 19, 2024
7c66486
restrict valid characters for resource ids
FynnBe Mar 19, 2024
ac1d4c1
Merge pull request #569 from bioimage-io/add_cache_path_env_var
FynnBe Mar 19, 2024
b11afb6
fix conversion of fixed zero mean unit variance
FynnBe Mar 19, 2024
12a983e
fix _get_complement_v04_axis
FynnBe Mar 19, 2024
1f210b0
add docstring
FynnBe Mar 19, 2024
8c9b7fe
mark 10.5281/zenodo.7274275/8123818/rdf.yaml as invalid as latest
FynnBe Mar 19, 2024
4c558fb
move resource id types to their respective submodules
FynnBe Mar 19, 2024
58b53c6
Merge pull request #568 from bioimage-io/binarize_along_axis
FynnBe Mar 19, 2024
f699cb9
fix test_specific_reexports_generics
FynnBe Mar 19, 2024
d4ec591
allow dots in ids
FynnBe Mar 19, 2024
4273180
update git_repo urls in tests
FynnBe Mar 19, 2024
d777407
fix license unions
FynnBe Mar 19, 2024
6cb2cf7
make ValidatedString inherite from str
FynnBe Mar 19, 2024
ea40629
fix root_model annotations
FynnBe Mar 20, 2024
11b996a
fix _ValidatedString.validated
FynnBe Mar 20, 2024
3346152
fix test_specific_reexports_generics
FynnBe Mar 20, 2024
40f36a4
avoid pydantic warning
FynnBe Mar 21, 2024
830547c
refactor internal bioimageio.yaml file name helpers
FynnBe Mar 21, 2024
e4cd976
expose is_valid_bioimageio_yaml_name
FynnBe Mar 21, 2024
7a52fe8
include local badges in package
FynnBe Mar 21, 2024
879c33d
expose VALID_COVER_IMAGE_EXTENSIONS in subspecs
FynnBe Mar 21, 2024
9690db3
fix test_specific_reexports_generics
FynnBe Mar 21, 2024
d48430b
update license examples
FynnBe Mar 21, 2024
eb4af73
fix test_types
FynnBe Mar 21, 2024
74d6586
Merge branch 'ensure_dtype' into stricter_id_validation
FynnBe Mar 21, 2024
7e6a621
remove cyclic imports
FynnBe Mar 21, 2024
1e29939
fix test_license_id_in_model
FynnBe Mar 21, 2024
119b8d7
Merge pull request #570 from bioimage-io/stricter_id_validation
FynnBe Mar 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ or
pip install -U bioimageio.core
```

## 🏞 Environment variables

TODO: link to settings in dev docs

## 🤝 How to contribute

## ♥ Contributors
Expand All @@ -85,6 +89,10 @@ Made with [contrib.rocks](https://contrib.rocks).

### bioimageio.spec Python package

#### bioimageio.spec 0.5.1

* new patch version model 0.5.1

#### bioimageio.spec 0.5.0post2

* don't fail if CI env var is a string
Expand Down Expand Up @@ -228,11 +236,13 @@ Made with [contrib.rocks](https://contrib.rocks).

### Resource Description Format Versions

#### model 0.5.1 (planned)
#### model 0.5.1

* Non-breaking changes
* added `DataDependentSize` for `outputs.i.size` to specify an output shape that is not known before inference is run.
* added optional `inputs.i.optional` field to indicate that a tensor may be `None`
* made data type assumptions in `preprocessing` and `postprocessing` explicit by adding `'ensure_dtype'` operations per default.
* allow to specify multiple thresholds (along an `axis`) in a 'binarize' processing step

#### generic 0.3.0 / application 0.3.0 / collection 0.3.0 / dataset 0.3.0 / notebook 0.3.0

Expand Down
2 changes: 1 addition & 1 deletion bioimageio/spec/VERSION
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "0.5.0post2"
"version": "0.5.1"
}
1 change: 1 addition & 0 deletions bioimageio/spec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from ._description import build_description as build_description
from ._description import dump_description as dump_description
from ._description import validate_format as validate_format
from ._internal import settings as settings
from ._internal.common_nodes import InvalidDescr as InvalidDescr
from ._internal.constants import VERSION
from ._internal.validation_context import ValidationContext as ValidationContext
Expand Down
5 changes: 5 additions & 0 deletions bioimageio/spec/_internal/_settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from pathlib import Path
from typing import Optional, Union

import pooch
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
from typing_extensions import Annotated
Expand Down Expand Up @@ -33,6 +35,9 @@ class Settings(BaseSettings, extra="ignore"):
user_agent: Optional[str] = None
"""user agent for http requests"""

cache_path: Path = pooch.os_cache("bioimageio")
"""bioimageio cache location"""

@property
def github_auth(self):
if self.github_username is None or self.github_token is None:
Expand Down
8 changes: 4 additions & 4 deletions bioimageio/spec/_internal/field_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@

import requests

from bioimageio.spec._internal._settings import settings
from bioimageio.spec._internal.constants import KNOWN_GH_USERS, KNOWN_INVALID_GH_USERS
from bioimageio.spec._internal.field_warning import issue_warning
from bioimageio.spec._internal.validation_context import validation_context_var
from ._settings import settings
from .constants import KNOWN_GH_USERS, KNOWN_INVALID_GH_USERS
from .field_warning import issue_warning
from .validation_context import validation_context_var


def is_valid_yaml_leaf_value(value: Any) -> bool:
Expand Down
81 changes: 62 additions & 19 deletions bioimageio/spec/_internal/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
from pathlib import Path, PurePath
from typing import (
Any,
ClassVar,
Dict,
Generic,
Iterable,
List,
Optional,
Sequence,
Expand All @@ -22,6 +24,7 @@
Union,
)
from urllib.parse import urlparse, urlsplit, urlunsplit
from zipfile import ZipFile, is_zipfile

import pooch
import pydantic
Expand Down Expand Up @@ -52,6 +55,7 @@
from .._internal._settings import settings
from .._internal.io_basics import (
ALL_BIOIMAGEIO_YAML_NAMES,
ALTERNATIVE_BIOIMAGEIO_YAML_NAMES,
BIOIMAGEIO_YAML,
AbsoluteDirectory,
AbsoluteFilePath,
Expand All @@ -73,18 +77,17 @@
SLOTS = {"slots": True}


class Sha256(
ValidatedString[
class Sha256(ValidatedString):
"""SHA-256 hash value"""

root_model: ClassVar[Type[RootModel[Any]]] = RootModel[
Annotated[
str,
StringConstraints(
strip_whitespace=True, to_lower=True, min_length=64, max_length=64
),
]
],
frozen=True,
):
"""SHA-256 hash value"""
]


AbsolutePathT = TypeVar(
Expand Down Expand Up @@ -303,7 +306,7 @@ def validate(self, value: FileSource) -> FileSource:


def wo_special_file_name(src: FileSource) -> FileSource:
if has_valid_rdf_name(src):
if has_valid_bioimageio_yaml_name(src):
raise ValueError(
f"'{src}' not allowed here as its filename is reserved to identify"
+ f" '{BIOIMAGEIO_YAML}' (or equivalent) files."
Expand All @@ -323,7 +326,7 @@ def _package(value: FileSource, info: SerializationInfo) -> Union[str, Path, Fil
if isinstance(value, Path):
unpackaged = value
elif isinstance(value, HttpUrl):
unpackaged = value.root
unpackaged = value
elif isinstance(value, RelativeFilePath):
unpackaged = Path(value.path)
elif isinstance(value, AnyUrl):
Expand Down Expand Up @@ -395,22 +398,60 @@ def _package(value: FileSource, info: SerializationInfo) -> Union[str, Path, Fil
AfterValidator(wo_special_file_name),
include_in_package_serializer,
]
InPackageIfLocalFileSource = Union[
Annotated[
Union[FilePath, RelativeFilePath],
AfterValidator(wo_special_file_name),
include_in_package_serializer,
],
Union[HttpUrl, pydantic.HttpUrl],
]


def has_valid_rdf_name(src: FileSource) -> bool:
return is_valid_rdf_name(extract_file_name(src))
def has_valid_bioimageio_yaml_name(src: FileSource) -> bool:
return is_valid_bioimageio_yaml_name(extract_file_name(src))


def is_valid_rdf_name(file_name: FileName) -> bool:
for special in ALL_BIOIMAGEIO_YAML_NAMES:
if file_name.endswith(special):
def is_valid_bioimageio_yaml_name(file_name: FileName) -> bool:
for bioimageio_name in ALL_BIOIMAGEIO_YAML_NAMES:
if file_name == bioimageio_name or file_name.endswith("." + bioimageio_name):
return True

return False


def ensure_has_valid_rdf_name(src: FileSource) -> FileSource:
if not has_valid_rdf_name(src):
def identify_bioimageio_yaml_file_name(file_names: Iterable[FileName]) -> FileName:
file_names = sorted(file_names)
for bioimageio_name in ALL_BIOIMAGEIO_YAML_NAMES:
for file_name in file_names:
if file_name == bioimageio_name or file_name.endswith(
"." + bioimageio_name
):
return file_name

raise ValueError(
f"No {BIOIMAGEIO_YAML} found in {file_names}. (Looking for '{BIOIMAGEIO_YAML}'"
+ " or or any of the alterntive file names:"
+ f" {ALTERNATIVE_BIOIMAGEIO_YAML_NAMES}, or any file with an extension of"
+ f" those, e.g. 'anything.{BIOIMAGEIO_YAML}')."
)


def find_bioimageio_yaml_file_name(path: Path) -> FileName:
if path.is_file():
if not is_zipfile(path):
return path.name

with ZipFile(path, "r") as f:
file_names = identify_bioimageio_yaml_file_name(f.namelist())
else:
file_names = [p.name for p in path.glob("*")]

return identify_bioimageio_yaml_file_name(file_names)


def ensure_has_valid_bioimageio_yaml_name(src: FileSource) -> FileSource:
if not has_valid_bioimageio_yaml_name(src):
raise ValueError(
f"'{src}' does not have a valid filename to identify"
+ f" '{BIOIMAGEIO_YAML}' (or equivalent) files."
Expand All @@ -419,8 +460,8 @@ def ensure_has_valid_rdf_name(src: FileSource) -> FileSource:
return src


def ensure_is_valid_rdf_name(file_name: FileName) -> FileName:
if not is_valid_rdf_name(file_name):
def ensure_is_valid_bioimageio_yaml_name(file_name: FileName) -> FileName:
if not is_valid_bioimageio_yaml_name(file_name):
raise ValueError(
f"'{file_name}' is not a valid filename to identify"
+ f" '{BIOIMAGEIO_YAML}' (or equivalent) files."
Expand Down Expand Up @@ -448,14 +489,14 @@ def ensure_is_valid_rdf_name(file_name: FileName) -> FileName:
class OpenedBioimageioYaml:
content: BioimageioYamlContent
original_root: Union[AbsoluteDirectory, RootHttpUrl]
original_file_name: str
original_file_name: FileName


@dataclass
class DownloadedFile:
path: FilePath
original_root: Union[AbsoluteDirectory, RootHttpUrl]
original_file_name: str
original_file_name: FileName


class HashKwargs(TypedDict):
Expand Down Expand Up @@ -502,6 +543,7 @@ def download(
/,
**kwargs: Unpack[HashKwargs],
) -> DownloadedFile:
"""download `source` URL (or pass local file path)"""
if isinstance(source, FileDescr):
return source.download()

Expand Down Expand Up @@ -533,6 +575,7 @@ def download(
known_hash=_get_known_hash(kwargs),
downloader=downloader,
fname=fname,
path=settings.cache_path,
)
local_source = Path(_ls).absolute()
root = strict_source.parent
Expand Down
4 changes: 2 additions & 2 deletions bioimageio/spec/_internal/io_basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
AbsoluteDirectory = Annotated[DirectoryPath, Predicate(Path.is_absolute)]
AbsoluteFilePath = Annotated[FilePath, Predicate(Path.is_absolute)]

BIOIMAGEIO_YAML = "rdf.yaml"
ALTERNATIVE_BIOIMAGEIO_YAML_NAMES = ("bioimageio.yaml", "model.yaml")
BIOIMAGEIO_YAML = "bioimageio.yaml"
ALTERNATIVE_BIOIMAGEIO_YAML_NAMES = ("rdf.yaml", "model.yaml")
ALL_BIOIMAGEIO_YAML_NAMES = (BIOIMAGEIO_YAML,) + ALTERNATIVE_BIOIMAGEIO_YAML_NAMES
41 changes: 3 additions & 38 deletions bioimageio/spec/_internal/io_utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import io
import platform
import warnings
from contextlib import nullcontext
from pathlib import Path
from typing import IO, Any, Dict, Iterable, Mapping, Optional, TextIO, Union, cast
from typing import IO, Any, Dict, Mapping, Optional, TextIO, Union, cast
from zipfile import ZipFile, is_zipfile

import numpy
Expand All @@ -13,24 +12,18 @@
from typing_extensions import Unpack

from .io import (
ALL_BIOIMAGEIO_YAML_NAMES,
BIOIMAGEIO_YAML,
BioimageioYamlContent,
FileDescr,
HashKwargs,
OpenedBioimageioYaml,
YamlValue,
download,
find_bioimageio_yaml_file_name,
)
from .io_basics import ALTERNATIVE_BIOIMAGEIO_YAML_NAMES, FileName
from .io_basics import FileName
from .types import FileSource, PermissiveFileSource

if platform.machine() == "wasm32":
import pyodide_http # type: ignore

pyodide_http.patch_all()


yaml = YAML(typ="safe")


Expand Down Expand Up @@ -91,34 +84,6 @@ def open_bioimageio_yaml(
return OpenedBioimageioYaml(content, root, downloaded.original_file_name)


def identify_bioimageio_yaml_file_name(file_names: Iterable[FileName]) -> FileName:
file_names = sorted(file_names)
for bioimageio_name in ALL_BIOIMAGEIO_YAML_NAMES:
for fname in file_names:
if fname == bioimageio_name or fname.endswith(f".{bioimageio_name}"):
return fname

raise ValueError(
f"No {BIOIMAGEIO_YAML} found in {file_names}. (Looking for '{BIOIMAGEIO_YAML}'"
+ " or or any of the alterntive file names:"
+ f" {ALTERNATIVE_BIOIMAGEIO_YAML_NAMES}, or any file with an extension of"
+ f" those, e.g. 'anything.{BIOIMAGEIO_YAML}')."
)


def find_bioimageio_yaml_file_name(path: Path) -> FileName:
if path.is_file():
if not is_zipfile(path):
return path.name

with ZipFile(path, "r") as f:
file_names = identify_bioimageio_yaml_file_name(f.namelist())
else:
file_names = [p.name for p in path.glob("*")]

return identify_bioimageio_yaml_file_name(file_names)


def unzip(
zip_file: Union[FilePath, ZipFile],
out_path: Optional[DirectoryPath] = None,
Expand Down
21 changes: 7 additions & 14 deletions bioimageio/spec/_internal/license_id.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
from typing import TypeVar
from typing import Any, ClassVar, Type

from pydantic import RootModel

from ._generated_spdx_license_literals import (
DeprecatedLicenseId as DeprecatedLicenseIdLiteral,
)
from ._generated_spdx_license_literals import LicenseId as LicenseIdLiteral
from .validated_string import ValidatedString

LicenceT = TypeVar("LicenceT", LicenseIdLiteral, DeprecatedLicenseIdLiteral)


class _LicenseId(ValidatedString[LicenceT], frozen=True):
def __repr__(self):
# don't include full literal in class repr
name, *_ = self.__class__.__name__.split("[")
return f'{name}("{self.root}")'


class DeprecatedLicenseId(_LicenseId[DeprecatedLicenseIdLiteral], frozen=True):
pass
class LicenseId(ValidatedString):
root_model: ClassVar[Type[RootModel[Any]]] = RootModel[LicenseIdLiteral]


class LicenseId(_LicenseId[LicenseIdLiteral], frozen=True):
pass
class DeprecatedLicenseId(ValidatedString):
root_model: ClassVar[Type[RootModel[Any]]] = RootModel[DeprecatedLicenseIdLiteral]
Loading
Loading