digitalhub 0.8.0b0__py3-none-any.whl → 0.8.0b1__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 +62 -94
- digitalhub/client/__init__.py +0 -0
- digitalhub/client/builder.py +105 -0
- digitalhub/client/objects/__init__.py +0 -0
- digitalhub/client/objects/base.py +56 -0
- digitalhub/client/objects/dhcore.py +681 -0
- digitalhub/client/objects/local.py +533 -0
- digitalhub/context/__init__.py +0 -0
- digitalhub/context/builder.py +178 -0
- digitalhub/context/context.py +136 -0
- digitalhub/datastores/__init__.py +0 -0
- digitalhub/datastores/builder.py +134 -0
- digitalhub/datastores/objects/__init__.py +0 -0
- digitalhub/datastores/objects/base.py +85 -0
- digitalhub/datastores/objects/local.py +42 -0
- digitalhub/datastores/objects/remote.py +23 -0
- digitalhub/datastores/objects/s3.py +38 -0
- digitalhub/datastores/objects/sql.py +60 -0
- digitalhub/entities/__init__.py +0 -0
- digitalhub/entities/_base/__init__.py +0 -0
- digitalhub/entities/_base/api.py +346 -0
- digitalhub/entities/_base/base.py +82 -0
- digitalhub/entities/_base/crud.py +610 -0
- digitalhub/entities/_base/entity/__init__.py +0 -0
- digitalhub/entities/_base/entity/base.py +132 -0
- digitalhub/entities/_base/entity/context.py +118 -0
- digitalhub/entities/_base/entity/executable.py +380 -0
- digitalhub/entities/_base/entity/material.py +214 -0
- digitalhub/entities/_base/entity/unversioned.py +87 -0
- digitalhub/entities/_base/entity/versioned.py +94 -0
- digitalhub/entities/_base/metadata.py +59 -0
- digitalhub/entities/_base/spec/__init__.py +0 -0
- digitalhub/entities/_base/spec/base.py +58 -0
- digitalhub/entities/_base/spec/material.py +22 -0
- digitalhub/entities/_base/state.py +31 -0
- digitalhub/entities/_base/status/__init__.py +0 -0
- digitalhub/entities/_base/status/base.py +32 -0
- digitalhub/entities/_base/status/material.py +49 -0
- digitalhub/entities/_builders/__init__.py +0 -0
- digitalhub/entities/_builders/metadata.py +60 -0
- digitalhub/entities/_builders/name.py +31 -0
- digitalhub/entities/_builders/spec.py +43 -0
- digitalhub/entities/_builders/status.py +62 -0
- digitalhub/entities/_builders/uuid.py +33 -0
- digitalhub/entities/artifact/__init__.py +0 -0
- digitalhub/entities/artifact/builder.py +133 -0
- digitalhub/entities/artifact/crud.py +358 -0
- digitalhub/entities/artifact/entity/__init__.py +0 -0
- digitalhub/entities/artifact/entity/_base.py +39 -0
- digitalhub/entities/artifact/entity/artifact.py +9 -0
- digitalhub/entities/artifact/spec.py +39 -0
- digitalhub/entities/artifact/status.py +15 -0
- digitalhub/entities/dataitem/__init__.py +0 -0
- digitalhub/entities/dataitem/builder.py +144 -0
- digitalhub/entities/dataitem/crud.py +395 -0
- digitalhub/entities/dataitem/entity/__init__.py +0 -0
- digitalhub/entities/dataitem/entity/_base.py +75 -0
- digitalhub/entities/dataitem/entity/dataitem.py +9 -0
- digitalhub/entities/dataitem/entity/iceberg.py +7 -0
- digitalhub/entities/dataitem/entity/table.py +125 -0
- digitalhub/entities/dataitem/models.py +62 -0
- digitalhub/entities/dataitem/spec.py +61 -0
- digitalhub/entities/dataitem/status.py +38 -0
- digitalhub/entities/entity_types.py +19 -0
- digitalhub/entities/function/__init__.py +0 -0
- digitalhub/entities/function/builder.py +86 -0
- digitalhub/entities/function/crud.py +305 -0
- digitalhub/entities/function/entity.py +101 -0
- digitalhub/entities/function/models.py +118 -0
- digitalhub/entities/function/spec.py +81 -0
- digitalhub/entities/function/status.py +9 -0
- digitalhub/entities/model/__init__.py +0 -0
- digitalhub/entities/model/builder.py +152 -0
- digitalhub/entities/model/crud.py +358 -0
- digitalhub/entities/model/entity/__init__.py +0 -0
- digitalhub/entities/model/entity/_base.py +34 -0
- digitalhub/entities/model/entity/huggingface.py +9 -0
- digitalhub/entities/model/entity/mlflow.py +90 -0
- digitalhub/entities/model/entity/model.py +9 -0
- digitalhub/entities/model/entity/sklearn.py +9 -0
- digitalhub/entities/model/models.py +26 -0
- digitalhub/entities/model/spec.py +146 -0
- digitalhub/entities/model/status.py +33 -0
- digitalhub/entities/project/__init__.py +0 -0
- digitalhub/entities/project/builder.py +82 -0
- digitalhub/entities/project/crud.py +350 -0
- digitalhub/entities/project/entity.py +2060 -0
- digitalhub/entities/project/spec.py +50 -0
- digitalhub/entities/project/status.py +9 -0
- digitalhub/entities/registries.py +48 -0
- digitalhub/entities/run/__init__.py +0 -0
- digitalhub/entities/run/builder.py +77 -0
- digitalhub/entities/run/crud.py +232 -0
- digitalhub/entities/run/entity.py +461 -0
- digitalhub/entities/run/spec.py +153 -0
- digitalhub/entities/run/status.py +114 -0
- digitalhub/entities/secret/__init__.py +0 -0
- digitalhub/entities/secret/builder.py +93 -0
- digitalhub/entities/secret/crud.py +294 -0
- digitalhub/entities/secret/entity.py +73 -0
- digitalhub/entities/secret/spec.py +35 -0
- digitalhub/entities/secret/status.py +9 -0
- digitalhub/entities/task/__init__.py +0 -0
- digitalhub/entities/task/builder.py +74 -0
- digitalhub/entities/task/crud.py +241 -0
- digitalhub/entities/task/entity.py +135 -0
- digitalhub/entities/task/models.py +199 -0
- digitalhub/entities/task/spec.py +51 -0
- digitalhub/entities/task/status.py +9 -0
- digitalhub/entities/utils.py +184 -0
- digitalhub/entities/workflow/__init__.py +0 -0
- digitalhub/entities/workflow/builder.py +91 -0
- digitalhub/entities/workflow/crud.py +304 -0
- digitalhub/entities/workflow/entity.py +77 -0
- digitalhub/entities/workflow/spec.py +15 -0
- digitalhub/entities/workflow/status.py +9 -0
- digitalhub/readers/__init__.py +0 -0
- digitalhub/readers/builder.py +54 -0
- digitalhub/readers/objects/__init__.py +0 -0
- digitalhub/readers/objects/base.py +70 -0
- digitalhub/readers/objects/pandas.py +207 -0
- digitalhub/readers/registry.py +15 -0
- digitalhub/registry/__init__.py +0 -0
- digitalhub/registry/models.py +87 -0
- digitalhub/registry/registry.py +74 -0
- digitalhub/registry/utils.py +150 -0
- digitalhub/runtimes/__init__.py +0 -0
- digitalhub/runtimes/base.py +164 -0
- digitalhub/runtimes/builder.py +53 -0
- digitalhub/runtimes/kind_registry.py +170 -0
- digitalhub/stores/__init__.py +0 -0
- digitalhub/stores/builder.py +257 -0
- digitalhub/stores/objects/__init__.py +0 -0
- digitalhub/stores/objects/base.py +189 -0
- digitalhub/stores/objects/local.py +230 -0
- digitalhub/stores/objects/remote.py +143 -0
- digitalhub/stores/objects/s3.py +563 -0
- digitalhub/stores/objects/sql.py +328 -0
- digitalhub/utils/__init__.py +0 -0
- digitalhub/utils/data_utils.py +127 -0
- digitalhub/utils/env_utils.py +123 -0
- digitalhub/utils/exceptions.py +55 -0
- digitalhub/utils/file_utils.py +204 -0
- digitalhub/utils/generic_utils.py +207 -0
- digitalhub/utils/git_utils.py +148 -0
- digitalhub/utils/io_utils.py +79 -0
- digitalhub/utils/logger.py +17 -0
- digitalhub/utils/uri_utils.py +56 -0
- {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b1.dist-info}/METADATA +27 -12
- digitalhub-0.8.0b1.dist-info/RECORD +161 -0
- test/test_crud_artifacts.py +1 -1
- test/test_crud_dataitems.py +1 -1
- test/test_crud_functions.py +1 -1
- test/test_crud_runs.py +1 -1
- test/test_crud_tasks.py +1 -1
- digitalhub-0.8.0b0.dist-info/RECORD +0 -14
- {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b1.dist-info}/LICENSE.txt +0 -0
- {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b1.dist-info}/WHEEL +0 -0
- {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from digitalhub.entities.entity_types import EntityTypes
|
|
6
|
+
from digitalhub.utils.env_utils import get_s3_bucket
|
|
7
|
+
from digitalhub.utils.file_utils import get_file_mime_type
|
|
8
|
+
from digitalhub.utils.uri_utils import check_local_path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def parse_entity_key(key: str) -> tuple[str]:
|
|
12
|
+
"""
|
|
13
|
+
Parse the entity key. Returns project, entity type, kind, name and uuid.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
key : str
|
|
18
|
+
The entity key.
|
|
19
|
+
|
|
20
|
+
Returns
|
|
21
|
+
-------
|
|
22
|
+
tuple[str]
|
|
23
|
+
Project, entity type, kind, name and uuid.
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
# Remove "store://" from the key
|
|
27
|
+
key = key.replace("store://", "")
|
|
28
|
+
|
|
29
|
+
# Split the key into parts
|
|
30
|
+
parts = key.split("/")
|
|
31
|
+
|
|
32
|
+
# The project is the first part
|
|
33
|
+
project = parts[0]
|
|
34
|
+
|
|
35
|
+
# The entity type is the second part
|
|
36
|
+
entity_type = parts[1]
|
|
37
|
+
|
|
38
|
+
# The kind is the third part
|
|
39
|
+
kind = parts[2]
|
|
40
|
+
|
|
41
|
+
# Tasks and runs have no name and uuid
|
|
42
|
+
if entity_type in (EntityTypes.TASK.value, EntityTypes.RUN.value):
|
|
43
|
+
name = None
|
|
44
|
+
uuid = parts[3]
|
|
45
|
+
|
|
46
|
+
# The name and uuid are separated by a colon in the last part
|
|
47
|
+
else:
|
|
48
|
+
name, uuid = parts[3].split(":")
|
|
49
|
+
|
|
50
|
+
return project, entity_type, kind, name, uuid
|
|
51
|
+
except Exception as e:
|
|
52
|
+
raise ValueError("Invalid key format.") from e
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def eval_local_source(source: str | list[str]) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Evaluate if source is local.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
source : str | list[str]
|
|
62
|
+
Source(s).
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
None
|
|
67
|
+
"""
|
|
68
|
+
if isinstance(source, list):
|
|
69
|
+
if not source:
|
|
70
|
+
raise ValueError("Empty list of sources.")
|
|
71
|
+
source_is_local = all(check_local_path(s) for s in source)
|
|
72
|
+
for s in source:
|
|
73
|
+
if Path(s).is_dir():
|
|
74
|
+
raise ValueError(f"Invalid source path: {s}. List of paths must be list of files, not directories.")
|
|
75
|
+
else:
|
|
76
|
+
source_is_local = check_local_path(source)
|
|
77
|
+
|
|
78
|
+
if not source_is_local:
|
|
79
|
+
raise ValueError("Invalid source path. Source must be a local path.")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def eval_zip_type(source: str | list[str]) -> bool:
|
|
83
|
+
"""
|
|
84
|
+
Evaluate zip type.
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
source : str | list[str]
|
|
89
|
+
Source(s).
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
bool
|
|
94
|
+
True if path is zip.
|
|
95
|
+
"""
|
|
96
|
+
if isinstance(source, list):
|
|
97
|
+
if len(source) > 1:
|
|
98
|
+
return False
|
|
99
|
+
else:
|
|
100
|
+
path = source[0]
|
|
101
|
+
else:
|
|
102
|
+
if Path(source).is_dir():
|
|
103
|
+
return False
|
|
104
|
+
path = source
|
|
105
|
+
|
|
106
|
+
extension = path.endswith(".zip")
|
|
107
|
+
mime_zip = get_file_mime_type(path) == "application/zip"
|
|
108
|
+
return extension or mime_zip
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def build_log_path_from_filename(
|
|
112
|
+
project: str,
|
|
113
|
+
entity_type: str,
|
|
114
|
+
name: str,
|
|
115
|
+
uuid: str,
|
|
116
|
+
filename: str,
|
|
117
|
+
) -> str:
|
|
118
|
+
"""
|
|
119
|
+
Build log path.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
project : str
|
|
124
|
+
Project name.
|
|
125
|
+
entity_type : str
|
|
126
|
+
Entity type.
|
|
127
|
+
name : str
|
|
128
|
+
Object name.
|
|
129
|
+
uuid : str
|
|
130
|
+
Object UUID.
|
|
131
|
+
filename : str
|
|
132
|
+
Filename.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
str
|
|
137
|
+
Log path.
|
|
138
|
+
"""
|
|
139
|
+
return f"s3://{get_s3_bucket()}/{project}/{entity_type}/{name}/{uuid}/{filename}"
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def build_log_path_from_source(
|
|
143
|
+
project: str,
|
|
144
|
+
entity_type: str,
|
|
145
|
+
name: str,
|
|
146
|
+
uuid: str,
|
|
147
|
+
source: str | list[str],
|
|
148
|
+
) -> str:
|
|
149
|
+
"""
|
|
150
|
+
Build log path.
|
|
151
|
+
|
|
152
|
+
Parameters
|
|
153
|
+
----------
|
|
154
|
+
project : str
|
|
155
|
+
Project name.
|
|
156
|
+
entity_type : str
|
|
157
|
+
Entity type.
|
|
158
|
+
name : str
|
|
159
|
+
Object name.
|
|
160
|
+
uuid : str
|
|
161
|
+
Object UUID.
|
|
162
|
+
source : str | list[str]
|
|
163
|
+
Source(s).
|
|
164
|
+
|
|
165
|
+
Returns
|
|
166
|
+
-------
|
|
167
|
+
str
|
|
168
|
+
Log path.
|
|
169
|
+
"""
|
|
170
|
+
is_zip = eval_zip_type(source)
|
|
171
|
+
scheme = "zip+s3" if is_zip else "s3"
|
|
172
|
+
path = f"{scheme}://{get_s3_bucket()}/{project}/{entity_type}/{name}/{uuid}"
|
|
173
|
+
|
|
174
|
+
if isinstance(source, list) and len(source) >= 1:
|
|
175
|
+
if len(source) > 1:
|
|
176
|
+
path += "/"
|
|
177
|
+
else:
|
|
178
|
+
path += f"/{Path(source[0]).name}"
|
|
179
|
+
elif Path(source).is_dir():
|
|
180
|
+
path += "/"
|
|
181
|
+
elif Path(source).is_file():
|
|
182
|
+
path += f"/{Path(source).name}"
|
|
183
|
+
|
|
184
|
+
return path
|
|
File without changes
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from digitalhub.entities._builders.metadata import build_metadata
|
|
4
|
+
from digitalhub.entities._builders.name import build_name
|
|
5
|
+
from digitalhub.entities._builders.spec import build_spec
|
|
6
|
+
from digitalhub.entities._builders.status import build_status
|
|
7
|
+
from digitalhub.entities._builders.uuid import build_uuid
|
|
8
|
+
from digitalhub.entities.workflow.entity import Workflow
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def workflow_from_parameters(
|
|
12
|
+
project: str,
|
|
13
|
+
name: str,
|
|
14
|
+
kind: str,
|
|
15
|
+
uuid: str | None = None,
|
|
16
|
+
description: str | None = None,
|
|
17
|
+
labels: list[str] | None = None,
|
|
18
|
+
embedded: bool = True,
|
|
19
|
+
**kwargs,
|
|
20
|
+
) -> Workflow:
|
|
21
|
+
"""
|
|
22
|
+
Create a new object.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
project : str
|
|
27
|
+
Project name.
|
|
28
|
+
name : str
|
|
29
|
+
Object name.
|
|
30
|
+
kind : str
|
|
31
|
+
Kind the object.
|
|
32
|
+
uuid : str
|
|
33
|
+
ID of the object (UUID4, e.g. 40f25c4b-d26b-4221-b048-9527aff291e2).
|
|
34
|
+
labels : list[str]
|
|
35
|
+
List of labels.
|
|
36
|
+
description : str
|
|
37
|
+
Description of the object (human readable).
|
|
38
|
+
embedded : bool
|
|
39
|
+
Flag to determine if object spec must be embedded in project spec.
|
|
40
|
+
**kwargs : dict
|
|
41
|
+
Spec keyword arguments.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
Workflow
|
|
46
|
+
Object instance.
|
|
47
|
+
"""
|
|
48
|
+
name = build_name(name)
|
|
49
|
+
uuid = build_uuid(uuid)
|
|
50
|
+
spec = build_spec(
|
|
51
|
+
kind,
|
|
52
|
+
**kwargs,
|
|
53
|
+
)
|
|
54
|
+
metadata = build_metadata(
|
|
55
|
+
kind,
|
|
56
|
+
project=project,
|
|
57
|
+
name=name,
|
|
58
|
+
version=uuid,
|
|
59
|
+
description=description,
|
|
60
|
+
labels=labels,
|
|
61
|
+
embedded=embedded,
|
|
62
|
+
)
|
|
63
|
+
status = build_status(
|
|
64
|
+
kind,
|
|
65
|
+
)
|
|
66
|
+
return Workflow(
|
|
67
|
+
project=project,
|
|
68
|
+
name=name,
|
|
69
|
+
uuid=uuid,
|
|
70
|
+
kind=kind,
|
|
71
|
+
metadata=metadata,
|
|
72
|
+
spec=spec,
|
|
73
|
+
status=status,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def workflow_from_dict(obj: dict) -> Workflow:
|
|
78
|
+
"""
|
|
79
|
+
Create a new object from dictionary.
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
obj : dict
|
|
84
|
+
Dictionary to create object from.
|
|
85
|
+
|
|
86
|
+
Returns
|
|
87
|
+
-------
|
|
88
|
+
Workflow
|
|
89
|
+
Object instance.
|
|
90
|
+
"""
|
|
91
|
+
return Workflow.from_dict(obj)
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from digitalhub.context.builder import check_context
|
|
6
|
+
from digitalhub.entities._base.crud import (
|
|
7
|
+
delete_entity_api_ctx,
|
|
8
|
+
list_entity_api_ctx,
|
|
9
|
+
read_entity_api_ctx,
|
|
10
|
+
read_entity_api_ctx_versions,
|
|
11
|
+
)
|
|
12
|
+
from digitalhub.entities.entity_types import EntityTypes
|
|
13
|
+
from digitalhub.entities.workflow.builder import workflow_from_dict, workflow_from_parameters
|
|
14
|
+
from digitalhub.utils.exceptions import EntityAlreadyExistsError
|
|
15
|
+
from digitalhub.utils.io_utils import read_yaml
|
|
16
|
+
|
|
17
|
+
if typing.TYPE_CHECKING:
|
|
18
|
+
from digitalhub.entities.workflow.entity import Workflow
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
ENTITY_TYPE = EntityTypes.WORKFLOW.value
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def new_workflow(
|
|
25
|
+
project: str,
|
|
26
|
+
name: str,
|
|
27
|
+
kind: str,
|
|
28
|
+
uuid: str | None = None,
|
|
29
|
+
description: str | None = None,
|
|
30
|
+
labels: list[str] | None = None,
|
|
31
|
+
embedded: bool = True,
|
|
32
|
+
**kwargs,
|
|
33
|
+
) -> Workflow:
|
|
34
|
+
"""
|
|
35
|
+
Create a new object.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
project : str
|
|
40
|
+
Project name.
|
|
41
|
+
name : str
|
|
42
|
+
Object name.
|
|
43
|
+
uuid : str
|
|
44
|
+
ID of the object (UUID4, e.g. 40f25c4b-d26b-4221-b048-9527aff291e2).
|
|
45
|
+
description : str
|
|
46
|
+
Description of the object (human readable).
|
|
47
|
+
labels : list[str]
|
|
48
|
+
List of labels.
|
|
49
|
+
embedded : bool
|
|
50
|
+
Flag to determine if object spec must be embedded in project spec.
|
|
51
|
+
**kwargs : dict
|
|
52
|
+
Spec keyword arguments.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
Workflow
|
|
57
|
+
Object instance.
|
|
58
|
+
|
|
59
|
+
Examples
|
|
60
|
+
--------
|
|
61
|
+
>>> obj = new_function(project="my-project",
|
|
62
|
+
>>> name="my-workflow",
|
|
63
|
+
>>> kind="kfp",
|
|
64
|
+
>>> code_src="pipeline.py",
|
|
65
|
+
>>> handler="pipeline-handler")
|
|
66
|
+
"""
|
|
67
|
+
check_context(project)
|
|
68
|
+
obj = workflow_from_parameters(
|
|
69
|
+
project=project,
|
|
70
|
+
name=name,
|
|
71
|
+
kind=kind,
|
|
72
|
+
uuid=uuid,
|
|
73
|
+
description=description,
|
|
74
|
+
labels=labels,
|
|
75
|
+
embedded=embedded,
|
|
76
|
+
**kwargs,
|
|
77
|
+
)
|
|
78
|
+
obj.save()
|
|
79
|
+
return obj
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def get_workflow(
|
|
83
|
+
identifier: str,
|
|
84
|
+
project: str | None = None,
|
|
85
|
+
entity_id: str | None = None,
|
|
86
|
+
**kwargs,
|
|
87
|
+
) -> Workflow:
|
|
88
|
+
"""
|
|
89
|
+
Get object from backend.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
identifier : str
|
|
94
|
+
Entity key (store://...) or entity name.
|
|
95
|
+
project : str
|
|
96
|
+
Project name.
|
|
97
|
+
entity_id : str
|
|
98
|
+
Entity ID.
|
|
99
|
+
**kwargs : dict
|
|
100
|
+
Parameters to pass to the API call.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
Workflow
|
|
105
|
+
Object instance.
|
|
106
|
+
|
|
107
|
+
Examples
|
|
108
|
+
--------
|
|
109
|
+
Using entity key:
|
|
110
|
+
>>> obj = get_workflow("store://my-workflow-key")
|
|
111
|
+
|
|
112
|
+
Using entity name:
|
|
113
|
+
>>> obj = get_workflow("my-workflow-name"
|
|
114
|
+
>>> project="my-project",
|
|
115
|
+
>>> entity_id="my-workflow-id")
|
|
116
|
+
"""
|
|
117
|
+
obj = read_entity_api_ctx(
|
|
118
|
+
identifier,
|
|
119
|
+
ENTITY_TYPE,
|
|
120
|
+
project=project,
|
|
121
|
+
entity_id=entity_id,
|
|
122
|
+
**kwargs,
|
|
123
|
+
)
|
|
124
|
+
return workflow_from_dict(obj)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def get_workflow_versions(
|
|
128
|
+
identifier: str,
|
|
129
|
+
project: str | None = None,
|
|
130
|
+
**kwargs,
|
|
131
|
+
) -> list[Workflow]:
|
|
132
|
+
"""
|
|
133
|
+
Get object versions from backend.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
identifier : str
|
|
138
|
+
Entity key (store://...) or entity name.
|
|
139
|
+
project : str
|
|
140
|
+
Project name.
|
|
141
|
+
**kwargs : dict
|
|
142
|
+
Parameters to pass to the API call.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
list[Workflow]
|
|
147
|
+
List of object instances.
|
|
148
|
+
|
|
149
|
+
Examples
|
|
150
|
+
--------
|
|
151
|
+
Using entity key:
|
|
152
|
+
>>> obj = get_workflow_versions("store://my-workflow-key")
|
|
153
|
+
|
|
154
|
+
Using entity name:
|
|
155
|
+
>>> obj = get_workflow_versions("my-workflow-name"
|
|
156
|
+
>>> project="my-project")
|
|
157
|
+
"""
|
|
158
|
+
obj = read_entity_api_ctx_versions(
|
|
159
|
+
identifier,
|
|
160
|
+
entity_type=ENTITY_TYPE,
|
|
161
|
+
project=project,
|
|
162
|
+
**kwargs,
|
|
163
|
+
)
|
|
164
|
+
return [workflow_from_dict(o) for o in obj]
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def list_workflows(project: str, **kwargs) -> list[Workflow]:
|
|
168
|
+
"""
|
|
169
|
+
List all latest version objects from backend.
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
project : str
|
|
174
|
+
Project name.
|
|
175
|
+
**kwargs : dict
|
|
176
|
+
Parameters to pass to the API call.
|
|
177
|
+
|
|
178
|
+
Returns
|
|
179
|
+
-------
|
|
180
|
+
list[Workflow]
|
|
181
|
+
List of object instances.
|
|
182
|
+
|
|
183
|
+
Examples
|
|
184
|
+
--------
|
|
185
|
+
>>> objs = list_workflows(project="my-project")
|
|
186
|
+
"""
|
|
187
|
+
objs = list_entity_api_ctx(
|
|
188
|
+
project=project,
|
|
189
|
+
entity_type=ENTITY_TYPE,
|
|
190
|
+
**kwargs,
|
|
191
|
+
)
|
|
192
|
+
return [workflow_from_dict(obj) for obj in objs]
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def import_workflow(file: str) -> Workflow:
|
|
196
|
+
"""
|
|
197
|
+
Import object from a YAML file.
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
file : str
|
|
202
|
+
Path to YAML file.
|
|
203
|
+
|
|
204
|
+
Returns
|
|
205
|
+
-------
|
|
206
|
+
Workflow
|
|
207
|
+
Object instance.
|
|
208
|
+
|
|
209
|
+
Examples
|
|
210
|
+
--------
|
|
211
|
+
>>> obj = import_workflow("my-workflow.yaml")
|
|
212
|
+
"""
|
|
213
|
+
dict_obj: dict | list[dict] = read_yaml(file)
|
|
214
|
+
if isinstance(dict_obj, list):
|
|
215
|
+
wkf_dict = dict_obj[0]
|
|
216
|
+
tsk_dicts = dict_obj[1:]
|
|
217
|
+
else:
|
|
218
|
+
wkf_dict = dict_obj
|
|
219
|
+
tsk_dicts = []
|
|
220
|
+
|
|
221
|
+
check_context(wkf_dict.get("project"))
|
|
222
|
+
obj = workflow_from_dict(wkf_dict)
|
|
223
|
+
|
|
224
|
+
obj.import_tasks(tsk_dicts)
|
|
225
|
+
|
|
226
|
+
try:
|
|
227
|
+
obj.save()
|
|
228
|
+
except EntityAlreadyExistsError:
|
|
229
|
+
pass
|
|
230
|
+
finally:
|
|
231
|
+
return obj
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def update_workflow(entity: Workflow) -> Workflow:
|
|
235
|
+
"""
|
|
236
|
+
Update object. Note that object spec are immutable.
|
|
237
|
+
|
|
238
|
+
Parameters
|
|
239
|
+
----------
|
|
240
|
+
entity : Workflow
|
|
241
|
+
Object to update.
|
|
242
|
+
|
|
243
|
+
Returns
|
|
244
|
+
-------
|
|
245
|
+
Workflow
|
|
246
|
+
Entity updated.
|
|
247
|
+
|
|
248
|
+
Examples
|
|
249
|
+
--------
|
|
250
|
+
>>> obj = update_workflow(obj)
|
|
251
|
+
"""
|
|
252
|
+
return entity.save(update=True)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def delete_workflow(
|
|
256
|
+
identifier: str,
|
|
257
|
+
project: str | None = None,
|
|
258
|
+
entity_id: str | None = None,
|
|
259
|
+
delete_all_versions: bool = False,
|
|
260
|
+
cascade: bool = True,
|
|
261
|
+
**kwargs,
|
|
262
|
+
) -> dict:
|
|
263
|
+
"""
|
|
264
|
+
Delete object from backend.
|
|
265
|
+
|
|
266
|
+
Parameters
|
|
267
|
+
----------
|
|
268
|
+
identifier : str
|
|
269
|
+
Entity key (store://...) or entity name.
|
|
270
|
+
project : str
|
|
271
|
+
Project name.
|
|
272
|
+
entity_id : str
|
|
273
|
+
Entity ID.
|
|
274
|
+
delete_all_versions : bool
|
|
275
|
+
Delete all versions of the named entity. If True, use entity name instead of entity key as identifier.
|
|
276
|
+
cascade : bool
|
|
277
|
+
Cascade delete.
|
|
278
|
+
**kwargs : dict
|
|
279
|
+
Parameters to pass to the API call.
|
|
280
|
+
|
|
281
|
+
Returns
|
|
282
|
+
-------
|
|
283
|
+
dict
|
|
284
|
+
Response from backend.
|
|
285
|
+
|
|
286
|
+
Examples
|
|
287
|
+
--------
|
|
288
|
+
If delete_all_versions is False:
|
|
289
|
+
>>> obj = delete_workflow("store://my-workflow-key")
|
|
290
|
+
|
|
291
|
+
Otherwise:
|
|
292
|
+
>>> obj = delete_workflow("workflow-name",
|
|
293
|
+
>>> project="my-project",
|
|
294
|
+
>>> delete_all_versions=True)
|
|
295
|
+
"""
|
|
296
|
+
return delete_entity_api_ctx(
|
|
297
|
+
identifier=identifier,
|
|
298
|
+
entity_type=ENTITY_TYPE,
|
|
299
|
+
project=project,
|
|
300
|
+
entity_id=entity_id,
|
|
301
|
+
delete_all_versions=delete_all_versions,
|
|
302
|
+
cascade=cascade,
|
|
303
|
+
**kwargs,
|
|
304
|
+
)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from digitalhub.entities._base.entity.executable import ExecutableEntity
|
|
6
|
+
from digitalhub.entities.entity_types import EntityTypes
|
|
7
|
+
from digitalhub.runtimes.builder import get_kind_registry
|
|
8
|
+
from digitalhub.utils.exceptions import BackendError
|
|
9
|
+
|
|
10
|
+
if typing.TYPE_CHECKING:
|
|
11
|
+
from digitalhub.entities._base.metadata import Metadata
|
|
12
|
+
from digitalhub.entities.run.entity import Run
|
|
13
|
+
from digitalhub.entities.workflow.spec import WorkflowSpec
|
|
14
|
+
from digitalhub.entities.workflow.status import WorkflowStatus
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Workflow(ExecutableEntity):
|
|
18
|
+
"""
|
|
19
|
+
A class representing a workflow.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
ENTITY_TYPE = EntityTypes.WORKFLOW.value
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
project: str,
|
|
27
|
+
name: str,
|
|
28
|
+
uuid: str,
|
|
29
|
+
kind: str,
|
|
30
|
+
metadata: Metadata,
|
|
31
|
+
spec: WorkflowSpec,
|
|
32
|
+
status: WorkflowStatus,
|
|
33
|
+
user: str | None = None,
|
|
34
|
+
) -> None:
|
|
35
|
+
super().__init__(project, name, uuid, kind, metadata, spec, status, user)
|
|
36
|
+
|
|
37
|
+
self.spec: WorkflowSpec
|
|
38
|
+
self.status: WorkflowStatus
|
|
39
|
+
|
|
40
|
+
##############################
|
|
41
|
+
# Workflow Methods
|
|
42
|
+
##############################
|
|
43
|
+
|
|
44
|
+
def run(self, action: str | None = None, **kwargs) -> Run:
|
|
45
|
+
"""
|
|
46
|
+
Run workflow.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
action : str
|
|
51
|
+
Action to execute.
|
|
52
|
+
**kwargs : dict
|
|
53
|
+
Keyword arguments passed to Run builder.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
Run
|
|
58
|
+
Run instance.
|
|
59
|
+
"""
|
|
60
|
+
if action is None:
|
|
61
|
+
action = "pipeline"
|
|
62
|
+
|
|
63
|
+
# Get kind registry
|
|
64
|
+
kind_reg = get_kind_registry(self.kind)
|
|
65
|
+
|
|
66
|
+
# Get task and run kind
|
|
67
|
+
task_kind = kind_reg.get_task_kind_from_action(action=action)
|
|
68
|
+
run_kind = kind_reg.get_run_kind()
|
|
69
|
+
|
|
70
|
+
# Create or update new task
|
|
71
|
+
task = self._get_or_create_task(task_kind)
|
|
72
|
+
|
|
73
|
+
# Raise error if execution is not done by DHCore backend
|
|
74
|
+
if self._context().local:
|
|
75
|
+
raise BackendError("Cannot run workflow with local backend.")
|
|
76
|
+
|
|
77
|
+
return task.run(run_kind, local_execution=False, **kwargs)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from digitalhub.entities._base.spec.base import Spec, SpecParams
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WorkflowSpec(Spec):
|
|
7
|
+
"""
|
|
8
|
+
Workflow specifications.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WorkflowParams(SpecParams):
|
|
13
|
+
"""
|
|
14
|
+
Workflow parameters.
|
|
15
|
+
"""
|
|
File without changes
|