digitalhub 0.13.0b3__py3-none-any.whl → 0.14.9__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 (139) hide show
  1. digitalhub/__init__.py +3 -8
  2. digitalhub/context/api.py +43 -6
  3. digitalhub/context/builder.py +1 -5
  4. digitalhub/context/context.py +28 -13
  5. digitalhub/entities/_base/_base/entity.py +0 -15
  6. digitalhub/entities/_base/context/entity.py +1 -4
  7. digitalhub/entities/_base/entity/builder.py +5 -5
  8. digitalhub/entities/_base/entity/entity.py +0 -8
  9. digitalhub/entities/_base/executable/entity.py +195 -87
  10. digitalhub/entities/_base/material/entity.py +11 -23
  11. digitalhub/entities/_base/material/utils.py +28 -4
  12. digitalhub/entities/_base/runtime_entity/builder.py +53 -18
  13. digitalhub/entities/_base/unversioned/entity.py +1 -1
  14. digitalhub/entities/_base/versioned/entity.py +1 -1
  15. digitalhub/entities/_commons/enums.py +1 -31
  16. digitalhub/entities/_commons/metrics.py +64 -30
  17. digitalhub/entities/_commons/utils.py +119 -30
  18. digitalhub/entities/_constructors/_resources.py +151 -0
  19. digitalhub/entities/{_base/entity/_constructors → _constructors}/name.py +18 -0
  20. digitalhub/entities/_processors/base/crud.py +381 -0
  21. digitalhub/entities/_processors/base/import_export.py +118 -0
  22. digitalhub/entities/_processors/base/processor.py +299 -0
  23. digitalhub/entities/_processors/base/special_ops.py +104 -0
  24. digitalhub/entities/_processors/context/crud.py +652 -0
  25. digitalhub/entities/_processors/context/import_export.py +242 -0
  26. digitalhub/entities/_processors/context/material.py +123 -0
  27. digitalhub/entities/_processors/context/processor.py +400 -0
  28. digitalhub/entities/_processors/context/special_ops.py +476 -0
  29. digitalhub/entities/_processors/processors.py +12 -0
  30. digitalhub/entities/_processors/utils.py +38 -102
  31. digitalhub/entities/artifact/crud.py +58 -22
  32. digitalhub/entities/artifact/utils.py +28 -13
  33. digitalhub/entities/builders.py +2 -0
  34. digitalhub/entities/dataitem/crud.py +63 -20
  35. digitalhub/entities/dataitem/table/entity.py +27 -22
  36. digitalhub/entities/dataitem/utils.py +82 -32
  37. digitalhub/entities/function/_base/entity.py +3 -6
  38. digitalhub/entities/function/crud.py +55 -24
  39. digitalhub/entities/model/_base/entity.py +62 -20
  40. digitalhub/entities/model/crud.py +59 -23
  41. digitalhub/entities/model/mlflow/utils.py +29 -20
  42. digitalhub/entities/model/utils.py +28 -13
  43. digitalhub/entities/project/_base/builder.py +0 -6
  44. digitalhub/entities/project/_base/entity.py +337 -164
  45. digitalhub/entities/project/_base/spec.py +4 -4
  46. digitalhub/entities/project/crud.py +28 -71
  47. digitalhub/entities/project/utils.py +7 -3
  48. digitalhub/entities/run/_base/builder.py +0 -4
  49. digitalhub/entities/run/_base/entity.py +70 -63
  50. digitalhub/entities/run/crud.py +79 -26
  51. digitalhub/entities/secret/_base/entity.py +1 -5
  52. digitalhub/entities/secret/crud.py +31 -28
  53. digitalhub/entities/task/_base/builder.py +0 -4
  54. digitalhub/entities/task/_base/entity.py +5 -5
  55. digitalhub/entities/task/_base/models.py +13 -16
  56. digitalhub/entities/task/crud.py +61 -29
  57. digitalhub/entities/trigger/_base/entity.py +1 -5
  58. digitalhub/entities/trigger/crud.py +89 -30
  59. digitalhub/entities/workflow/_base/entity.py +3 -8
  60. digitalhub/entities/workflow/crud.py +55 -24
  61. digitalhub/factory/entity.py +283 -0
  62. digitalhub/factory/enums.py +18 -0
  63. digitalhub/factory/registry.py +197 -0
  64. digitalhub/factory/runtime.py +44 -0
  65. digitalhub/factory/utils.py +3 -54
  66. digitalhub/runtimes/_base.py +2 -2
  67. digitalhub/stores/client/{dhcore/api_builder.py → api_builder.py} +3 -3
  68. digitalhub/stores/client/builder.py +19 -31
  69. digitalhub/stores/client/client.py +322 -0
  70. digitalhub/stores/client/configurator.py +408 -0
  71. digitalhub/stores/client/enums.py +50 -0
  72. digitalhub/stores/client/{dhcore/error_parser.py → error_parser.py} +0 -4
  73. digitalhub/stores/client/header_manager.py +61 -0
  74. digitalhub/stores/client/http_handler.py +152 -0
  75. digitalhub/stores/client/{_base/key_builder.py → key_builder.py} +14 -14
  76. digitalhub/stores/client/params_builder.py +330 -0
  77. digitalhub/stores/client/response_processor.py +102 -0
  78. digitalhub/stores/client/utils.py +35 -0
  79. digitalhub/stores/{credentials → configurator}/api.py +5 -9
  80. digitalhub/stores/configurator/configurator.py +123 -0
  81. digitalhub/stores/{credentials → configurator}/enums.py +27 -10
  82. digitalhub/stores/configurator/handler.py +213 -0
  83. digitalhub/stores/{credentials → configurator}/ini_module.py +31 -22
  84. digitalhub/stores/data/_base/store.py +0 -20
  85. digitalhub/stores/data/api.py +5 -7
  86. digitalhub/stores/data/builder.py +53 -27
  87. digitalhub/stores/data/local/store.py +0 -103
  88. digitalhub/stores/data/remote/store.py +0 -4
  89. digitalhub/stores/data/s3/configurator.py +39 -77
  90. digitalhub/stores/data/s3/store.py +57 -37
  91. digitalhub/stores/data/sql/configurator.py +66 -46
  92. digitalhub/stores/data/sql/store.py +171 -104
  93. digitalhub/stores/readers/data/factory.py +0 -8
  94. digitalhub/stores/readers/data/pandas/reader.py +9 -19
  95. digitalhub/utils/file_utils.py +0 -17
  96. digitalhub/utils/generic_utils.py +1 -14
  97. digitalhub/utils/git_utils.py +0 -8
  98. digitalhub/utils/io_utils.py +0 -12
  99. digitalhub/utils/store_utils.py +44 -0
  100. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/METADATA +5 -4
  101. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/RECORD +112 -113
  102. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/WHEEL +1 -1
  103. digitalhub/entities/_commons/types.py +0 -9
  104. digitalhub/entities/_processors/base.py +0 -531
  105. digitalhub/entities/_processors/context.py +0 -1299
  106. digitalhub/entities/task/_base/utils.py +0 -22
  107. digitalhub/factory/factory.py +0 -381
  108. digitalhub/stores/client/_base/api_builder.py +0 -34
  109. digitalhub/stores/client/_base/client.py +0 -243
  110. digitalhub/stores/client/_base/params_builder.py +0 -34
  111. digitalhub/stores/client/api.py +0 -36
  112. digitalhub/stores/client/dhcore/client.py +0 -613
  113. digitalhub/stores/client/dhcore/configurator.py +0 -675
  114. digitalhub/stores/client/dhcore/enums.py +0 -34
  115. digitalhub/stores/client/dhcore/key_builder.py +0 -62
  116. digitalhub/stores/client/dhcore/models.py +0 -40
  117. digitalhub/stores/client/dhcore/params_builder.py +0 -278
  118. digitalhub/stores/client/dhcore/utils.py +0 -94
  119. digitalhub/stores/client/local/api_builder.py +0 -116
  120. digitalhub/stores/client/local/client.py +0 -573
  121. digitalhub/stores/client/local/enums.py +0 -15
  122. digitalhub/stores/client/local/key_builder.py +0 -62
  123. digitalhub/stores/client/local/params_builder.py +0 -120
  124. digitalhub/stores/credentials/__init__.py +0 -3
  125. digitalhub/stores/credentials/configurator.py +0 -210
  126. digitalhub/stores/credentials/handler.py +0 -176
  127. digitalhub/stores/credentials/store.py +0 -81
  128. digitalhub/stores/data/enums.py +0 -15
  129. digitalhub/stores/data/s3/utils.py +0 -78
  130. /digitalhub/entities/{_base/entity/_constructors → _constructors}/__init__.py +0 -0
  131. /digitalhub/entities/{_base/entity/_constructors → _constructors}/metadata.py +0 -0
  132. /digitalhub/entities/{_base/entity/_constructors → _constructors}/spec.py +0 -0
  133. /digitalhub/entities/{_base/entity/_constructors → _constructors}/status.py +0 -0
  134. /digitalhub/entities/{_base/entity/_constructors → _constructors}/uuid.py +0 -0
  135. /digitalhub/{stores/client/_base → entities/_processors/base}/__init__.py +0 -0
  136. /digitalhub/{stores/client/dhcore → entities/_processors/context}/__init__.py +0 -0
  137. /digitalhub/stores/{client/local → configurator}/__init__.py +0 -0
  138. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/licenses/AUTHORS +0 -0
  139. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,242 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ import typing
