digitalhub 0.8.0__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.

Files changed (248) hide show
  1. digitalhub/__init__.py +4 -5
  2. digitalhub/client/builder.py +58 -3
  3. digitalhub/client/{dhcore/client.py → objects/dhcore.py} +60 -48
  4. digitalhub/client/{local/client.py → objects/local.py} +2 -2
  5. digitalhub/context/builder.py +85 -1
  6. digitalhub/context/context.py +1 -1
  7. digitalhub/datastores/builder.py +37 -13
  8. digitalhub/datastores/{_base/datastore.py → objects/base.py} +3 -3
  9. digitalhub/datastores/{local/datastore.py → objects/local.py} +2 -10
  10. digitalhub/datastores/{remote/datastore.py → objects/remote.py} +1 -9
  11. digitalhub/datastores/{s3/datastore.py → objects/s3.py} +2 -10
  12. digitalhub/datastores/{sql/datastore.py → objects/sql.py} +2 -10
  13. digitalhub/entities/_base/{_base/entity.py → base.py} +1 -1
  14. digitalhub/entities/_base/crud.py +389 -247
  15. digitalhub/entities/_base/entity/{entity.py → base.py} +34 -8
  16. digitalhub/entities/_base/{context/entity.py → entity/context.py} +6 -6
  17. digitalhub/entities/_base/{executable/entity.py → entity/executable.py} +36 -61
  18. digitalhub/entities/_base/{material/entity.py → entity/material.py} +6 -6
  19. digitalhub/entities/_base/entity/unversioned.py +87 -0
  20. digitalhub/entities/_base/entity/versioned.py +94 -0
  21. digitalhub/entities/_base/{entity/metadata.py → metadata.py} +2 -2
  22. digitalhub/entities/_base/{entity/spec.py → spec/base.py} +11 -11
  23. digitalhub/entities/_base/{material/spec.py → spec/material.py} +3 -3
  24. digitalhub/entities/_base/{entity/status.py → status/base.py} +3 -14
  25. digitalhub/entities/_base/{material/status.py → status/material.py} +1 -1
  26. digitalhub/entities/_builders/metadata.py +60 -0
  27. digitalhub/entities/_builders/spec.py +43 -0
  28. digitalhub/entities/_builders/status.py +62 -0
  29. digitalhub/entities/{_base/entity/_constructors → _builders}/uuid.py +11 -4
  30. digitalhub/entities/artifact/builder.py +133 -0
  31. digitalhub/entities/artifact/crud.py +48 -22
  32. digitalhub/entities/artifact/{_base/entity.py → entity/_base.py} +5 -5
  33. digitalhub/entities/artifact/entity/artifact.py +9 -0
  34. digitalhub/entities/artifact/{artifact/spec.py → spec.py} +16 -4
  35. digitalhub/entities/artifact/{artifact/status.py → status.py} +1 -1
  36. digitalhub/entities/dataitem/builder.py +144 -0
  37. digitalhub/entities/dataitem/crud.py +52 -29
  38. digitalhub/entities/dataitem/{_base/entity.py → entity/_base.py} +5 -5
  39. digitalhub/entities/dataitem/entity/dataitem.py +9 -0
  40. digitalhub/entities/dataitem/entity/iceberg.py +7 -0
  41. digitalhub/entities/dataitem/{table/entity.py → entity/table.py} +4 -25
  42. digitalhub/entities/dataitem/spec.py +61 -0
  43. digitalhub/entities/dataitem/status.py +38 -0
  44. digitalhub/entities/function/builder.py +86 -0
  45. digitalhub/entities/function/crud.py +43 -17
  46. digitalhub/entities/function/{_base/entity.py → entity.py} +12 -9
  47. digitalhub/entities/function/{_base/models.py → models.py} +1 -1
  48. digitalhub/entities/function/spec.py +81 -0
  49. digitalhub/entities/function/status.py +9 -0
  50. digitalhub/entities/model/builder.py +152 -0
  51. digitalhub/entities/model/crud.py +48 -21
  52. digitalhub/entities/model/{_base/entity.py → entity/_base.py} +5 -5
  53. digitalhub/entities/model/entity/huggingface.py +9 -0
  54. digitalhub/entities/model/{mlflow/utils.py → entity/mlflow.py} +10 -1
  55. digitalhub/entities/model/entity/model.py +9 -0
  56. digitalhub/entities/model/entity/sklearn.py +9 -0
  57. digitalhub/entities/model/spec.py +146 -0
  58. digitalhub/entities/model/status.py +33 -0
  59. digitalhub/entities/project/builder.py +82 -0
  60. digitalhub/entities/project/crud.py +12 -19
  61. digitalhub/entities/project/{_base/entity.py → entity.py} +102 -120
  62. digitalhub/entities/project/{_base/spec.py → spec.py} +4 -4
  63. digitalhub/entities/project/status.py +9 -0
  64. digitalhub/entities/registries.py +48 -0
  65. digitalhub/entities/run/builder.py +77 -0
  66. digitalhub/entities/run/crud.py +33 -20
  67. digitalhub/entities/run/{_base/entity.py → entity.py} +189 -35
  68. digitalhub/entities/run/spec.py +153 -0
  69. digitalhub/entities/run/status.py +114 -0
  70. digitalhub/entities/secret/builder.py +93 -0
  71. digitalhub/entities/secret/crud.py +31 -27
  72. digitalhub/entities/secret/{_base/entity.py → entity.py} +7 -8
  73. digitalhub/entities/secret/{_base/spec.py → spec.py} +4 -4
  74. digitalhub/entities/secret/status.py +9 -0
  75. digitalhub/entities/task/builder.py +74 -0
  76. digitalhub/entities/task/crud.py +33 -20
  77. digitalhub/entities/task/{_base/entity.py → entity.py} +8 -9
  78. digitalhub/entities/task/{_base/models.py → models.py} +0 -9
  79. digitalhub/entities/task/{_base/spec.py → spec.py} +7 -9
  80. digitalhub/entities/task/status.py +9 -0
  81. digitalhub/entities/{utils/utils.py → utils.py} +2 -20
  82. digitalhub/entities/workflow/builder.py +91 -0
  83. digitalhub/entities/workflow/crud.py +43 -17
  84. digitalhub/entities/workflow/{_base/entity.py → entity.py} +12 -9
  85. digitalhub/entities/workflow/spec.py +15 -0
  86. digitalhub/entities/workflow/status.py +9 -0
  87. digitalhub/readers/builder.py +54 -0
  88. digitalhub/readers/{pandas/reader.py → objects/pandas.py} +1 -1
  89. digitalhub/readers/registry.py +15 -0
  90. digitalhub/registry/models.py +87 -0
  91. digitalhub/registry/registry.py +74 -0
  92. digitalhub/registry/utils.py +150 -0
  93. digitalhub/runtimes/{_base.py → base.py} +65 -3
  94. digitalhub/runtimes/builder.py +40 -19
  95. digitalhub/runtimes/kind_registry.py +170 -0
  96. digitalhub/stores/builder.py +52 -6
  97. digitalhub/stores/{local/store.py → objects/local.py} +1 -1
  98. digitalhub/stores/{remote/store.py → objects/remote.py} +1 -1
  99. digitalhub/stores/{s3/store.py → objects/s3.py} +1 -1
  100. digitalhub/stores/{sql/store.py → objects/sql.py} +1 -1
  101. digitalhub/{client/dhcore/utils.py → utils/env_utils.py} +14 -2
  102. digitalhub/utils/exceptions.py +0 -12
  103. digitalhub/utils/generic_utils.py +42 -18
  104. digitalhub/utils/io_utils.py +2 -39
  105. {digitalhub-0.8.0.dist-info → digitalhub-0.8.0b1.dist-info}/METADATA +2 -3
  106. digitalhub-0.8.0b1.dist-info/RECORD +161 -0
  107. {digitalhub-0.8.0.dist-info → digitalhub-0.8.0b1.dist-info}/WHEEL +1 -1
  108. test/test_crud_artifacts.py +96 -0
  109. test/test_crud_dataitems.py +96 -0
  110. test/test_crud_functions.py +1 -1
  111. test/test_crud_runs.py +1 -1
  112. test/test_crud_tasks.py +1 -1
  113. digitalhub/client/api.py +0 -63
  114. digitalhub/client/dhcore/env.py +0 -21
  115. digitalhub/client/dhcore/models.py +0 -46
  116. digitalhub/context/api.py +0 -93
  117. digitalhub/datastores/api.py +0 -37
  118. digitalhub/entities/_base/api_utils.py +0 -620
  119. digitalhub/entities/_base/entity/_constructors/metadata.py +0 -44
  120. digitalhub/entities/_base/entity/_constructors/spec.py +0 -33
  121. digitalhub/entities/_base/entity/_constructors/status.py +0 -52
  122. digitalhub/entities/_base/entity/builder.py +0 -175
  123. digitalhub/entities/_base/executable/__init__.py +0 -0
  124. digitalhub/entities/_base/material/__init__.py +0 -0
  125. digitalhub/entities/_base/runtime_entity/__init__.py +0 -0
  126. digitalhub/entities/_base/runtime_entity/builder.py +0 -106
  127. digitalhub/entities/_base/unversioned/__init__.py +0 -0
  128. digitalhub/entities/_base/unversioned/builder.py +0 -66
  129. digitalhub/entities/_base/unversioned/entity.py +0 -49
  130. digitalhub/entities/_base/versioned/__init__.py +0 -0
  131. digitalhub/entities/_base/versioned/builder.py +0 -68
  132. digitalhub/entities/_base/versioned/entity.py +0 -53
  133. digitalhub/entities/artifact/_base/__init__.py +0 -0
  134. digitalhub/entities/artifact/_base/builder.py +0 -86
  135. digitalhub/entities/artifact/_base/spec.py +0 -15
  136. digitalhub/entities/artifact/_base/status.py +0 -9
  137. digitalhub/entities/artifact/artifact/__init__.py +0 -0
  138. digitalhub/entities/artifact/artifact/builder.py +0 -18
  139. digitalhub/entities/artifact/artifact/entity.py +0 -32
  140. digitalhub/entities/builders.py +0 -63
  141. digitalhub/entities/dataitem/_base/__init__.py +0 -0
  142. digitalhub/entities/dataitem/_base/builder.py +0 -86
  143. digitalhub/entities/dataitem/_base/spec.py +0 -15
  144. digitalhub/entities/dataitem/_base/status.py +0 -20
  145. digitalhub/entities/dataitem/dataitem/__init__.py +0 -0
  146. digitalhub/entities/dataitem/dataitem/builder.py +0 -18
  147. digitalhub/entities/dataitem/dataitem/entity.py +0 -32
  148. digitalhub/entities/dataitem/dataitem/spec.py +0 -15
  149. digitalhub/entities/dataitem/dataitem/status.py +0 -9
  150. digitalhub/entities/dataitem/iceberg/__init__.py +0 -0
  151. digitalhub/entities/dataitem/iceberg/builder.py +0 -18
  152. digitalhub/entities/dataitem/iceberg/entity.py +0 -32
  153. digitalhub/entities/dataitem/iceberg/spec.py +0 -15
  154. digitalhub/entities/dataitem/iceberg/status.py +0 -9
  155. digitalhub/entities/dataitem/table/__init__.py +0 -0
  156. digitalhub/entities/dataitem/table/builder.py +0 -18
  157. digitalhub/entities/dataitem/table/spec.py +0 -25
  158. digitalhub/entities/dataitem/table/status.py +0 -9
  159. digitalhub/entities/function/_base/__init__.py +0 -0
  160. digitalhub/entities/function/_base/builder.py +0 -79
  161. digitalhub/entities/function/_base/spec.py +0 -15
  162. digitalhub/entities/function/_base/status.py +0 -9
  163. digitalhub/entities/model/_base/__init__.py +0 -0
  164. digitalhub/entities/model/_base/builder.py +0 -86
  165. digitalhub/entities/model/_base/spec.py +0 -49
  166. digitalhub/entities/model/_base/status.py +0 -9
  167. digitalhub/entities/model/huggingface/__init__.py +0 -0
  168. digitalhub/entities/model/huggingface/builder.py +0 -18
  169. digitalhub/entities/model/huggingface/entity.py +0 -32
  170. digitalhub/entities/model/huggingface/spec.py +0 -36
  171. digitalhub/entities/model/huggingface/status.py +0 -9
  172. digitalhub/entities/model/mlflow/__init__.py +0 -0
  173. digitalhub/entities/model/mlflow/builder.py +0 -18
  174. digitalhub/entities/model/mlflow/entity.py +0 -32
  175. digitalhub/entities/model/mlflow/spec.py +0 -44
  176. digitalhub/entities/model/mlflow/status.py +0 -9
  177. digitalhub/entities/model/model/__init__.py +0 -0
  178. digitalhub/entities/model/model/builder.py +0 -18
  179. digitalhub/entities/model/model/entity.py +0 -32
  180. digitalhub/entities/model/model/spec.py +0 -15
  181. digitalhub/entities/model/model/status.py +0 -9
  182. digitalhub/entities/model/sklearn/__init__.py +0 -0
  183. digitalhub/entities/model/sklearn/builder.py +0 -18
  184. digitalhub/entities/model/sklearn/entity.py +0 -32
  185. digitalhub/entities/model/sklearn/spec.py +0 -15
  186. digitalhub/entities/model/sklearn/status.py +0 -9
  187. digitalhub/entities/project/_base/__init__.py +0 -0
  188. digitalhub/entities/project/_base/builder.py +0 -128
  189. digitalhub/entities/project/_base/status.py +0 -9
  190. digitalhub/entities/run/_base/__init__.py +0 -0
  191. digitalhub/entities/run/_base/builder.py +0 -94
  192. digitalhub/entities/run/_base/spec.py +0 -50
  193. digitalhub/entities/run/_base/status.py +0 -9
  194. digitalhub/entities/secret/_base/__init__.py +0 -0
  195. digitalhub/entities/secret/_base/builder.py +0 -81
  196. digitalhub/entities/secret/_base/status.py +0 -9
  197. digitalhub/entities/task/_base/__init__.py +0 -0
  198. digitalhub/entities/task/_base/builder.py +0 -91
  199. digitalhub/entities/task/_base/status.py +0 -9
  200. digitalhub/entities/utils/__init__.py +0 -0
  201. digitalhub/entities/workflow/_base/__init__.py +0 -0
  202. digitalhub/entities/workflow/_base/builder.py +0 -79
  203. digitalhub/entities/workflow/_base/spec.py +0 -15
  204. digitalhub/entities/workflow/_base/status.py +0 -9
  205. digitalhub/factory/__init__.py +0 -0
  206. digitalhub/factory/api.py +0 -277
  207. digitalhub/factory/factory.py +0 -268
  208. digitalhub/factory/utils.py +0 -90
  209. digitalhub/readers/_base/__init__.py +0 -0
  210. digitalhub/readers/_base/builder.py +0 -26
  211. digitalhub/readers/api.py +0 -80
  212. digitalhub/readers/factory.py +0 -133
  213. digitalhub/readers/pandas/__init__.py +0 -0
  214. digitalhub/readers/pandas/builder.py +0 -29
  215. digitalhub/stores/_base/__init__.py +0 -0
  216. digitalhub/stores/api.py +0 -54
  217. digitalhub/stores/local/__init__.py +0 -0
  218. digitalhub/stores/remote/__init__.py +0 -0
  219. digitalhub/stores/s3/__init__.py +0 -0
  220. digitalhub/stores/sql/__init__.py +0 -0
  221. digitalhub/utils/s3_utils.py +0 -58
  222. digitalhub-0.8.0.dist-info/RECORD +0 -231
  223. test/local/CRUD/test_artifacts.py +0 -96
  224. test/local/CRUD/test_dataitems.py +0 -96
  225. test/local/CRUD/test_models.py +0 -95
  226. /digitalhub/client/{_base → objects}/__init__.py +0 -0
  227. /digitalhub/client/{_base/client.py → objects/base.py} +0 -0
  228. /digitalhub/{client/dhcore → datastores/objects}/__init__.py +0 -0
  229. /digitalhub/entities/{utils → _base}/api.py +0 -0
  230. /digitalhub/{client/local → entities/_base/spec}/__init__.py +0 -0
  231. /digitalhub/entities/{utils → _base}/state.py +0 -0
  232. /digitalhub/{datastores/_base → entities/_base/status}/__init__.py +0 -0
  233. /digitalhub/{datastores/local → entities/_builders}/__init__.py +0 -0
  234. /digitalhub/entities/{_base/entity/_constructors → _builders}/name.py +0 -0
  235. /digitalhub/{datastores/remote → entities/artifact/entity}/__init__.py +0 -0
  236. /digitalhub/{datastores/s3 → entities/dataitem/entity}/__init__.py +0 -0
  237. /digitalhub/entities/dataitem/{table/models.py → models.py} +0 -0
  238. /digitalhub/entities/{utils/entity_types.py → entity_types.py} +0 -0
  239. /digitalhub/{datastores/sql → entities/model/entity}/__init__.py +0 -0
  240. /digitalhub/entities/model/{mlflow/models.py → models.py} +0 -0
  241. /digitalhub/{entities/_base/_base → readers/objects}/__init__.py +0 -0
  242. /digitalhub/readers/{_base/reader.py → objects/base.py} +0 -0
  243. /digitalhub/{entities/_base/context → registry}/__init__.py +0 -0
  244. /digitalhub/{entities/_base/entity/_constructors → stores/objects}/__init__.py +0 -0
  245. /digitalhub/stores/{_base/store.py → objects/base.py} +0 -0
  246. {digitalhub-0.8.0.dist-info → digitalhub-0.8.0b1.dist-info}/LICENSE.txt +0 -0
  247. {digitalhub-0.8.0.dist-info → digitalhub-0.8.0b1.dist-info}/top_level.txt +0 -0
  248. /test/{local/imports/test_imports.py → test_imports.py} +0 -0
