eotdl 2023.10.25.post10__py3-none-any.whl → 2023.11.2.post2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. eotdl/__init__.py +1 -1
  2. eotdl/cli.py +6 -2
  3. eotdl/commands/auth.py +18 -1
  4. eotdl/commands/datasets.py +61 -11
  5. eotdl/commands/models.py +108 -0
  6. eotdl/curation/__init__.py +1 -4
  7. eotdl/curation/stac/assets.py +2 -1
  8. eotdl/curation/stac/dataframe.py +1 -1
  9. eotdl/curation/stac/extensions/label/image_name_labeler.py +6 -5
  10. eotdl/curation/stac/extensions/ml_dataset.py +15 -25
  11. eotdl/curation/stac/extent.py +1 -1
  12. eotdl/curation/stac/stac.py +1 -1
  13. eotdl/datasets/download.py +5 -4
  14. eotdl/datasets/ingest.py +25 -154
  15. eotdl/datasets/retrieve.py +1 -1
  16. eotdl/files/__init__.py +1 -0
  17. eotdl/files/ingest.py +175 -0
  18. eotdl/models/__init__.py +3 -0
  19. eotdl/models/download.py +119 -0
  20. eotdl/models/ingest.py +47 -0
  21. eotdl/models/metadata.py +16 -0
  22. eotdl/models/retrieve.py +26 -0
  23. eotdl/repos/FilesAPIRepo.py +136 -95
  24. eotdl/repos/ModelsAPIRepo.py +40 -0
  25. eotdl/repos/__init__.py +1 -0
  26. eotdl/shared/__init__.py +1 -0
  27. eotdl/tools/__init__.py +5 -6
  28. eotdl/tools/geo_utils.py +15 -1
  29. eotdl/tools/stac.py +144 -8
  30. eotdl/tools/time_utils.py +19 -6
  31. eotdl/tools/tools.py +2 -3
  32. {eotdl-2023.10.25.post10.dist-info → eotdl-2023.11.2.post2.dist-info}/METADATA +1 -1
  33. {eotdl-2023.10.25.post10.dist-info → eotdl-2023.11.2.post2.dist-info}/RECORD +38 -35
  34. eotdl/curation/folder_formatters/__init__.py +0 -1
  35. eotdl/curation/folder_formatters/base.py +0 -19
  36. eotdl/curation/folder_formatters/sentinel_hub.py +0 -135
  37. eotdl/curation/stac/utils/__init__.py +0 -5
  38. eotdl/curation/stac/utils/geometry.py +0 -22
  39. eotdl/curation/stac/utils/stac.py +0 -143
  40. eotdl/curation/stac/utils/time.py +0 -21
  41. /eotdl/{datasets/utils.py → shared/checksum.py} +0 -0
  42. /eotdl/{curation/stac/utils → tools}/metadata.py +0 -0
  43. /eotdl/{curation/stac/utils → tools}/paths.py +0 -0
  44. {eotdl-2023.10.25.post10.dist-info → eotdl-2023.11.2.post2.dist-info}/WHEEL +0 -0
  45. {eotdl-2023.10.25.post10.dist-info → eotdl-2023.11.2.post2.dist-info}/entry_points.txt +0 -0
eotdl/datasets/ingest.py CHANGED
@@ -1,13 +1,10 @@
1
1
  from pathlib import Path
2
- from glob import glob
3
2
  import yaml
4
- from tqdm import tqdm
5
- import os
6
3
 
7
4
  from ..auth import with_auth
8
5
  from .metadata import Metadata
9
- from ..repos import DatasetsAPIRepo, FilesAPIRepo
10
- from .utils import calculate_checksum
6
+ from ..repos import DatasetsAPIRepo
7
+ from ..files import ingest_files
11
8
 
12
9
 
13
10
  def ingest_dataset(path, verbose=False, logger=print):
@@ -19,160 +16,34 @@ def ingest_dataset(path, verbose=False, logger=print):
19
16
  return ingest_folder(path, verbose, logger)
20
17
 
21
18
 
19
+ def retrieve_dataset(metadata, user):
20
+ repo = DatasetsAPIRepo()
21
+ data, error = repo.retrieve_dataset(metadata.name)
22
+ # print(data, error)
23
+ if data and data["uid"] != user["sub"]:
24
+ raise Exception("Dataset already exists.")
25
+ if error and error == "Dataset doesn't exist":
26
+ # create dataset
27
+ data, error = repo.create_dataset(metadata.dict(), user["id_token"])
28
+ # print(data, error)
29
+ if error:
30
+ raise Exception(error)
31
+ data["id"] = data["dataset_id"]
32
+ return data["id"]
33
+
34
+
22
35
  @with_auth
