digitalhub 0.8.1__py3-none-any.whl → 0.9.0b0__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.
Potentially problematic release.
This version of digitalhub might be problematic. Click here for more details.
- digitalhub/__init__.py +19 -2
- digitalhub/client/_base/api_builder.py +16 -0
- digitalhub/client/_base/client.py +31 -0
- digitalhub/client/api.py +2 -38
- digitalhub/client/dhcore/api_builder.py +100 -0
- digitalhub/client/dhcore/client.py +77 -24
- digitalhub/client/dhcore/enums.py +26 -0
- digitalhub/client/dhcore/env.py +2 -2
- digitalhub/client/dhcore/utils.py +17 -17
- digitalhub/client/local/api_builder.py +100 -0
- digitalhub/client/local/client.py +20 -0
- digitalhub/context/api.py +3 -38
- digitalhub/context/builder.py +10 -23
- digitalhub/context/context.py +20 -92
- digitalhub/entities/_base/context/entity.py +30 -22
- digitalhub/entities/_base/entity/_constructors/metadata.py +12 -1
- digitalhub/entities/_base/entity/_constructors/name.py +1 -1
- digitalhub/entities/_base/entity/_constructors/spec.py +1 -1
- digitalhub/entities/_base/entity/_constructors/status.py +3 -2
- digitalhub/entities/_base/entity/builder.py +6 -1
- digitalhub/entities/_base/entity/entity.py +30 -10
- digitalhub/entities/_base/entity/metadata.py +22 -0
- digitalhub/entities/_base/entity/spec.py +7 -2
- digitalhub/entities/_base/executable/entity.py +8 -8
- digitalhub/entities/_base/material/entity.py +48 -16
- digitalhub/entities/_base/material/status.py +0 -31
- digitalhub/entities/_base/material/utils.py +106 -0
- digitalhub/entities/_base/project/entity.py +341 -0
- digitalhub/entities/_base/unversioned/entity.py +1 -23
- digitalhub/entities/_base/versioned/entity.py +0 -25
- digitalhub/entities/_commons/enums.py +103 -0
- digitalhub/entities/_commons/utils.py +83 -0
- digitalhub/entities/_operations/processor.py +1747 -0
- digitalhub/entities/artifact/_base/builder.py +1 -1
- digitalhub/entities/artifact/_base/entity.py +1 -1
- digitalhub/entities/artifact/artifact/builder.py +2 -1
- digitalhub/entities/artifact/crud.py +46 -29
- digitalhub/entities/artifact/utils.py +62 -0
- digitalhub/entities/dataitem/_base/builder.py +1 -1
- digitalhub/entities/dataitem/_base/entity.py +6 -6
- digitalhub/entities/dataitem/crud.py +50 -66
- digitalhub/entities/dataitem/dataitem/builder.py +2 -1
- digitalhub/entities/dataitem/iceberg/builder.py +2 -1
- digitalhub/entities/dataitem/table/builder.py +2 -1
- digitalhub/entities/dataitem/table/entity.py +5 -10
- digitalhub/entities/dataitem/table/models.py +4 -5
- digitalhub/entities/dataitem/utils.py +137 -0
- digitalhub/entities/function/_base/builder.py +1 -1
- digitalhub/entities/function/_base/entity.py +5 -1
- digitalhub/entities/function/crud.py +36 -17
- digitalhub/entities/model/_base/builder.py +1 -1
- digitalhub/entities/model/_base/entity.py +1 -1
- digitalhub/entities/model/crud.py +46 -29
- digitalhub/entities/model/huggingface/builder.py +2 -1
- digitalhub/entities/model/huggingface/spec.py +4 -2
- digitalhub/entities/model/mlflow/builder.py +2 -1
- digitalhub/entities/model/mlflow/models.py +17 -9
- digitalhub/entities/model/mlflow/spec.py +6 -1
- digitalhub/entities/model/mlflow/utils.py +4 -2
- digitalhub/entities/model/model/builder.py +2 -1
- digitalhub/entities/model/sklearn/builder.py +2 -1
- digitalhub/entities/model/utils.py +62 -0
- digitalhub/entities/project/_base/builder.py +2 -2
- digitalhub/entities/project/_base/entity.py +82 -272
- digitalhub/entities/project/crud.py +110 -91
- digitalhub/entities/project/utils.py +35 -0
- digitalhub/entities/run/_base/builder.py +3 -1
- digitalhub/entities/run/_base/entity.py +52 -54
- digitalhub/entities/run/_base/spec.py +11 -7
- digitalhub/entities/run/crud.py +35 -17
- digitalhub/entities/secret/_base/builder.py +2 -2
- digitalhub/entities/secret/_base/entity.py +4 -10
- digitalhub/entities/secret/crud.py +36 -21
- digitalhub/entities/task/_base/builder.py +14 -14
- digitalhub/entities/task/_base/entity.py +6 -6
- digitalhub/entities/task/_base/models.py +29 -6
- digitalhub/entities/task/_base/spec.py +44 -13
- digitalhub/entities/task/_base/utils.py +18 -0
- digitalhub/entities/task/crud.py +35 -15
- digitalhub/entities/workflow/_base/builder.py +1 -1
- digitalhub/entities/workflow/_base/entity.py +14 -6
- digitalhub/entities/workflow/crud.py +36 -17
- digitalhub/factory/utils.py +1 -1
- digitalhub/readers/_base/reader.py +2 -2
- digitalhub/readers/_commons/enums.py +13 -0
- digitalhub/readers/api.py +3 -2
- digitalhub/readers/factory.py +12 -6
- digitalhub/readers/pandas/reader.py +20 -8
- digitalhub/runtimes/_base.py +0 -7
- digitalhub/stores/_base/store.py +53 -9
- digitalhub/stores/builder.py +5 -5
- digitalhub/stores/local/store.py +37 -2
- digitalhub/stores/remote/store.py +25 -3
- digitalhub/stores/s3/store.py +34 -7
- digitalhub/stores/sql/store.py +112 -45
- digitalhub/utils/exceptions.py +6 -0
- digitalhub/utils/file_utils.py +60 -2
- digitalhub/utils/generic_utils.py +45 -4
- digitalhub/utils/io_utils.py +18 -0
- digitalhub/utils/uri_utils.py +153 -15
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/METADATA +2 -2
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/RECORD +110 -113
- test/testkfp.py +4 -1
- digitalhub/datastores/_base/datastore.py +0 -85
- digitalhub/datastores/api.py +0 -37
- digitalhub/datastores/builder.py +0 -110
- digitalhub/datastores/local/datastore.py +0 -50
- digitalhub/datastores/remote/__init__.py +0 -0
- digitalhub/datastores/remote/datastore.py +0 -31
- digitalhub/datastores/s3/__init__.py +0 -0
- digitalhub/datastores/s3/datastore.py +0 -46
- digitalhub/datastores/sql/__init__.py +0 -0
- digitalhub/datastores/sql/datastore.py +0 -68
- digitalhub/entities/_base/api_utils.py +0 -620
- digitalhub/entities/_base/crud.py +0 -468
- digitalhub/entities/function/_base/models.py +0 -118
- digitalhub/entities/utils/__init__.py +0 -0
- digitalhub/entities/utils/api.py +0 -346
- digitalhub/entities/utils/entity_types.py +0 -19
- digitalhub/entities/utils/state.py +0 -31
- digitalhub/entities/utils/utils.py +0 -202
- /digitalhub/{context → entities/_base/project}/__init__.py +0 -0
- /digitalhub/{datastores → entities/_commons}/__init__.py +0 -0
- /digitalhub/{datastores/_base → entities/_operations}/__init__.py +0 -0
- /digitalhub/{datastores/local → readers/_commons}/__init__.py +0 -0
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/LICENSE.txt +0 -0
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/WHEEL +0 -0
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/top_level.txt +0 -0
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import importlib.util as imputil
|
|
4
3
|
import typing
|
|
5
|
-
from pathlib import Path
|
|
6
4
|
|
|
7
|
-
from digitalhub.
|
|
8
|
-
from digitalhub.
|
|
9
|
-
from digitalhub.entities.
|
|
10
|
-
from digitalhub.
|
|
11
|
-
from digitalhub.factory.api import build_entity_from_dict, build_entity_from_params
|
|
12
|
-
from digitalhub.utils.exceptions import BackendError, EntityAlreadyExistsError, EntityError
|
|
13
|
-
from digitalhub.utils.io_utils import read_yaml
|
|
5
|
+
from digitalhub.entities._commons.enums import EntityTypes
|
|
6
|
+
from digitalhub.entities._operations.processor import processor
|
|
7
|
+
from digitalhub.entities.project.utils import setup_project
|
|
8
|
+
from digitalhub.utils.exceptions import BackendError
|
|
14
9
|
|
|
15
10
|
if typing.TYPE_CHECKING:
|
|
11
|
+
from digitalhub.entities._base.context.entity import ContextEntity
|
|
16
12
|
from digitalhub.entities.project._base.entity import Project
|
|
17
13
|
|
|
18
14
|
|
|
@@ -60,20 +56,19 @@ def new_project(
|
|
|
60
56
|
--------
|
|
61
57
|
>>> obj = new_project("my-project")
|
|
62
58
|
"""
|
|
63
|
-
build_client(local, config)
|
|
64
59
|
if context is None:
|
|
65
|
-
context =
|
|
66
|
-
obj =
|
|
60
|
+
context = "./"
|
|
61
|
+
obj = processor.create_project_entity(
|
|
67
62
|
name=name,
|
|
68
63
|
kind="project",
|
|
69
64
|
description=description,
|
|
70
65
|
labels=labels,
|
|
71
66
|
local=local,
|
|
67
|
+
config=config,
|
|
72
68
|
context=context,
|
|
73
69
|
**kwargs,
|
|
74
70
|
)
|
|
75
|
-
obj
|
|
76
|
-
return _setup_project(obj, setup_kwargs)
|
|
71
|
+
return setup_project(obj, setup_kwargs)
|
|
77
72
|
|
|
78
73
|
|
|
79
74
|
def get_project(
|
|
@@ -108,12 +103,14 @@ def get_project(
|
|
|
108
103
|
--------
|
|
109
104
|
>>> obj = get_project("my-project")
|
|
110
105
|
"""
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
106
|
+
obj = processor.read_project_entity(
|
|
107
|
+
entity_type=ENTITY_TYPE,
|
|
108
|
+
entity_name=name,
|
|
109
|
+
local=local,
|
|
110
|
+
config=config,
|
|
111
|
+
**kwargs,
|
|
112
|
+
)
|
|
113
|
+
return setup_project(obj, setup_kwargs)
|
|
117
114
|
|
|
118
115
|
|
|
119
116
|
def import_project(
|
|
@@ -123,7 +120,7 @@ def import_project(
|
|
|
123
120
|
setup_kwargs: dict | None = None,
|
|
124
121
|
) -> Project:
|
|
125
122
|
"""
|
|
126
|
-
Import object from a YAML file.
|
|
123
|
+
Import object from a YAML file and create a new object into the backend.
|
|
127
124
|
|
|
128
125
|
Parameters
|
|
129
126
|
----------
|
|
@@ -145,42 +142,22 @@ def import_project(
|
|
|
145
142
|
--------
|
|
146
143
|
>>> obj = import_project("my-project.yaml")
|
|
147
144
|
"""
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
dict_obj["local"] = local
|
|
151
|
-
obj = build_entity_from_dict(dict_obj)
|
|
152
|
-
obj = _setup_project(obj, setup_kwargs)
|
|
153
|
-
|
|
154
|
-
try:
|
|
155
|
-
obj.save()
|
|
156
|
-
except EntityAlreadyExistsError:
|
|
157
|
-
pass
|
|
158
|
-
|
|
159
|
-
# Import related entities
|
|
160
|
-
obj._import_entities(dict_obj)
|
|
161
|
-
|
|
162
|
-
obj.refresh()
|
|
163
|
-
|
|
164
|
-
return obj
|
|
145
|
+
obj = processor.import_project_entity(file=file, local=local, config=config)
|
|
146
|
+
return setup_project(obj, setup_kwargs)
|
|
165
147
|
|
|
166
148
|
|
|
167
149
|
def load_project(
|
|
168
|
-
|
|
169
|
-
filename: str | None = None,
|
|
150
|
+
file: str,
|
|
170
151
|
local: bool = False,
|
|
171
152
|
config: dict | None = None,
|
|
172
153
|
setup_kwargs: dict | None = None,
|
|
173
|
-
**kwargs,
|
|
174
154
|
) -> Project:
|
|
175
155
|
"""
|
|
176
|
-
Load
|
|
177
|
-
filename must be provided. Name takes precedence over filename.
|
|
156
|
+
Load object from a YAML file and update an existing object into the backend.
|
|
178
157
|
|
|
179
158
|
Parameters
|
|
180
159
|
----------
|
|
181
|
-
|
|
182
|
-
Project name.
|
|
183
|
-
filename : str
|
|
160
|
+
file : str
|
|
184
161
|
Path to YAML file.
|
|
185
162
|
local : bool
|
|
186
163
|
Flag to determine if backend is local.
|
|
@@ -188,8 +165,6 @@ def load_project(
|
|
|
188
165
|
DHCore environment configuration.
|
|
189
166
|
setup_kwargs : dict
|
|
190
167
|
Setup keyword arguments passed to setup_project() function.
|
|
191
|
-
**kwargs : dict
|
|
192
|
-
Keyword arguments.
|
|
193
168
|
|
|
194
169
|
Returns
|
|
195
170
|
-------
|
|
@@ -198,17 +173,29 @@ def load_project(
|
|
|
198
173
|
|
|
199
174
|
Examples
|
|
200
175
|
--------
|
|
201
|
-
|
|
202
|
-
|
|
176
|
+
>>> obj = load_project("my-project.yaml")
|
|
177
|
+
"""
|
|
178
|
+
obj = processor.load_project_entity(file=file, local=local, config=config)
|
|
179
|
+
return setup_project(obj, setup_kwargs)
|
|
180
|
+
|
|
203
181
|
|
|
204
|
-
|
|
205
|
-
>>> obj = load_project(filename="my-project.yaml")
|
|
182
|
+
def list_projects(local: bool = False, **kwargs) -> list[Project]:
|
|
206
183
|
"""
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
184
|
+
List projects in backend.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
local : bool
|
|
189
|
+
Flag to determine if backend is local.
|
|
190
|
+
**kwargs : dict
|
|
191
|
+
Parameters to pass to the API call.
|
|
192
|
+
|
|
193
|
+
Returns
|
|
194
|
+
-------
|
|
195
|
+
list
|
|
196
|
+
List of objects.
|
|
197
|
+
"""
|
|
198
|
+
return processor.list_project_entities(local=local, **kwargs)
|
|
212
199
|
|
|
213
200
|
|
|
214
201
|
def get_or_create_project(
|
|
@@ -261,7 +248,7 @@ def get_or_create_project(
|
|
|
261
248
|
)
|
|
262
249
|
|
|
263
250
|
|
|
264
|
-
def update_project(entity: Project,
|
|
251
|
+
def update_project(entity: Project, **kwargs) -> Project:
|
|
265
252
|
"""
|
|
266
253
|
Update object. Note that object spec are immutable.
|
|
267
254
|
|
|
@@ -269,8 +256,6 @@ def update_project(entity: Project, local: bool = False, **kwargs) -> Project:
|
|
|
269
256
|
----------
|
|
270
257
|
entity : Project
|
|
271
258
|
Object to update.
|
|
272
|
-
local : bool
|
|
273
|
-
Flag to determine if backend is local.
|
|
274
259
|
**kwargs : dict
|
|
275
260
|
Parameters to pass to the API call.
|
|
276
261
|
|
|
@@ -283,9 +268,13 @@ def update_project(entity: Project, local: bool = False, **kwargs) -> Project:
|
|
|
283
268
|
--------
|
|
284
269
|
>>> obj = update_project(obj)
|
|
285
270
|
"""
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
271
|
+
return processor.update_project_entity(
|
|
272
|
+
entity_type=entity.ENTITY_TYPE,
|
|
273
|
+
entity_name=entity.name,
|
|
274
|
+
entity_dict=entity.to_dict(),
|
|
275
|
+
local=entity.local,
|
|
276
|
+
**kwargs,
|
|
277
|
+
)
|
|
289
278
|
|
|
290
279
|
|
|
291
280
|
def delete_project(
|
|
@@ -305,8 +294,7 @@ def delete_project(
|
|
|
305
294
|
cascade : bool
|
|
306
295
|
Flag to determine if delete is cascading.
|
|
307
296
|
clean_context : bool
|
|
308
|
-
Flag to determine if context will be deleted.
|
|
309
|
-
all its objects are unreacheable.
|
|
297
|
+
Flag to determine if context will be deleted.
|
|
310
298
|
local : bool
|
|
311
299
|
Flag to determine if backend is local.
|
|
312
300
|
**kwargs : dict
|
|
@@ -321,37 +309,68 @@ def delete_project(
|
|
|
321
309
|
--------
|
|
322
310
|
>>> delete_project("my-project")
|
|
323
311
|
"""
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
312
|
+
return processor.delete_project_entity(
|
|
313
|
+
entity_type=ENTITY_TYPE,
|
|
314
|
+
entity_name=name,
|
|
315
|
+
local=local,
|
|
316
|
+
cascade=cascade,
|
|
317
|
+
clean_context=clean_context,
|
|
318
|
+
**kwargs,
|
|
319
|
+
)
|
|
329
320
|
|
|
330
321
|
|
|
331
|
-
def
|
|
322
|
+
def search_entity(
|
|
323
|
+
project_name: str,
|
|
324
|
+
query: str | None = None,
|
|
325
|
+
entity_types: list[str] | None = None,
|
|
326
|
+
name: str | None = None,
|
|
327
|
+
kind: str | None = None,
|
|
328
|
+
created: str | None = None,
|
|
329
|
+
updated: str | None = None,
|
|
330
|
+
description: str | None = None,
|
|
331
|
+
labels: list[str] | None = None,
|
|
332
|
+
**kwargs,
|
|
333
|
+
) -> list[ContextEntity]:
|
|
332
334
|
"""
|
|
333
|
-
Search
|
|
335
|
+
Search objects from backend.
|
|
334
336
|
|
|
335
337
|
Parameters
|
|
336
338
|
----------
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
339
|
+
project_name : str
|
|
340
|
+
Project name.
|
|
341
|
+
query : str
|
|
342
|
+
Search query.
|
|
343
|
+
entity_types : list[str]
|
|
344
|
+
Entity types.
|
|
345
|
+
name : str
|
|
346
|
+
Entity name.
|
|
347
|
+
kind : str
|
|
348
|
+
Entity kind.
|
|
349
|
+
created : str
|
|
350
|
+
Entity creation date.
|
|
351
|
+
updated : str
|
|
352
|
+
Entity update date.
|
|
353
|
+
description : str
|
|
354
|
+
Entity description.
|
|
355
|
+
labels : list[str]
|
|
356
|
+
Entity labels.
|
|
357
|
+
**kwargs : dict
|
|
358
|
+
Parameters to pass to the API call.
|
|
341
359
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
360
|
+
Returns
|
|
361
|
+
-------
|
|
362
|
+
list[ContextEntity]
|
|
363
|
+
List of object instances.
|
|
346
364
|
"""
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
365
|
+
return processor.search_entity(
|
|
366
|
+
project_name,
|
|
367
|
+
query=query,
|
|
368
|
+
entity_types=entity_types,
|
|
369
|
+
name=name,
|
|
370
|
+
kind=kind,
|
|
371
|
+
created=created,
|
|
372
|
+
updated=updated,
|
|
373
|
+
description=description,
|
|
374
|
+
labels=labels,
|
|
375
|
+
**kwargs,
|
|
376
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from digitalhub.utils.generic_utils import import_function
|
|
7
|
+
|
|
8
|
+
if typing.TYPE_CHECKING:
|
|
9
|
+
from digitalhub.entities.project._base.entity import Project
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def setup_project(project: Project, setup_kwargs: dict | None = None) -> Project:
|
|
13
|
+
"""
|
|
14
|
+
Search for setup_project.py file and launch setup hanlder as project hook.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
project : Project
|
|
19
|
+
The project to scafold.
|
|
20
|
+
setup_kwargs : dict
|
|
21
|
+
Arguments to pass to setup handler.
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
Project
|
|
26
|
+
Set up project.
|
|
27
|
+
"""
|
|
28
|
+
setup_kwargs = setup_kwargs if setup_kwargs is not None else {}
|
|
29
|
+
check_pth = Path(project.spec.context, ".CHECK")
|
|
30
|
+
setup_pth = Path(project.spec.context, "setup_project.py")
|
|
31
|
+
if setup_pth.exists() and not check_pth.exists():
|
|
32
|
+
setup_fnc = import_function(setup_pth, "setup")
|
|
33
|
+
project = setup_fnc(project, **setup_kwargs)
|
|
34
|
+
check_pth.touch()
|
|
35
|
+
return project
|
|
@@ -4,7 +4,7 @@ import typing
|
|
|
4
4
|
|
|
5
5
|
from digitalhub.entities._base.runtime_entity.builder import EntityError, RuntimeEntityBuilder
|
|
6
6
|
from digitalhub.entities._base.unversioned.builder import UnversionedBuilder
|
|
7
|
-
from digitalhub.entities.
|
|
7
|
+
from digitalhub.entities._commons.enums import EntityTypes
|
|
8
8
|
|
|
9
9
|
if typing.TYPE_CHECKING:
|
|
10
10
|
from digitalhub.entities.run._base.entity import Run
|
|
@@ -52,9 +52,11 @@ class RunBuilder(UnversionedBuilder, RuntimeEntityBuilder):
|
|
|
52
52
|
Run
|
|
53
53
|
Object instance.
|
|
54
54
|
"""
|
|
55
|
+
# Check task validity
|
|
55
56
|
if task is None:
|
|
56
57
|
raise EntityError("Missing task in run spec")
|
|
57
58
|
self._check_kind_validity(task)
|
|
59
|
+
|
|
58
60
|
uuid = self.build_uuid(uuid)
|
|
59
61
|
metadata = self.build_metadata(
|
|
60
62
|
project=project,
|
|
@@ -3,17 +3,9 @@ from __future__ import annotations
|
|
|
3
3
|
import time
|
|
4
4
|
import typing
|
|
5
5
|
|
|
6
|
-
from digitalhub.entities._base.api_utils import (
|
|
7
|
-
list_entity_api_base,
|
|
8
|
-
list_entity_api_ctx,
|
|
9
|
-
logs_api,
|
|
10
|
-
read_entity_api_ctx,
|
|
11
|
-
resume_api,
|
|
12
|
-
stop_api,
|
|
13
|
-
)
|
|
14
6
|
from digitalhub.entities._base.unversioned.entity import UnversionedEntity
|
|
15
|
-
from digitalhub.entities.
|
|
16
|
-
from digitalhub.entities.
|
|
7
|
+
from digitalhub.entities._commons.enums import EntityTypes, State
|
|
8
|
+
from digitalhub.entities._operations.processor import processor
|
|
17
9
|
from digitalhub.factory.api import (
|
|
18
10
|
build_runtime,
|
|
19
11
|
build_spec,
|
|
@@ -68,12 +60,9 @@ class Run(UnversionedEntity):
|
|
|
68
60
|
executable = self._get_executable()
|
|
69
61
|
task = self._get_task()
|
|
70
62
|
new_spec = self._get_runtime().build(executable, task, self.to_dict())
|
|
71
|
-
self.spec = build_spec(
|
|
72
|
-
self.kind,
|
|
73
|
-
**new_spec,
|
|
74
|
-
)
|
|
63
|
+
self.spec = build_spec(self.kind, **new_spec)
|
|
75
64
|
self._set_state(State.BUILT.value)
|
|
76
|
-
self.save()
|
|
65
|
+
self.save(update=True)
|
|
77
66
|
|
|
78
67
|
def run(self) -> Run:
|
|
79
68
|
"""
|
|
@@ -85,12 +74,8 @@ class Run(UnversionedEntity):
|
|
|
85
74
|
Run object.
|
|
86
75
|
"""
|
|
87
76
|
self.refresh()
|
|
88
|
-
if self.spec.local_execution:
|
|
89
|
-
if not self._is_ready_to_run():
|
|
90
|
-
raise EntityError("Run is not in a state to run.")
|
|
91
|
-
self._set_state(State.RUNNING.value)
|
|
92
|
-
self.save(update=True)
|
|
93
77
|
|
|
78
|
+
self._start_execution()
|
|
94
79
|
self._setup_execution()
|
|
95
80
|
|
|
96
81
|
try:
|
|
@@ -102,6 +87,8 @@ class Run(UnversionedEntity):
|
|
|
102
87
|
self._set_message(str(e))
|
|
103
88
|
self.save(update=True)
|
|
104
89
|
raise e
|
|
90
|
+
finally:
|
|
91
|
+
self._finish_execution()
|
|
105
92
|
|
|
106
93
|
self.refresh()
|
|
107
94
|
if not self.spec.local_execution:
|
|
@@ -143,17 +130,14 @@ class Run(UnversionedEntity):
|
|
|
143
130
|
|
|
144
131
|
def logs(self) -> dict:
|
|
145
132
|
"""
|
|
146
|
-
Get
|
|
147
|
-
Returns empty dictionary if context is local.
|
|
133
|
+
Get run logs.
|
|
148
134
|
|
|
149
135
|
Returns
|
|
150
136
|
-------
|
|
151
137
|
dict
|
|
152
|
-
|
|
138
|
+
Run logs.
|
|
153
139
|
"""
|
|
154
|
-
|
|
155
|
-
return {}
|
|
156
|
-
return logs_api(self.project, self.ENTITY_TYPE, self.id)
|
|
140
|
+
return processor.read_run_logs(self.project, self.ENTITY_TYPE, self.id)
|
|
157
141
|
|
|
158
142
|
def stop(self) -> None:
|
|
159
143
|
"""
|
|
@@ -163,8 +147,8 @@ class Run(UnversionedEntity):
|
|
|
163
147
|
-------
|
|
164
148
|
None
|
|
165
149
|
"""
|
|
166
|
-
if not self.
|
|
167
|
-
return
|
|
150
|
+
if not self.spec.local_execution:
|
|
151
|
+
return processor.stop_run(self.project, self.ENTITY_TYPE, self.id)
|
|
168
152
|
|
|
169
153
|
def resume(self) -> None:
|
|
170
154
|
"""
|
|
@@ -174,9 +158,8 @@ class Run(UnversionedEntity):
|
|
|
174
158
|
-------
|
|
175
159
|
None
|
|
176
160
|
"""
|
|
177
|
-
if not self.
|
|
178
|
-
return
|
|
179
|
-
self.run()
|
|
161
|
+
if not self.spec.local_execution:
|
|
162
|
+
return processor.resume_run(self.project, self.ENTITY_TYPE, self.id)
|
|
180
163
|
|
|
181
164
|
##############################
|
|
182
165
|
# Helpers
|
|
@@ -184,13 +167,38 @@ class Run(UnversionedEntity):
|
|
|
184
167
|
|
|
185
168
|
def _setup_execution(self) -> None:
|
|
186
169
|
"""
|
|
187
|
-
Setup run execution.
|
|
170
|
+
Setup run execution.
|
|
188
171
|
|
|
189
172
|
Returns
|
|
190
173
|
-------
|
|
191
174
|
None
|
|
192
175
|
"""
|
|
193
176
|
|
|
177
|
+
def _start_execution(self) -> None:
|
|
178
|
+
"""
|
|
179
|
+
Start run execution.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
None
|
|
184
|
+
"""
|
|
185
|
+
self._context().set_run(f"{self.key}:{self.id}")
|
|
186
|
+
if self.spec.local_execution:
|
|
187
|
+
if not self._is_ready_to_run():
|
|
188
|
+
raise EntityError("Run is not in a state to run.")
|
|
189
|
+
self._set_state(State.RUNNING.value)
|
|
190
|
+
self.save(update=True)
|
|
191
|
+
|
|
192
|
+
def _finish_execution(self) -> None:
|
|
193
|
+
"""
|
|
194
|
+
Finish run execution.
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
None
|
|
199
|
+
"""
|
|
200
|
+
self._context().unset_run()
|
|
201
|
+
|
|
194
202
|
def _is_ready_to_run(self) -> bool:
|
|
195
203
|
"""
|
|
196
204
|
Check if run is in a state ready for running (BUILT or STOPPED).
|
|
@@ -269,16 +277,15 @@ class Run(UnversionedEntity):
|
|
|
269
277
|
Executable (function or workflow) from backend.
|
|
270
278
|
"""
|
|
271
279
|
exec_kind = get_executable_kind(self.kind)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
exec_name =
|
|
275
|
-
|
|
276
|
-
return read_entity_api_ctx(
|
|
280
|
+
exec_type = get_entity_type_from_kind(exec_kind)
|
|
281
|
+
string_to_split = getattr(self.spec, exec_type)
|
|
282
|
+
exec_name, exec_id = string_to_split.split("://")[-1].split("/")[-1].split(":")
|
|
283
|
+
return processor.read_context_entity(
|
|
277
284
|
exec_name,
|
|
278
|
-
entity_type=
|
|
285
|
+
entity_type=exec_type,
|
|
279
286
|
project=self.project,
|
|
280
287
|
entity_id=exec_id,
|
|
281
|
-
)
|
|
288
|
+
).to_dict()
|
|
282
289
|
|
|
283
290
|
def _get_task(self) -> dict:
|
|
284
291
|
"""
|
|
@@ -290,18 +297,9 @@ class Run(UnversionedEntity):
|
|
|
290
297
|
dict
|
|
291
298
|
Task from backend.
|
|
292
299
|
"""
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
for i in tasks:
|
|
300
|
-
if i.get("spec").get("function") == exec_string:
|
|
301
|
-
return i
|
|
302
|
-
raise EntityError("Task not found.")
|
|
303
|
-
|
|
304
|
-
# Remote backend
|
|
305
|
-
task_kind = self.spec.task.split("://")[0]
|
|
306
|
-
params = {"function": exec_string, "kind": task_kind}
|
|
307
|
-
return list_entity_api_ctx(self.project, EntityTypes.TASK.value, params=params)[0]
|
|
300
|
+
task_id = self.spec.task.split("://")[-1].split("/")[-1]
|
|
301
|
+
return processor.read_unversioned_entity(
|
|
302
|
+
task_id,
|
|
303
|
+
entity_type=EntityTypes.TASK.value,
|
|
304
|
+
project=self.project,
|
|
305
|
+
).to_dict()
|
|
@@ -12,19 +12,21 @@ class RunSpec(Spec):
|
|
|
12
12
|
task: str,
|
|
13
13
|
local_execution: bool = False,
|
|
14
14
|
function: str | None = None,
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
workflow: str | None = None,
|
|
16
|
+
node_selector: list[dict] | None = None,
|
|
17
|
+
volumes: list[dict] | None = None,
|
|
17
18
|
resources: dict | None = None,
|
|
18
19
|
affinity: dict | None = None,
|
|
19
|
-
tolerations: list | None = None,
|
|
20
|
-
envs: list | None = None,
|
|
21
|
-
secrets: list | None = None,
|
|
20
|
+
tolerations: list[dict] | None = None,
|
|
21
|
+
envs: list[dict] | None = None,
|
|
22
|
+
secrets: list[str] | None = None,
|
|
22
23
|
profile: str | None = None,
|
|
23
24
|
**kwargs,
|
|
24
25
|
) -> None:
|
|
25
26
|
self.task = task
|
|
26
27
|
self.local_execution = local_execution
|
|
27
28
|
self.function = function
|
|
29
|
+
self.workflow = workflow
|
|
28
30
|
self.node_selector = node_selector
|
|
29
31
|
self.volumes = volumes
|
|
30
32
|
self.resources = resources
|
|
@@ -40,10 +42,12 @@ class RunValidator(SpecValidator, K8s):
|
|
|
40
42
|
RunValidator validator.
|
|
41
43
|
"""
|
|
42
44
|
|
|
45
|
+
# Task parameters
|
|
43
46
|
function: str = None
|
|
44
|
-
|
|
47
|
+
workflow: str = None
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
# Run parameters
|
|
50
|
+
task: str
|
|
47
51
|
"""The task string associated with the run."""
|
|
48
52
|
|
|
49
53
|
local_execution: bool = False
|