@@ -0,0 +1,77 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalhub.entities._builders.metadata import build_metadata
4
+ from digitalhub.entities._builders.spec import build_spec
5
+ from digitalhub.entities._builders.status import build_status
6
+ from digitalhub.entities._builders.uuid import build_uuid
7
+ from digitalhub.entities.run.entity import Run
8
+
9
+
10
+ def run_from_parameters(
11
+ project: str,
12
+ kind: str,
13
+ uuid: str | None = None,
14
+ labels: list[str] | None = None,
15
+ task: str | None = None,
16
+ local_execution: bool = False,
17
+ **kwargs,
18
+ ) -> Run:
19
+ """
20
+ Create run.
21
+
22
+ Parameters
23
+ ----------
24
+ project : str
25
+ Project name.
26
+ kind : str
27
+ Kind the object.
28
+ uuid : str
29
+ ID of the object (UUID4, e.g. 40f25c4b-d26b-4221-b048-9527aff291e2).
30
+ labels : list[str]
31
+ List of labels.
32
+ task : str
33
+ Name of the task associated with the run.
34
+ local_execution : bool
35
+ Flag to determine if object has local execution.
36
+ **kwargs : dict
37
+ Spec keyword arguments.
38
+
39
+ Returns
40
+ -------
41
+ Run
42
+ Object instance.
43
+ """
44
+ uuid = build_uuid(uuid)
45
+ metadata = build_metadata(
46
+ kind=kind,
47
+ project=project,
48
+ name=uuid,
49
+ labels=labels,
50
+ )
51
+ spec = build_spec(kind, task=task, local_execution=local_execution, **kwargs)
52
+ status = build_status(kind)
53
+ return Run(
54
+ project=project,
55
+ uuid=uuid,
56
+ kind=kind,
57
+ metadata=metadata,
58
+ spec=spec,
59
+ status=status,
60
+ )
61
+
62
+
63
+ def run_from_dict(obj: dict) -> Run:
64
+ """
65
+ Create a new object from dictionary.
66
+
67
+ Parameters
68
+ ----------
69
+ obj : dict
70
+ Dictionary to create object from.
71
+
72
+ Returns
73
+ -------
74
+ Run
75
+ Object instance.
76
+ """
77
+ return Run.from_dict(obj)
@@ -2,18 +2,15 @@ from __future__ import annotations
2
2
 