23
36
  def ingest_folder(folder, verbose=False, logger=print, user=None):
24
- repo, files_repo = DatasetsAPIRepo(), FilesAPIRepo()
25
- logger(f"Uploading directory {folder}...")
26
- # get all files in directory recursively
27
- items = [Path(item) for item in glob(str(folder) + "/**/*", recursive=True)]
28
- # remove directories
29
- items = [item for item in items if not item.is_dir()]
30
- if len(items) == 0:
31
- raise Exception("No files found in directory")
32
- if not any(item.name == "metadata.yml" for item in items):
33
- raise Exception("metadata.yml not found in directory")
37
+ repo = DatasetsAPIRepo()
34
38
  # load metadata
35
39
  metadata = yaml.safe_load(open(folder.joinpath("metadata.yml"), "r").read()) or {}
36
40
  metadata = Metadata(**metadata)
37
- # remove metadata.yml from files
38
- items = [item for item in items if item.name != "metadata.yml"]
39
- # if zip or tar file, send error
40
- if any(item.suffix.endswith((".zip", ".tar", ".tar.gz", ".gz")) for item in items):
41
- raise Exception(
42
- f"At least one zip, tar or gz file found in {folder}, please unzip and try again"
43
- )
44
- # create dataset
45
- data, error = repo.create_dataset(metadata.dict(), user["id_token"])
46
- # dataset may already exist, and will return an error, but if user is owner continue ingesting files
47
- current_files = []
48
- if error:
49
- data, error2 = repo.retrieve_dataset(metadata.name)
50
- if error2:
51
- raise Exception(error)
52
- if data["uid"] != user["sub"]:
53
- raise Exception("Dataset already exists.")
54
- data["dataset_id"] = data["id"]
55
- dataset_id = data["dataset_id"]
56
- # create new version
57
- data, error = repo.create_version(dataset_id, user["id_token"])
58
- if error:
59
- raise Exception(error)
60
- version = data["version"]
61
- # upload files
62
- current_files = []
63
- if version > 1:
64
- current_files, error = files_repo.retrieve_dataset_files(
65
- dataset_id, version - 1
66
- )
67
- if error:
68
- # print("retreive dataset files error: ", error)
69
- current_files = []
70
- for item in tqdm(items, desc="Uploading files", unit="files", disable=verbose):
71
- data = ingest_file(
72
- str(item),
73
- dataset_id,
74
- version,
75
- str(item.relative_to(folder).parent),
76
- logger=logger,
77
- verbose=verbose,
78
- user=user,
79
- current_files=current_files,
80
- )
81
- return data
82
-
83
-
84
- def ingest_file(
85
- file,
86
- dataset_id,
87
- version,
88
- parent,
89
- logger=None,
90
- verbose=True,
91
- root=None,
92
- user=None,
93
- current_files=[],
94
- ):
95
- id_token = user["id_token"]
96
- if verbose:
97
- logger(f"Uploading file {file}...")
98
- repo = FilesAPIRepo()
99
- if file.startswith("http://") or file.startswith("https://"):
100
- raise NotImplementedError("URL ingestion not implemented yet")
101
- # data, error = repo.ingest_file_url(file, dataset_id, id_token)
102
- else:
103
- file_path = Path(file)
104
- if not file_path.is_absolute():
105
- # file_path = glob(
106
- # str(root) + "/**/" + os.path.basename(file_path),
107
- # recursive=True,
108
- # )
109
- # if len(file_path) == 0:
110
- # raise Exception(f"File {file} not found")
111
- # elif len(file_path) > 1:
112
- # raise Exception(f"Multiple files found for {file}")
113
- # file_path = file_path[0]
114
- file_path = str(file_path.absolute())
115
- if verbose:
116
- logger("Computing checksum...")
117
- checksum = calculate_checksum(file_path)
118
- # check if file already exists in dataset
119
- filename = os.path.basename(file_path)
120
- if parent != ".":
121
- filename = parent + "/" + filename
122
- if len(current_files) > 0:
123
- matches = [
124
- f
125
- for f in current_files
126
- if f["filename"] == filename and f["checksum"] == checksum
127
- ] # this could slow down ingestion in large datasets... should think of faster search algos, puede que sea mejor hacer el re-upload simplemente...
128
- if len(matches) == 1:
129
- if verbose:
130
- print(f"File {file_path} already exists in dataset, skipping...")
131
- data, error = repo.ingest_existing_file(
132
- filename,
133
- dataset_id,
134
- version,
135
- matches[0]["version"],
136
- id_token,
137
- checksum,
138
- )
139
- if error:
140
- raise Exception(error)
141
- if verbose:
142
- logger("Done")
143
- return data
144
- if verbose:
145
- logger("Ingesting file...")
146
- filesize = os.path.getsize(file_path)
147
- # ingest small file
148
- if filesize < 1024 * 1024 * 16: # 16 MB
149
- data, error = repo.ingest_file(
150
- file_path,
151
- dataset_id,
152
- version,
153
- parent,
154
- id_token,
155
- checksum,
156
- )
157
- if error:
158
- raise Exception(error)
159
- if verbose:
160
- logger("Done")
161
- return data
162
- raise NotImplementedError("Large file ingestion not implemented yet")
163
- # # ingest large file
164
- # upload_id, parts = repo.prepare_large_upload(
165
- # file_path, dataset_id, checksum, id_token
166
- # )
167
- # repo.ingest_large_dataset(file_path, upload_id, id_token, parts)
168
- # if verbose:
169
- # logger("\nCompleting upload...")
170
- # data, error = repo.complete_upload(id_token, upload_id)
171
- if error:
172
- raise Exception(error)
173
- if verbose:
174
- logger("Done")
175
- return data
41
+ # retrieve dataset (create if doesn't exist)
42
+ dataset_id = retrieve_dataset(metadata, user)
43
+ # ingest files
44
+ return ingest_files(
45
+ repo, dataset_id, folder, verbose, logger, user, endpoint="datasets"
46
+ )
176
47
 
