|
1 | 1 | import os |
2 | 2 | import pathlib |
3 | | -import warnings |
4 | | -import zipfile |
5 | 3 | from copy import deepcopy |
6 | | -from hashlib import sha256 |
7 | | -from typing import Dict, IO, Optional, Sequence, Tuple, Union |
| 4 | +from typing import Dict, Optional, Sequence, Union |
8 | 5 | from zipfile import ZIP_DEFLATED, ZipFile |
9 | 6 |
|
10 | 7 | from marshmallow import missing |
11 | 8 |
|
12 | 9 | from bioimageio import spec |
13 | 10 | from bioimageio.core.resource_io.nodes import ResourceDescription |
14 | | -from bioimageio.spec.io_ import RDF_NAMES, resolve_rdf_source |
| 11 | +from bioimageio.spec import load_raw_resource_description |
15 | 12 | from bioimageio.spec.shared import raw_nodes |
16 | 13 | from bioimageio.spec.shared.common import BIOIMAGEIO_CACHE_PATH, get_class_name_from_type |
17 | 14 | from bioimageio.spec.shared.raw_nodes import ResourceDescription as RawResourceDescription |
18 | | -from bioimageio.spec.shared.utils import PathToRemoteUriTransformer |
19 | 15 | from . import nodes |
20 | 16 | from .utils import resolve_raw_resource_description, resolve_source |
21 | 17 |
|
22 | 18 | serialize_raw_resource_description = spec.io_.serialize_raw_resource_description |
23 | 19 | save_raw_resource_description = spec.io_.save_raw_resource_description |
24 | 20 |
|
25 | 21 |
|
26 | | -def extract_resource_package( |
27 | | - source: Union[os.PathLike, IO, str, bytes, raw_nodes.URI] |
28 | | -) -> Tuple[dict, str, pathlib.Path]: |
29 | | - """extract a zip source to BIOIMAGEIO_CACHE_PATH""" |
30 | | - source, source_name, root = resolve_rdf_source(source) |
31 | | - if isinstance(root, bytes): |
32 | | - raise NotImplementedError("package source was bytes") |
33 | | - |
34 | | - cache_folder = BIOIMAGEIO_CACHE_PATH / "extracted_packages" |
35 | | - cache_folder.mkdir(exist_ok=True, parents=True) |
36 | | - |
37 | | - package_path = cache_folder / sha256(str(root).encode("utf-8")).hexdigest() |
38 | | - if isinstance(root, raw_nodes.URI): |
39 | | - for rdf_name in RDF_NAMES: |
40 | | - if (package_path / rdf_name).exists(): |
41 | | - download = None |
42 | | - break |
43 | | - else: |
44 | | - download = resolve_source(root) |
45 | | - |
46 | | - local_source = download |
47 | | - else: |
48 | | - download = None |
49 | | - local_source = root |
50 | | - |
51 | | - if local_source is not None: |
52 | | - with zipfile.ZipFile(local_source) as zf: |
53 | | - zf.extractall(package_path) |
54 | | - |
55 | | - for rdf_name in RDF_NAMES: |
56 | | - if (package_path / rdf_name).exists(): |
57 | | - break |
58 | | - else: |
59 | | - raise FileNotFoundError(f"Missing 'rdf.yaml' in {root} extracted from {download}") |
60 | | - |
61 | | - if download is not None: |
62 | | - try: |
63 | | - os.remove(download) |
64 | | - except Exception as e: |
65 | | - warnings.warn(f"Could not remove download {download} due to {e}") |
66 | | - |
67 | | - assert isinstance(package_path, pathlib.Path) |
68 | | - return source, source_name, package_path |
69 | | - |
70 | | - |
71 | | -def _replace_relative_paths_for_remote_source( |
72 | | - raw_rd: RawResourceDescription, root: Union[pathlib.Path, raw_nodes.URI, bytes] |
73 | | -) -> RawResourceDescription: |
74 | | - if isinstance(root, raw_nodes.URI): |
75 | | - # for a remote source relative paths are invalid; replace all relative file paths in source with URLs |
76 | | - warnings.warn( |
77 | | - f"changing file paths in RDF to URIs due to a remote {root.scheme} source " |
78 | | - "(may result in an invalid node)" |
79 | | - ) |
80 | | - raw_rd = PathToRemoteUriTransformer(remote_source=root).transform(raw_rd) |
81 | | - root_path = pathlib.Path() # root_path cannot be URI |
82 | | - elif isinstance(root, pathlib.Path): |
83 | | - if zipfile.is_zipfile(root): |
84 | | - _, _, root_path = extract_resource_package(root) |
85 | | - else: |
86 | | - root_path = root |
87 | | - elif isinstance(root, bytes): |
88 | | - raise NotImplementedError("root as bytes (io)") |
89 | | - else: |
90 | | - raise TypeError(root) |
91 | | - |
92 | | - assert isinstance(root_path, pathlib.Path) |
93 | | - raw_rd.root_path = root_path.resolve() |
94 | | - return raw_rd |
95 | | - |
96 | | - |
97 | | -def load_raw_resource_description( |
98 | | - source: Union[dict, os.PathLike, IO, str, bytes, raw_nodes.URI, RawResourceDescription], |
99 | | - update_to_format: Optional[str] = "latest", |
100 | | -) -> RawResourceDescription: |
101 | | - """load a raw python representation from a BioImage.IO resource description file (RDF). |
102 | | - Use `load_resource_description` for a more convenient representation. |
103 | | - |
104 | | - Args: |
105 | | - source: resource description file (RDF) |
106 | | - update_to_format: update resource to specific "major.minor" or "latest" format version; ignoring patch version. |
107 | | - |
108 | | - Returns: |
109 | | - raw BioImage.IO resource |
110 | | - """ |
111 | | - if isinstance(source, RawResourceDescription): |
112 | | - return source |
113 | | - |
114 | | - raw_rd = spec.load_raw_resource_description(source, update_to_format=update_to_format) |
115 | | - raw_rd = _replace_relative_paths_for_remote_source(raw_rd, raw_rd.root_path) |
116 | | - return raw_rd |
117 | | - |
118 | | - |
119 | 22 | def load_resource_description( |
120 | 23 | source: Union[RawResourceDescription, ResourceDescription, os.PathLike, str, dict, raw_nodes.URI], |
121 | 24 | *, |
@@ -152,20 +55,23 @@ def load_resource_description( |
152 | 55 |
|
153 | 56 |
|
154 | 57 | def get_local_resource_package_content( |
155 | | - source: RawResourceDescription, weights_priority_order: Optional[Sequence[Union[str]]] |
| 58 | + source: RawResourceDescription, |
| 59 | + weights_priority_order: Optional[Sequence[Union[str]]], |
| 60 | + update_to_format: Optional[str] = None, |
156 | 61 | ) -> Dict[str, Union[pathlib.Path, str]]: |
157 | 62 | """ |
158 | 63 |
|
159 | 64 | Args: |
160 | 65 | source: raw resource description |
161 | 66 | weights_priority_order: If given only the first weights format present in the model is included. |
162 | 67 | If none of the prioritized weights formats is found all are included. |
| 68 | + update_to_format: update resource to specific major.minor format version; ignoring patch version. |
163 | 69 |
|
164 | 70 | Returns: |
165 | 71 | Package content of local file paths or text content keyed by file names. |
166 | 72 |
|
167 | 73 | """ |
168 | | - raw_rd = load_raw_resource_description(source) |
| 74 | + raw_rd = load_raw_resource_description(source, update_to_format=update_to_format) |
169 | 75 | package_content = spec.get_resource_package_content(raw_rd, weights_priority_order=weights_priority_order) |
170 | 76 |
|
171 | 77 | local_package_content = {} |
@@ -205,7 +111,9 @@ def export_resource_package( |
205 | 111 | path to zipped BioImage.IO package in BIOIMAGEIO_CACHE_PATH or 'output_path' |
206 | 112 | """ |
207 | 113 | raw_rd = load_raw_resource_description(source, update_to_format=update_to_format) |
208 | | - package_content = get_local_resource_package_content(raw_rd, weights_priority_order) |
| 114 | + package_content = get_local_resource_package_content( |
| 115 | + raw_rd, weights_priority_order, update_to_format=update_to_format |
| 116 | + ) |
209 | 117 | if output_path is None: |
210 | 118 | package_path = _get_tmp_package_path(raw_rd, weights_priority_order) |
211 | 119 | else: |
|
0 commit comments