3
3
  import typing
4
4
 
5
- from digitalhub.entities._base.crud import (
6
- delete_entity,
7
- get_unversioned_entity,
8
- import_context_entity,
9
- list_context_entities,
10
- new_context_entity,
11
- )
12
- from digitalhub.entities.utils.entity_types import EntityTypes
13
- from digitalhub.utils.exceptions import EntityError
5
+ from digitalhub.context.builder import check_context
6
+ from digitalhub.entities._base.crud import delete_entity_api_ctx, list_entity_api_ctx, read_entity_api_ctx
7
+ from digitalhub.entities.entity_types import EntityTypes
8
+ from digitalhub.entities.run.builder import run_from_dict, run_from_parameters
9
+ from digitalhub.utils.exceptions import EntityAlreadyExistsError, EntityError
10
+ from digitalhub.utils.io_utils import read_yaml
14
11
 
15
12
  if typing.TYPE_CHECKING:
16
- from digitalhub.entities.run._base.entity import Run
13
+ from digitalhub.entities.run.entity import Run
17
14
 
18
15
 
19
16
  ENTITY_TYPE = EntityTypes.RUN.value
@@ -38,7 +35,7 @@ def new_run(
38
35
  kind : str
39
36
  Kind the object.
40
37
  uuid : str
41
- ID of the object.
38
+ ID of the object (UUID4, e.g. 40f25c4b-d26b-4221-b048-9527aff291e2).
42
39
  labels : list[str]
43
40
  List of labels.
44
41
  task : str
@@ -55,11 +52,13 @@ def new_run(
55
52
 
56
53
  Examples
57
54
  --------
58
- >>> obj = new_run(project="my-project",
59
- >>> kind="python+run",
60
- >>> task="task-string")
55
+ >>> obj = new_function(project="my-project",
56
+ >>> name="my-function",
57
+ >>> kind="python+run",
58
+ >>> task="task-string"
61
59
  """
62
- return new_context_entity(
60
+ check_context(project)
61
+ obj = run_from_parameters(
63
62
  project=project,
64
63
  kind=kind,
65
64
  uuid=uuid,
@@ -68,6 +67,8 @@ def new_run(
68
67
  local_execution=local_execution,
69
68
  **kwargs,
70
69
  )
70
+ obj.save()
71
+ return obj
71
72
 
72
73
 
73
74
  def get_run(
@@ -101,12 +102,16 @@ def get_run(
101
102
  >>> obj = get_run("my-run-id"
102
103
  >>> project="my-project")
103
104
  """
104
- return get_unversioned_entity(
105
+ if not identifier.startswith("store://") and project is None:
106
+ raise EntityError("Specify entity key or entity ID combined with project")
107
+ obj = read_entity_api_ctx(
105
108
  identifier,
106
- entity_type=ENTITY_TYPE,
109
+ ENTITY_TYPE,
107
110
  project=project,
111
+ entity_id=identifier,
108
112
  **kwargs,
109
113
  )
114
+ return run_from_dict(obj)
110
115
 
111
116
 
112
117
  def list_runs(project: str, **kwargs) -> list[Run]:
@@ -130,11 +135,12 @@ def list_runs(project: str, **kwargs) -> list[Run]:
130
135
  >>> objs = list_runs(project="my-project")
131
136
  """
132
137
  # TODO more examples: search by function, latest for task and function
133
- return list_context_entities(
138
+ objs = list_entity_api_ctx(
134
139
  project=project,
135
140
  entity_type=ENTITY_TYPE,
136
141
  **kwargs,
137
142
  )
143
+ return [run_from_dict(obj) for obj in objs]
138
144
 
139
145
 
140
146
  def import_run(file: str) -> Run:
@@ -155,7 +161,14 @@ def import_run(file: str) -> Run:
155
161
  -------
156
162
  >>> obj = import_run("my-run.yaml")
157
163
  """
158
- return import_context_entity(file)
164
+ dict_obj: dict = read_yaml(file)
165
+ obj = run_from_dict(dict_obj)
166
+ try:
167
+ obj.save()
168
+ except EntityAlreadyExistsError:
169
+ pass
170
+ finally:
171
+ return obj
159
172
 
160
173
 
161
174
  def update_run(entity: Run) -> Run:
@@ -208,7 +221,7 @@ def delete_run(
208
221
  """
209
222
  if not identifier.startswith("store://") and project is None:
210
223
  raise EntityError("Specify entity key or entity ID combined with project")
211
- return delete_entity(
224
+ return delete_entity_api_ctx(
212
225
  identifier=identifier,
213
226
  entity_type=ENTITY_TYPE,
214
227
  project=project,
@@ -2,8 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  import time
4
4
  import typing
5
+ from typing import Any
5
6
 
6
- from digitalhub.entities._base.api_utils import (
7
+ import requests
8
+
9
+ from digitalhub.entities._base.crud import (
7
10
  list_entity_api_base,
8
11
  list_entity_api_ctx,
9
12
  logs_api,
@@ -11,24 +14,22 @@ from digitalhub.entities._base.api_utils import (
11
14
  resume_api,
12
15
  stop_api,
13
16
  )
14
- from digitalhub.entities._base.unversioned.entity import UnversionedEntity
15
- from digitalhub.entities.utils.entity_types import EntityTypes
16
- from digitalhub.entities.utils.state import State
17
- from digitalhub.factory.api import (
18
- build_runtime,
19
- build_spec,
20
- build_status,
21
- get_entity_type_from_kind,
22
- get_executable_kind,
23
- )
17
+ from digitalhub.entities._base.entity.unversioned import UnversionedEntity
18
+ from digitalhub.entities._base.state import State
19
+ from digitalhub.entities._builders.spec import build_spec
20
+ from digitalhub.entities._builders.status import build_status
21
+ from digitalhub.entities.entity_types import EntityTypes
22
+ from digitalhub.registry.registry import registry
23
+ from digitalhub.runtimes.builder import build_runtime
24
24
  from digitalhub.utils.exceptions import EntityError
25
25
  from digitalhub.utils.logger import LOGGER
26
26
 
27
27
  if typing.TYPE_CHECKING:
28
- from digitalhub.entities._base.entity.metadata import Metadata
29
- from digitalhub.entities.run._base.spec import RunSpec
30
- from digitalhub.entities.run._base.status import RunStatus
31
- from digitalhub.runtimes._base import Runtime
28
+ from digitalhub.entities._base.entity.material import MaterialEntity
29
+ from digitalhub.entities._base.metadata import Metadata
30
+ from digitalhub.entities.run.spec import RunSpec
31
+ from digitalhub.entities.run.status import RunStatus
32
+ from digitalhub.runtimes.base import Runtime
32
33
 
33
34
 
34
35
  class Run(UnversionedEntity):
@@ -65,9 +66,10 @@ class Run(UnversionedEntity):
65
66
  -------
66
67
  None
67
68
  """
68
- executable = self._get_executable()
69
- task = self._get_task()
70
- new_spec = self._get_runtime().build(executable, task, self.to_dict())
69
+ runtime = self._get_runtime()
70
+ executable = self._get_executable(runtime)
71
+ task = self._get_task(runtime)
72
+ new_spec = runtime.build(executable, task, self.to_dict())
71
73
  self.spec = build_spec(
72
74
  self.kind,
73
75
  **new_spec,
@@ -91,7 +93,11 @@ class Run(UnversionedEntity):
91
93
  self._set_state(State.RUNNING.value)
92
94
  self.save(update=True)
93
95
 
94
- self._setup_execution()
96
+ # Try to get inputs if they exist
97
+ try:
98
+ self.spec.inputs = self.inputs(as_dict=True)
99
+ except EntityError:
100
+ pass
95
101
 
96
102
  try:
97
103
  status = self._get_runtime().run(self.to_dict())
@@ -141,6 +147,116 @@ class Run(UnversionedEntity):
141
147
  LOGGER.info(f"Run {self.id} finished in {current:.2f} seconds.")
142
148
  return self
143
149
 
150
+ def inputs(self, as_dict: bool = False) -> list[dict]:
151
+ """
152
+ Get inputs passed in spec as objects or as dictionaries.
153
+
154
+ Parameters
155
+ ----------
156
+ as_dict : bool
157
+ If True, return inputs as dictionaries.
158
+
159
+ Returns
160
+ -------
161
+ list[dict]
162
+ List of input objects.
163
+ """
164
+ try:
165
+ return self.spec.get_inputs(as_dict=as_dict)
166
+ except AttributeError:
167
+ msg = f"Run of type {self.kind} has no inputs."
168
+ raise EntityError(msg)
169
+
170
+ def results(self) -> dict:
171
+ """
172
+ Get results from runtime execution.
173
+
174
+ Returns
175
+ -------
176
+ dict
177
+ Results.
178
+ """
179
+ try:
180
+ return self.status.get_results()
181
+ except AttributeError:
182
+ msg = f"Run of type {self.kind} has no results."
183
+ raise EntityError(msg)
184
+
185
+ def result(self, key: str) -> Any:
186
+ """
187
+ Get result from runtime execution by key.
188
+
189
+ Parameters
190
+ ----------
191
+ key : str
192
+ Key of the result.
193
+
194
+ Returns
195
+ -------
196
+ Any
197
+ Result.
198
+ """
199
+ return self.results().get(key)
200
+
201
+ def outputs(self, as_key: bool = False, as_dict: bool = False) -> dict:
202
+ """
203
+ Get run objects results.
204
+
205
+ Parameters
206
+ ----------
207
+ as_key : bool
208
+ If True, return results as keys.
209
+ as_dict : bool
210
+ If True, return results as dictionaries.
211
+
212
+ Returns
213
+ -------
214
+ dict
215
+ List of output objects.
216
+ """
217
+ try:
218
+ return self.status.get_outputs(as_key=as_key, as_dict=as_dict)
219
+ except AttributeError:
220
+ msg = f"Run of type {self.kind} has no outputs."
221
+ raise EntityError(msg)
222
+
223
+ def output(self, key: str, as_key: bool = False, as_dict: bool = False) -> MaterialEntity | dict | str | None:
224
+ """
225
+ Get run object result by key.
226
+
227
+ Parameters
228
+ ----------
229
+ key : str
230
+ Key of the result.
231
+ as_key : bool
232
+ If True, return result as key.
233
+ as_dict : bool
234
+ If True, return result as dictionary.
235
+
236
+ Returns
237
+ -------
238
+ Entity | dict | str | None
239
+ Result.
240
+ """
241
+ return self.outputs(as_key=as_key, as_dict=as_dict).get(key)
242
+
243
+ def values(self) -> dict:
244
+ """
245
+ Get values from runtime execution.
246
+
247
+ Returns
248
+ -------
249
+ dict
250
+ Values from backend.
251
+ """
252
+ try:
253
+ value_list = getattr(self.spec, "values", [])
254
+ value_list = value_list if value_list is not None else []
255
+ return self.status.get_values(value_list)
256
+ except AttributeError:
257
+ msg = f"Run of type {self.kind} has no values."
258
+ raise EntityError(msg)
259
+
144
260
  def logs(self) -> dict:
145
261
  """
146
262
  Get object from backend.
@@ -165,6 +281,11 @@ class Run(UnversionedEntity):
165
281
  """
166
282
  if not self._context().local and not self.spec.local_execution:
167
283
  return stop_api(self.project, self.ENTITY_TYPE, self.id)
284
+ try:
285
+ self.status.stop()
286
+ except AttributeError:
287
+ raise EntityError("Stop is not supported in local execution.")
288
+ return
168
289
 
169
290
  def resume(self) -> None:
170
291
  """
@@ -176,20 +297,45 @@ class Run(UnversionedEntity):
176
297
  """
177
298
  if not self._context().local and not self.spec.local_execution:
178
299
  return resume_api(self.project, self.ENTITY_TYPE, self.id)
179
- self.run()
180
300
 
181
- ##############################
182
- # Helpers
183
- ##############################
301
+ try:
302
+ self.status.resume()
303
+ except AttributeError:
304
+ raise EntityError("Resume is not supported in local execution.")
305
+ return
306
+ # re-run
307
+ # TODO verify the logic and order
308
+ self.run()
184
309
 
185
- def _setup_execution(self) -> None:
310
+ def invoke(self, **kwargs) -> requests.Response:
186
311
  """
187
- Setup run execution. In base class, nothing to do.
312
+ Invoke run.
313
+
314
+ Parameters
315
+ ----------
316
+ kwargs
317
+ Keyword arguments to pass to the request.
188
318
 
189
319
  Returns
190
320
  -------
191
- None
321
+ requests.Response
322
+ Response from service.
192
323
  """
324
+ try:
325
+ if not self._context().local and not self.spec.local_execution:
326
+ local = False
327
+ else:
328
+ local = True
329
+ if kwargs is None:
330
+ kwargs = {}
331
+ return self.status.invoke(local, **kwargs)
332
+ except AttributeError:
333
+ msg = f"Run of type {self.kind} has no invoke operation."
334
+ raise EntityError(msg)
335
+
336
+ ##############################
337
+ # Helpers
338
+ ##############################
193
339
 
194
340
  def _is_ready_to_run(self) -> bool:
195
341
  """
@@ -258,18 +404,22 @@ class Run(UnversionedEntity):
258
404
  """
259
405
  return build_runtime(self.kind, self.project)
260
406
 
261
- def _get_executable(self) -> dict:
407
+ def _get_executable(self, runtime: Runtime) -> dict:
262
408
  """
263
- Get executable object from backend. Reimplemented to avoid
264
- circular imports.
409
+ Get object from backend. Reimplemented to avoid circular imports.
410
+
411
+ Parameters
412
+ ----------
413
+ runtime : Runtime
414
+ Runtime object.
265
415
 
266
416
  Returns
267
417
  -------
268
418
  dict
269
419
  Executable (function or workflow) from backend.
270
420
  """
271
- exec_kind = get_executable_kind(self.kind)
272
- entity_type = get_entity_type_from_kind(exec_kind)
421
+ exec_kind = runtime.get_executable_kind()
422
+ entity_type = registry.get_entity_type(exec_kind)
273
423
  splitted = self.spec.task.split("/")
274
424
  exec_name = splitted[-1].split(":")[0]
275
425
  exec_id = splitted[-1].split(":")[1]
@@ -280,17 +430,21 @@ class Run(UnversionedEntity):
280
430
  entity_id=exec_id,
281
431
  )
282
432
 
283
- def _get_task(self) -> dict:
433
+ def _get_task(self, runtime: Runtime) -> dict:
284
434
  """
285
- Get object from backend. Reimplemented to avoid
286
- circular imports.
435
+ Get object from backend. Reimplemented to avoid circular imports.
436
+
437
+ Parameters
438
+ ----------
439
+ runtime : Runtime
440
+ Runtime object.
287
441
 
288
442
  Returns
289
443
  -------
290
444
  dict
291
445
  Task from backend.
292
446
  """
293
- executable_kind = get_executable_kind(self.kind)
447
+ executable_kind = runtime.get_executable_kind()
294
448
  exec_string = f"{executable_kind}://{self.spec.task.split('://')[1]}"
295
449
 
296
450
  # Local backend
@@ -0,0 +1,153 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+
5
+ from digitalhub.entities._base.spec.base import Spec, SpecParams
6
+ from digitalhub.entities.artifact.crud import get_artifact
7
+ from digitalhub.entities.dataitem.crud import get_dataitem
8
+ from digitalhub.entities.entity_types import EntityTypes
9
+ from digitalhub.entities.model.crud import get_model
10
+ from digitalhub.entities.task.models import K8s
11
+ from digitalhub.entities.utils import parse_entity_key
12
+
13
+ if typing.TYPE_CHECKING:
14
+ from digitalhub.entities._base.entity.base import Entity
15
+
16
+
17
+ ENTITY_FUNC = {
18
+ EntityTypes.ARTIFACT.value: get_artifact,
19
+ EntityTypes.DATAITEM.value: get_dataitem,
20
+ EntityTypes.MODEL.value: get_model,
21
+ }
22
+
23
+
24
+ class RunSpec(Spec):
25
+ """Run specification."""
26
+
27
+ def __init__(
28
+ self,
29
+ task: str,
30
+ local_execution: bool = False,
31
+ function: str | None = None,
32
+ node_selector: dict | None = None,
33
+ volumes: list | None = None,
34
+ resources: dict | None = None,
35
+ affinity: dict | None = None,
36
+ tolerations: list | None = None,
37
+ envs: list | None = None,
38
+ secrets: list | None = None,
39
+ profile: str | None = None,
40
+ **kwargs,
41
+ ) -> None:
42
+ self.task = task
43
+ self.local_execution = local_execution
44
+ self.function = function
45
+ self.node_selector = node_selector
46
+ self.volumes = volumes
47
+ self.resources = resources
48
+ self.affinity = affinity
49
+ self.tolerations = tolerations
50
+ self.envs = envs
51
+ self.secrets = secrets
52
+ self.profile = profile
53
+
54
+ def get_inputs(self, as_dict: bool = False) -> dict:
55
+ """
56
+ Get inputs.
57
+
58
+ Returns
59
+ -------
60
+ dict
61
+ The inputs.
62
+ """
63
+ inputs = {}
64
+ if not hasattr(self, "inputs") or self.inputs is None:
65
+ return inputs
66
+
67
+ for parameter, item in self.inputs.items():
68
+ parameter_type = self._parse_parameter(parameter)
69
+
70
+ # Get entity from key
71
+ if parameter_type == "key":
72
+ key = self._collect_key(item)
73
+ entity = self._collect_entity(key)
74
+ if as_dict:
75
+ entity = entity.to_dict()
76
+ inputs[parameter] = entity
77
+
78
+ # Create entity from parameter
79
+ elif parameter_type == "create":
80
+ raise NotImplementedError
81
+
82
+ return inputs
83
+
84
+ @staticmethod
85
+ def _parse_parameter(parameter: str) -> str:
86
+ """
87
+ Parse parameter.
88
+
89
+ Parameters
90
+ ----------
91
+ parameter : str
92
+ Parameter.
93
+
94
+ Returns
95
+ -------
96
+ str
97
+ The parsed parameter.
98
+ """
99
+ if len(parameter.split(":")) == 1:
100
+ return "key"
101
+ return "create"
102
+
103
+ @staticmethod
104
+ def _collect_key(item: str | dict) -> str:
105
+ """
106
+ Collect key from item.
107
+
108
+ Parameters
109
+ ----------
110
+ item : str | dict
111
+ Key or dict representation of the entity.
112
+
113
+ Returns
114
+ -------
115
+ str
116
+ The key.
117
+ """
118
+ if isinstance(item, str):
119
+ return item
120
+ return item.get("key")
121
+
122
+ @staticmethod
123
+ def _collect_entity(key: str) -> Entity:
124
+ """
125
+ Collect entity from key.
126
+
127
+ Parameters
128
+ ----------
129
+ key : str
130
+ Key of the entity.
131
+
132
+ Returns
133
+ -------
134
+ Entity
135
+ The entity.
136
+ """
137
+ _, entity_type, _, _, _ = parse_entity_key(key)
138
+ return ENTITY_FUNC[entity_type](key)
139
+
140
+
141
+ class RunParams(SpecParams, K8s):
142
+ """
143
+ Run parameters.
144
+ """
145
+
146
+ function: str = None
147
+ """The function associated with the run."""
148
+
149
+ task: str = None
150
+ """The task string associated with the run."""
151
+
152
+ local_execution: bool = False
153
+ """Flag to indicate if the run will be executed locally."""