8
+
9
+ from digitalhub.entities._constructors.uuid import build_uuid
10
+ from digitalhub.entities._processors.utils import get_context, get_context_from_identifier
11
+ from digitalhub.factory.entity import entity_factory
12
+ from digitalhub.utils.exceptions import EntityAlreadyExistsError, EntityError, EntityNotExistsError
13
+ from digitalhub.utils.io_utils import read_yaml
14
+
15
+ if typing.TYPE_CHECKING:
16
+ from digitalhub.entities._base.context.entity import ContextEntity
17
+ from digitalhub.entities._base.executable.entity import ExecutableEntity
18
+ from digitalhub.entities._processors.context.crud import ContextEntityCRUDProcessor
19
+
20
+
21
+ class ContextEntityImportExportProcessor:
22
+ """
23
+ Processor for import and export operations on context entities.
24
+
25
+ Handles loading entities from YAML files and importing/exporting
26
+ entity configurations between local files and the backend.
27
+ """
28
+
29
+ def import_context_entity(
30
+ self,
31
+ crud_processor: ContextEntityCRUDProcessor,
32
+ file: str | None = None,
33
+ key: str | None = None,
34
+ reset_id: bool = False,
35
+ context: str | None = None,
36
+ ) -> ContextEntity:
37
+ """
38
+ Import a context entity from a YAML file or from a storage key.
39
+
40
+ Parameters
41
+ ----------
42
+ crud_processor : ContextEntityCRUDProcessor
43
+ The CRUD processor instance for entity operations.
44
+ file : str
45
+ Path to the YAML file containing entity configuration.
46
+ key : str
47
+ Storage key (store://...) to read the entity from.
48
+ reset_id : bool
49
+ Flag to determine if the ID of context entities should be reset.
50
+ context : str
51
+ Project name to use for context resolution. If None, uses
52
+ the project specified in the YAML file.
53
+
54
+ Returns
55
+ -------
56
+ ContextEntity
57
+ The imported and created context entity.
58
+
59
+ Raises
60
+ ------
61
+ EntityError
62
+ If the entity already exists in the backend.
63
+ """
64
+ if (file is None) == (key is None):
65
+ raise ValueError("Provide key or file, not both or none.")
66
+
67
+ if file is not None:
68
+ dict_obj: dict = read_yaml(file)
69
+ else:
70
+ ctx = get_context_from_identifier(key)
71
+ dict_obj: dict = crud_processor._read_context_entity(ctx, key)
72
+
73
+ dict_obj["status"] = {}
74
+
75
+ if context is None:
76
+ context = dict_obj["project"]
77
+
78
+ ctx = get_context(context)
79
+ obj = entity_factory.build_entity_from_dict(dict_obj)
80
+ if reset_id:
81
+ new_id = build_uuid()
82
+ obj.id = new_id
83
+ obj.metadata.version = new_id
84
+ try:
85
+ bck_obj = crud_processor._create_context_entity(ctx, obj.ENTITY_TYPE, obj.to_dict())
86
+ new_obj: ContextEntity = entity_factory.build_entity_from_dict(bck_obj)
87
+ except EntityAlreadyExistsError:
88
+ raise EntityError(f"Entity {obj.name} already exists. If you want to update it, use load instead.")
89
+ return new_obj
90
+
91
+ def import_executable_entity(
92
+ self,
93
+ crud_processor: ContextEntityCRUDProcessor,
94
+ file: str | None = None,
95
+ key: str | None = None,
96
+ reset_id: bool = False,
97
+ context: str | None = None,
98
+ ) -> ExecutableEntity:
99
+ """
100
+ Import an executable entity from a YAML file or from a storage key.
101
+
102
+ Parameters
103
+ ----------
104
+ crud_processor : ContextEntityCRUDProcessor
105
+ The CRUD processor instance for entity operations.
106
+ file : str
107
+ Path to the YAML file containing executable entity configuration.
108
+ Can contain a single entity or a list with the executable and tasks.
109
+ key : str
110
+ Storage key (store://...) to read the entity from.
111
+ reset_id : bool
112
+ Flag to determine if the ID of executable entities should be reset.
113
+ context : str
114
+ Project name to use for context resolution.
115
+
116
+ Returns
117
+ -------
118
+ ExecutableEntity
119
+ The imported and created executable entity.
120
+
121
+ Raises
122
+ ------
123
+ EntityError
124
+ If the entity already exists in the backend.
125
+ """
126
+ if (file is None) == (key is None):
127
+ raise ValueError("Provide key or file, not both or none.")
128
+
129
+ if file is not None:
130
+ dict_obj: dict | list[dict] = read_yaml(file)
131
+ else:
132
+ ctx = get_context_from_identifier(key)
133
+ dict_obj: dict = crud_processor._read_context_entity(ctx, key)
134
+
135
+ if isinstance(dict_obj, list):
136
+ exec_dict = dict_obj[0]
137
+ exec_dict["status"] = {}
138
+ tsk_dicts = []
139
+ for i in dict_obj[1:]:
140
+ i["status"] = {}
141
+ tsk_dicts.append(i)
142
+ else:
143
+ exec_dict = dict_obj
144
+ exec_dict["status"] = {}
145
+ tsk_dicts = []
146
+
147
+ if context is None:
148
+ context = exec_dict["project"]
149
+
150
+ ctx = get_context(context)
151
+ obj: ExecutableEntity = entity_factory.build_entity_from_dict(exec_dict)
152
+
153
+ if reset_id:
154
+ new_id = build_uuid()
155
+ obj.id = new_id
156
+ obj.metadata.version = new_id
157
+
158
+ try:
159
+ bck_obj = crud_processor._create_context_entity(ctx, obj.ENTITY_TYPE, obj.to_dict())
160
+ new_obj: ExecutableEntity = entity_factory.build_entity_from_dict(bck_obj)
161
+ except EntityAlreadyExistsError:
162
+ raise EntityError(f"Entity {obj.name} already exists. If you want to update it, use load instead.")
163
+
164
+ new_obj.import_tasks(tsk_dicts)
165
+
166
+ return new_obj
167
+
168
+ def load_context_entity(
169
+ self,
170
+ crud_processor: ContextEntityCRUDProcessor,
171
+ file: str,
172
+ ) -> ContextEntity:
173
+ """
174
+ Load a context entity from a YAML file and update it in the backend.
175
+
176
+ Reads entity configuration from a YAML file and updates an existing
177
+ entity in the backend. If the entity doesn't exist, it creates a
178
+ new one.
179
+
180
+ Parameters
181
+ ----------
182
+ crud_processor : ContextEntityCRUDProcessor
183
+ The CRUD processor instance for entity operations.
184
+ file : str
185
+ Path to the YAML file containing entity configuration.
186
+
187
+ Returns
188
+ -------
189
+ ContextEntity
190
+ The loaded and updated context entity.
191
+ """
192
+ dict_obj: dict = read_yaml(file)
193
+ context = get_context(dict_obj["project"])
194
+ obj: ContextEntity = entity_factory.build_entity_from_dict(dict_obj)
195
+ try:
196
+ crud_processor._update_context_entity(context, obj.ENTITY_TYPE, obj.id, obj.to_dict())
197
+ except EntityNotExistsError:
198
+ crud_processor._create_context_entity(context, obj.ENTITY_TYPE, obj.to_dict())
199
+ return obj
200
+
201
+ def load_executable_entity(
202
+ self,
203
+ crud_processor: ContextEntityCRUDProcessor,
204
+ file: str,
205
+ ) -> ExecutableEntity:
206
+ """
207
+ Load an executable entity from a YAML file and update it in the backend.
208
+
209
+ Reads executable entity configuration from a YAML file and updates
210
+ an existing executable entity in the backend. If the entity doesn't
211
+ exist, it creates a new one. Also handles task imports.
212
+
213
+ Parameters
214
+ ----------
215
+ crud_processor : ContextEntityCRUDProcessor
216
+ The CRUD processor instance for entity operations.
217
+ file : str
218
+ Path to the YAML file containing executable entity configuration.
219
+ Can contain a single entity or a list with the executable and tasks.
220
+
221
+ Returns
222
+ -------
223
+ ExecutableEntity
224
+ The loaded and updated executable entity.
225
+ """
226
+ dict_obj: dict | list[dict] = read_yaml(file)
227
+ if isinstance(dict_obj, list):
228
+ exec_dict = dict_obj[0]
229
+ tsk_dicts = dict_obj[1:]
230
+ else:
231
+ exec_dict = dict_obj
232
+ tsk_dicts = []
233
+
234
+ context = get_context(exec_dict["project"])
235
+ obj: ExecutableEntity = entity_factory.build_entity_from_dict(exec_dict)
236
+
237
+ try:
238
+ crud_processor._update_context_entity(context, obj.ENTITY_TYPE, obj.id, obj.to_dict())
239
+ except EntityNotExistsError:
240
+ crud_processor._create_context_entity(context, obj.ENTITY_TYPE, obj.to_dict())
241
+ obj.import_tasks(tsk_dicts)
242
+ return obj
@@ -0,0 +1,123 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ import typing
8
+
9
+ from digitalhub.entities._commons.enums import Relationship, State
10
+ from digitalhub.entities._processors.utils import get_context
11
+ from digitalhub.factory.entity import entity_factory
12
+ from digitalhub.utils.exceptions import EntityError
13
+ from digitalhub.utils.types import SourcesOrListOfSources
14
+
15
+ if typing.TYPE_CHECKING:
16
+ from digitalhub.entities._base.material.entity import MaterialEntity
17
+ from digitalhub.entities._processors.context.crud import ContextEntityCRUDProcessor
18
+
19
+
20
+ class ContextEntityMaterialProcessor:
21
+ """
22
+ Processor for material entity operations.
23
+
24
+ Handles creation and management of material entities (artifacts,
25
+ dataitems, models) including file upload operations and status
26
+ management during uploads.
27
+ """
28
+
29
+ def log_material_entity(
30
+ self,
31
+ crud_processor: ContextEntityCRUDProcessor,
32
+ **kwargs,
33
+ ) -> MaterialEntity:
34
+ """
35
+ Create a material entity in the backend and upload associated files.
36
+
37
+ Creates a new material entity (artifact, dataitem, or model) and
38
+ handles file upload operations. Manages upload state transitions
39
+ and error handling during the upload process.
40
+
41
+ Parameters
42
+ ----------
43
+ crud_processor : ContextEntityCRUDProcessor
44
+ The CRUD processor instance for entity operations.
45
+ **kwargs : dict
46
+ Parameters for entity creation including:
47
+ - 'source': file source(s) to upload
48
+ - 'project': project name
49
+ - other entity-specific parameters
50
+
51
+ Returns
52
+ -------
53
+ MaterialEntity
54
+ The created material entity with uploaded files.
55
+
56
+ Raises
57
+ ------
58
+ EntityError
59
+ If file upload fails during the process.
60
+ """
61
+ source: SourcesOrListOfSources = kwargs.pop("source")
62
+ context = get_context(kwargs["project"])
63
+ obj = entity_factory.build_entity_from_params(**kwargs)
64
+ if context.is_running:
65
+ obj.add_relationship(Relationship.PRODUCEDBY.value, context.get_run_ctx())
66
+
67
+ new_obj: MaterialEntity = crud_processor._create_context_entity(context, obj.ENTITY_TYPE, obj.to_dict())
68
+ new_obj = entity_factory.build_entity_from_dict(new_obj)
69
+
70
+ new_obj.status.state = State.UPLOADING.value
71
+ new_obj = self._update_material_entity(crud_processor, new_obj)
72
+
73
+ # Handle file upload
74
+ try:
75
+ new_obj.upload(source)
76
+ uploaded = True
77
+ msg = None
78
+ except Exception as e:
79
+ uploaded = False
80
+ msg = str(e.args)
81
+
82
+ new_obj.status.message = msg
83
+
84
+ # Update status after upload
85
+ if uploaded:
86
+ new_obj.status.state = State.READY.value
87
+ new_obj = self._update_material_entity(crud_processor, new_obj)
88
+ else:
89
+ new_obj.status.state = State.ERROR.value
90
+ new_obj = self._update_material_entity(crud_processor, new_obj)
91
+ raise EntityError(msg)
92
+
93
+ return new_obj
94
+
95
+ def _update_material_entity(
96
+ self,
97
+ crud_processor: ContextEntityCRUDProcessor,
98
+ new_obj: MaterialEntity,
99
+ ) -> MaterialEntity:
100
+ """
101
+ Update a material entity using a shortcut method.
102
+
103
+ Convenience method for updating material entities during
104
+ file upload operations.
105
+
106
+ Parameters
107
+ ----------
108
+ crud_processor : ContextEntityCRUDProcessor
109
+ The CRUD processor instance for entity operations.
110
+ new_obj : MaterialEntity
111
+ The material entity object to update.
112
+
113
+ Returns
114
+ -------
115
+ MaterialEntity
116
+ The updated material entity.
117
+ """
118
+ return crud_processor.update_context_entity(
119
+ new_obj.project,
120
+ new_obj.ENTITY_TYPE,
121
+ new_obj.id,
122
+ new_obj.to_dict(),
123
+ )