177
48
 
178
49
  # @with_auth
@@ -20,7 +20,7 @@ def retrieve_dataset(name):
20
20
 
21
21
  def retrieve_dataset_files(dataset_id, version):
22
22
  repo = FilesAPIRepo()
23
- data, error = repo.retrieve_dataset_files(dataset_id, version)
23
+ data, error = repo.retrieve_files(dataset_id, "datasets", version)
24
24
  if error:
25
25
  raise Exception(error)
26
26
  return data
@@ -0,0 +1 @@
1
+ from .ingest import ingest_files
eotdl/files/ingest.py ADDED
@@ -0,0 +1,175 @@
1
+ from pathlib import Path
2
+ import os
3
+ from tqdm import tqdm
4
+ import zipfile
5
+ import io
6
+ from glob import glob
7
+ import os
8
+
9
+ from ..repos import FilesAPIRepo
10
+ from ..shared import calculate_checksum
11
+ from ..shared import calculate_checksum
12
+
13
+
14
+ def retrieve_files(folder):
15
+ # get all files in directory recursively
16
+ items = [Path(item) for item in glob(str(folder) + "/**/*", recursive=True)]
17
+ if not any(item.name == "metadata.yml" for item in items):
18
+ raise Exception("metadata.yml not found in directory")
19
+ # remove directories
20
+ items = [item for item in items if not item.is_dir()]
21
+ if len(items) == 0:
22
+ raise Exception("No files found in directory")
23
+ return items
24
+
25
+
26
+ def prepare_item(item, folder):
27
+ return {
28
+ "filename": item.name,
29
+ "path": str(item.relative_to(folder)),
30
+ "absolute_path": item.absolute(),
31
+ "size": os.path.getsize(item.absolute()),
32
+ "checksum": calculate_checksum(item.absolute()),
33
+ }
34
+
35
+
36
+ def generate_batches(files, max_batch_size=1024 * 1024 * 10, max_batch_files=10):
37
+ batches = []
38
+ for item in tqdm(files):
39
+ if not batches:
40
+ batches.append([item])
41
+ continue
42
+ if max_batch_size:
43
+ size_check = sum([i["size"] for i in batches[-1]]) < max_batch_size
44
+ else:
45
+ size_check = True
46
+ if size_check and len(batches[-1]) < max_batch_files:
47
+ batches[-1].append(item)
48
+ else:
49
+ batches.append([item])
50
+ return batches
51
+
52
+
53
+ def compress_batch(batch):
54
+ memory_file = io.BytesIO()
55
+ with zipfile.ZipFile(memory_file, "w") as zf:
56
+ for f in batch:
57
+ zf.write(f["absolute_path"], arcname=f["path"])
58
+ memory_file.seek(0)
59
+ return memory_file
60
+
61
+
62
+ def generate_files_lists(
63
+ items, folder, dataset_or_model_id, endpoint, logger, max_size=1024 * 1024 * 16
64
+ ):
65
+ files_repo = FilesAPIRepo()
66
+ current_files, error = files_repo.retrieve_files(
67
+ dataset_or_model_id, "models", endpoint
68
+ )
69
+ # print(len(current_files), len(items) - len(current_files))
70
+ # print(current_files, error)
71
+ if error:
72
+ current_files = []
73
+ # generate list of files to upload
74
+ logger("generating list of files to upload...")
75
+ upload_files, existing_files, large_files = [], [], []
76
+ current_names = [f["filename"] for f in current_files]
77
+ current_checksums = [f["checksum"] for f in current_files]
78
+ for item in tqdm(items):
79
+ data = prepare_item(item, folder)
80
+ if data["path"] in current_names and data["checksum"] in current_checksums:
81
+ existing_files.append(data)
82
+ else:
83
+ if data["size"] > max_size:
84
+ large_files.append(data)
85
+ else:
86
+ upload_files.append(data)
87
+ if len(upload_files) == 0 and len(large_files) == 0:
88
+ raise Exception("No files to upload")
89
+ return upload_files, existing_files, large_files
90
+
91
+
92
+ def create_new_version(repo, dataset_or_model_id, user):
93
+ data, error = repo.create_version(dataset_or_model_id, user["id_token"])
94
+ if error:
95
+ raise Exception(error)
96
+ return data["version"]
97
+
98
+
99
+ def ingest_files(repo, dataset_or_model_id, folder, verbose, logger, user, endpoint):
100
+ files_repo = FilesAPIRepo()
101
+ logger(f"Uploading directory {folder}...")
102
+ items = retrieve_files(folder)
103
+ # retrieve files
104
+ upload_files, existing_files, large_files = generate_files_lists(
105
+ items, folder, dataset_or_model_id, endpoint, logger
106
+ )
107
+ logger(f"{len(upload_files) + len(large_files)} new files will be ingested")
108
+ logger(f"{len(existing_files)} files already exist in dataset")
109
+ logger(f"{len(large_files)} large files will be ingested separately")
110
+ # create new version
111
+ version = create_new_version(repo, dataset_or_model_id, user)
112
+ logger("New version created, version: " + str(version))
113
+ # ingest new large files
114
+ if len(large_files) > 0:
115
+ logger("ingesting large files...")
116
+ for file in large_files:
117
+ logger("ingesting file: " + file["path"])
118
+ upload_id, parts = files_repo.prepare_large_upload(
119
+ file["path"],
120
+ dataset_or_model_id,
121
+ file["checksum"],
122
+ user["id_token"],
123
+ endpoint,
124
+ )
125
+ # print(upload_id, parts)
126
+ files_repo.ingest_large_file(
127
+ file["absolute_path"],
128
+ file["size"],
129
+ upload_id,
130
+ user["id_token"],
131
+ parts,
132
+ endpoint,
133
+ )
134
+ files_repo.complete_upload(user["id_token"], upload_id, version, endpoint)
135
+ # ingest new small files in batches
136
+ if len(upload_files) > 0:
137
+ logger("generating batches...")
138
+ batches = generate_batches(upload_files)
139
+ logger(
140
+ f"Uploading {len(upload_files)} small files in {len(batches)} batches..."
141
+ )
142
+ repo = FilesAPIRepo()
143
+ for batch in tqdm(
144
+ batches, desc="Uploading batches", unit="batches", disable=verbose
145
+ ):
146
+ # compress batch
147
+ memory_file = compress_batch(batch)
148
+ # ingest batch
149
+ data, error = repo.ingest_files_batch(
150
+ memory_file,
151
+ [f["checksum"] for f in batch],
152
+ dataset_or_model_id,
153
+ user["id_token"],
154
+ endpoint,
155
+ version,
156
+ )
157
+ # ingest existing files
158
+ if len(existing_files) > 0:
159
+ batches = generate_batches(existing_files, max_batch_size=None)
160
+ for batch in tqdm(
161
+ batches,
162
+ desc="Ingesting existing files",
163
+ unit="batches",
164
+ disable=verbose,
165
+ ):
166
+ data, error = files_repo.add_files_batch_to_version(
167
+ batch,
168
+ dataset_or_model_id,
169
+ version,
170
+ user["id_token"],
171
+ endpoint,
172
+ )
173
+ if error:
174
+ raise Exception(error)
175
+ return data
@@ -0,0 +1,3 @@
1
+ from .retrieve import retrieve_models
2
+ from .ingest import ingest_model
3
+ from .download import download_model
@@ -0,0 +1,119 @@
1
+ import os
2
+ from pathlib import Path
3
+ from tqdm import tqdm
4
+
5
+ from ..auth import with_auth
6
+ from .retrieve import retrieve_model, retrieve_model_files
7
+ from ..shared import calculate_checksum
8
+ from ..repos import FilesAPIRepo
9
+
10
+
11
+ @with_auth
12
+ def download_model(
13
+ model_name,
14
+ version=None,
15
+ path=None,
16
+ logger=None,
17
+ assets=False,
18
+ force=False,
19
+ verbose=False,
20
+ user=None,
21
+ file=None,
22
+ ):
23
+ model = retrieve_model(model_name)
24
+ if version is None:
25
+ version = sorted(model["versions"], key=lambda v: v["version_id"])[-1][
26
+ "version_id"
27
+ ]
28
+ else:
29
+ assert version in [
30
+ v["version_id"] for v in model["versions"]
31
+ ], f"Version {version} not found"
32
+ download_base_path = os.getenv(
33
+ "EOTDL_DOWNLOAD_PATH", str(Path.home()) + "/.cache/eotdl/models"
34
+ )
35
+ if path is None:
36
+ download_path = download_base_path + "/" + model_name + "/v" + str(version)
37
+ else:
38
+ download_path = path + "/" + model_name + "/v" + str(version)
39
+ # check if model already exists
40
+ if os.path.exists(download_path) and not force:
41
+ os.makedirs(download_path, exist_ok=True)
42
+ raise Exception(
43
+ f"model `{model['name']} v{str(version)}` already exists at {download_path}. To force download, use force=True or -f in the CLI."
44
+ )
45
+ if model["quality"] == 0:
46
+ if file:
47
+ raise NotImplementedError("Downloading a specific file is not implemented")
48
+ # files = [f for f in model["files"] if f["name"] == file]
49
+ # if not files:
50
+ # raise Exception(f"File {file} not found")
51
+ # if len(files) > 1:
52
+ # raise Exception(f"Multiple files with name {file} found")
53
+ # dst_path = download(
54
+ # model,
55
+ # model["id"],
56
+ # file,
57
+ # files[0]["checksum"],
58
+ # download_path,
59
+ # user,
60
+ # )
61
+ # return Outputs(dst_path=dst_path)
62
+ model_files = retrieve_model_files(model["id"], version)
63
+ repo = FilesAPIRepo()
64
+ for file in tqdm(model_files, disable=verbose, unit="file"):
65
+ filename, file_version = file["filename"], file["version"]
66
+ if verbose:
67
+ logger(f"Downloading {file['filename']}...")
68
+ dst_path = repo.download_file(
69
+ model["id"],
70
+ filename,
71
+ user["id_token"],
72
+ download_path,
73
+ file_version,
74
+ endpoint="models",
75
+ )
76
+ # if calculate_checksum(dst_path) != checksum:
77
+ # logger(f"Checksum for {file} does not match")
78
+ if verbose:
79
+ logger(f"Done")
80
+ return "/".join(dst_path.split("/")[:-1])
81
+ else:
82
+ raise NotImplementedError("Downloading a STAC model is not implemented")
83
+ # logger("Downloading STAC metadata...")
84
+ # gdf, error = repo.download_stac(
85
+ # model["id"],
86
+ # user["id_token"],
87
+ # )
88
+ # if error:
89
+ # raise Exception(error)
90
+ # df = STACDataFrame(gdf)
91
+ # # df.geometry = df.geometry.apply(lambda x: Polygon() if x is None else x)
92
+ # path = path
93
+ # if path is None:
94
+ # path = download_base_path + "/" + model["name"]
95
+ # df.to_stac(path)
96
+ # # download assets
97
+ # if assets:
98
+ # logger("Downloading assets...")
99
+ # df = df.dropna(subset=["assets"])
100
+ # for row in tqdm(df.iterrows(), total=len(df)):
101
+ # id = row[1]["stac_id"]
102
+ # # print(row[1]["links"])
103
+ # for k, v in row[1]["assets"].items():
104
+ # href = v["href"]
105
+ # repo.download_file_url(
106
+ # href, f"{path}/assets/{id}", user["id_token"]
107
+ # )
108
+ # else:
109
+ # logger("To download assets, set assets=True or -a in the CLI.")
110
+ # return Outputs(dst_path=path)
111
+
112
+
113
+ # @with_auth
114
+ # def download_file_url(url, path, progress=True, logger=None, user=None):
115
+ # api_repo = APIRepo()
116
+ # download = DownloadFileURL(api_repo, logger, progress)
117
+ # inputs = DownloadFileURL.Inputs(url=url, path=path, user=user)
118
+ # outputs = download(inputs)
119
+ # return outputs.dst_path
eotdl/models/ingest.py ADDED
@@ -0,0 +1,47 @@
1
+ from pathlib import Path
2
+ import yaml
3
+
4
+ from ..auth import with_auth
5
+ from .metadata import Metadata
6
+ from ..repos import ModelsAPIRepo
7
+ from ..shared import calculate_checksum
8
+ from ..files import ingest_files
9
+
10
+
11
+ def ingest_model(path, verbose=False, logger=print):
12
+ path = Path(path)
13
+ if not path.is_dir():
14
+ raise Exception("Path must be a folder")
15
+ # if "catalog.json" in [f.name for f in path.iterdir()]:
16
+ # return ingest_stac(path / "catalog.json", logger)
17
+ return ingest_folder(path, verbose, logger)
18
+
19
+
20
+ def retrieve_model(metadata, user):
21
+ repo = ModelsAPIRepo()
22
+ data, error = repo.retrieve_model(metadata.name)
23
+ # print(data, error)
24
+ if data and data["uid"] != user["sub"]:
25
+ raise Exception("Model already exists.")
26
+ if error and error == "Model doesn't exist":
27
+ # create dataset
28
+ data, error = repo.create_model(metadata.dict(), user["id_token"])
29
+ # print(data, error)
30
+ if error:
31
+ raise Exception(error)
32
+ data["id"] = data["model_id"]
33
+ return data["id"]
34
+
35
+
36
+ @with_auth
37
+ def ingest_folder(folder, verbose=False, logger=print, user=None):
38
+ repo = ModelsAPIRepo()
39
+ # load metadata
40
+ metadata = yaml.safe_load(open(folder.joinpath("metadata.yml"), "r").read()) or {}
41
+ metadata = Metadata(**metadata)
42
+ # retrieve model (create if doesn't exist)
43
+ model_id = retrieve_model(metadata, user)
44
+ # ingest files
45
+ return ingest_files(
46
+ repo, model_id, folder, verbose, logger, user, endpoint="models"
47
+ )
@@ -0,0 +1,16 @@
1
+ from pydantic import BaseModel, validator
2
+ from typing import List
3
+
4
+
5
+ class Metadata(BaseModel):
6
+ authors: List[str]
7
+ license: str
8
+ source: str
9
+ name: str
10
+
11
+ # validate source is a URL
12
+ @validator("source")
13
+ def source_is_url(cls, v):
14
+ if not v.startswith("http") and not v.startswith("https"):
15
+ raise ValueError("source must be a URL")
16
+ return v
@@ -0,0 +1,26 @@
1
+ from ..repos import ModelsAPIRepo, FilesAPIRepo
2
+
3
+
4
+ def retrieve_models(name=None, limit=None):
5
+ api_repo = ModelsAPIRepo()
6
+ data, error = api_repo.retrieve_models(name, limit)
7
+ if data and not error:
8
+ models = [d["name"] for d in data] if data else []
9
+ return models
10
+ return []
11
+
12
+
13
+ def retrieve_model(name):
14
+ repo = ModelsAPIRepo()
15
+ data, error = repo.retrieve_model(name)
16
+ if error:
17
+ raise Exception(error)
18
+ return data
19
+
20
+
21
+ def retrieve_model_files(model_id, version):
22
+ repo = FilesAPIRepo()
23
+ data, error = repo.retrieve_files(model_id, "models", version)
24
+ if error:
25
+ raise Exception(error)
26
+ return data