Coverage for src/bioimageio/core/_description_serializer.py: 0%
44 statements
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-22 16:54 +0000
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-22 16:54 +0000
1import base64
2import hashlib
3from io import BytesIO
4from typing import Tuple
5from zipfile import ZipFile
7from bioimageio.spec import (
8 InvalidDescr,
9 ResourceDescr,
10 load_description,
11 save_bioimageio_package_to_stream,
12)
13from bioimageio.spec.common import Sha256
16class DescriptionSerializer:
17 """Description serializer intended for client/server communication, NOT for sharing resource descriptions.
19 This serializer only includes local files to keep the serialized package small.
20 """
22 STRING_ENCODING = "ascii"
24 @staticmethod
25 def serialize(rd: ResourceDescr) -> bytes:
26 stream = save_bioimageio_package_to_stream(rd, local_files_only=True)
27 _ = stream.seek(0)
28 return stream.read()
30 @classmethod
31 def serialize_to_string(cls, rd: ResourceDescr) -> str:
32 package_bytes = cls.serialize(rd)
34 safe_bytes = cls._get_safe_bytes(package_bytes)
35 serialized_str = safe_bytes.decode(cls.STRING_ENCODING)
36 if len(serialized_str) <= 2083:
37 raise RuntimeError(
38 "Serialized model description should be longer than 2083 characters to not be treated as a URL on the server side."
39 )
40 return serialized_str
42 @staticmethod
43 def _get_safe_bytes(raw_bytes: bytes) -> bytes:
44 return base64.b64encode(raw_bytes)
46 @classmethod
47 def deserialize_from_string(cls, serialized: str) -> ResourceDescr:
48 package_bytes = base64.b64decode(serialized.encode(cls.STRING_ENCODING))
49 return cls.deserialize(package_bytes)
51 @staticmethod
52 def deserialize(serialized: bytes) -> ResourceDescr:
53 descr = load_description(ZipFile(BytesIO(serialized)), perform_io_checks=False)
54 if isinstance(descr, InvalidDescr):
55 raise ValueError(f"invalid serialized model package: {descr.get_reason()}")
57 return descr
59 @classmethod
60 def serialize_to_string_and_hash(cls, rd: ResourceDescr) -> Tuple[str, Sha256]:
61 package_bytes = cls.serialize(rd)
62 safe_bytes = cls._get_safe_bytes(package_bytes)
63 serialized_str = safe_bytes.decode(cls.STRING_ENCODING)
64 if len(serialized_str) <= 2083:
65 raise RuntimeError(
66 "Serialized model description should be longer than 2083 characters to not be treated as a URL on the server side."
67 )
68 sha256 = Sha256(hashlib.sha256(package_bytes).hexdigest())
69 return serialized_str, sha256