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

Support ZipFile IO #640

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ To keep the bioimageio.spec Python package version in sync with the (model) desc

### bioimageio.spec Python package

#### bioimageio.spec 0.5.3.4 (to be released)

* support loading and saving from/to zipfile.ZipFile objects
* fix bug when packaging with weights priority order (#638)
* add conda_env module providing helper to create recommended conda environments for model descriptions
* fix summary formatting
* improve logged origin for logged messages
* make the `model.v0_5.ModelDescr.training_data` field a `left_to_right` Union to avoid warnings

#### bioimageio.spec 0.5.3.3

* expose `progressbar` to customize display of download progress
Expand Down
67 changes: 61 additions & 6 deletions bioimageio/spec/_internal/common_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import collections.abc
import traceback
import zipfile
from abc import ABC, abstractmethod
from copy import deepcopy
from io import BytesIO
from pathlib import Path
from typing import (
IO,
TYPE_CHECKING,
Any,
ClassVar,
Expand All @@ -21,6 +25,7 @@
cast,
get_type_hints,
)
from zipfile import ZipFile

import pydantic
from pydantic import (
Expand Down Expand Up @@ -52,9 +57,15 @@
)
from .field_warning import issue_warning
from .io import BioimageioYamlContent
from .io_basics import BIOIMAGEIO_YAML, AbsoluteFilePath, FileName
from .io_utils import write_content_to_zip
from .node import Node as Node
from .packaging_context import PackagingContext
from .url import HttpUrl
from .utils import assert_all_params_set_explicitly, get_format_version_tuple
from .utils import (
assert_all_params_set_explicitly,
get_format_version_tuple,
)
from .validation_context import (
ValidationContext,
validation_context_var,
Expand Down Expand Up @@ -242,7 +253,7 @@ def set_fields_explicitly(
call_default_factory=True
)

return data
return data # pyright: ignore[reportUnknownVariableType]


if TYPE_CHECKING:
Expand Down Expand Up @@ -287,12 +298,12 @@ def _ignore_future_patch(cls, data: Union[Dict[Any, Any], Any], /) -> Any:
or not isinstance(data, dict)
or "format_version" not in data
):
return data
return data # pyright: ignore[reportUnknownVariableType]

value = data["format_version"]
value: Any = data["format_version"]
fv = get_format_version_tuple(value)
if fv is None:
return data
return data # pyright: ignore[reportUnknownVariableType]

if (
fv[0] == cls.implemented_format_version_tuple[0]
Expand All @@ -306,7 +317,7 @@ def _ignore_future_patch(cls, data: Union[Dict[Any, Any], Any], /) -> Any:
)
data["format_version"] = cls.implemented_format_version

return data
return data # pyright: ignore[reportUnknownVariableType]

@model_validator(mode="after")
def _set_init_validation_summary(self) -> Self:
Expand Down Expand Up @@ -450,6 +461,50 @@ def _load_impl(

return rd, val_errors, val_warnings

def package(
self, dest: Optional[Union[ZipFile, IO[bytes], Path, str]] = None, /
) -> ZipFile:
"""package the described resource as a zip archive

Args:
dest: (path/bytes stream of) destination zipfile
"""
if dest is None:
dest = BytesIO()

if isinstance(dest, ZipFile):
zip = dest
if "r" in zip.mode:
raise ValueError(
f"zip file {dest} opened in '{zip.mode}' mode,"
+ " but write access is needed for packaging."
)
else:
zip = ZipFile(dest, mode="w")

content = self.get_package_content()
write_content_to_zip(content, zip)
return zip

def get_package_content(
self,
) -> Dict[
FileName, Union[HttpUrl, AbsoluteFilePath, BioimageioYamlContent, zipfile.Path]
]:
"""Returns package content without creating the package."""
content: Dict[FileName, Union[HttpUrl, AbsoluteFilePath, zipfile.Path]] = {}
with PackagingContext(
bioimageio_yaml_file_name=BIOIMAGEIO_YAML,
file_sources=content,
):
rdf_content: BioimageioYamlContent = self.model_dump(
mode="json", exclude_unset=True
)

_ = rdf_content.pop("rdf_source", None)

return {**content, BIOIMAGEIO_YAML: rdf_content}


class InvalidDescr(
ResourceDescrBase,
Expand Down
Loading
Loading