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,476 @@
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
+ from typing import Any
9
+
10
+ from digitalhub.entities._processors.utils import get_context
11
+ from digitalhub.stores.client.enums import ApiCategories, BackendOperations
12
+
13
+ if typing.TYPE_CHECKING:
14
+ from digitalhub.entities._base.context.entity import ContextEntity
15
+ from digitalhub.entities._processors.context.crud import ContextEntityCRUDProcessor
16
+
17
+
18
+ class ContextEntitySpecialOpsProcessor:
19
+ """
20
+ Processor for specialized context entity operations.
21
+
22
+ Handles backend operations like secrets management, logging,
23
+ entity control (start/stop/resume), file operations, and metrics.
24
+ """
25
+
26
+ def build_context_entity_key(
27
+ self,
28
+ project: str,
29
+ entity_type: str,
30
+ entity_kind: str,
31
+ entity_name: str,
32
+ entity_id: str | None = None,
33
+ ) -> str:
34
+ """
35
+ Build a storage key for a context entity.
36
+
37
+ Creates a standardized key string for context entity identification
38
+ and storage, resolving the project context automatically.
39
+
40
+ Parameters
41
+ ----------
42
+ project : str
43
+ The project name containing the entity.
44
+ entity_type : str
45
+ The type of entity.
46
+ entity_kind : str
47
+ The kind/subtype of entity.
48
+ entity_name : str
49
+ The name of the entity.
50
+ entity_id : str
51
+ The unique identifier of the entity version.
52
+
53
+ Returns
54
+ -------
55
+ str
56
+ The constructed context entity key string.
57
+ """
58
+ context = get_context(project)
59
+ return context.client.build_key(
60
+ ApiCategories.CONTEXT.value,
61
+ project=context.name,
62
+ entity_type=entity_type,
63
+ entity_kind=entity_kind,
64
+ entity_name=entity_name,
65
+ entity_id=entity_id,
66
+ )
67
+
68
+ def read_secret_data(
69
+ self,
70
+ project: str,
71
+ entity_type: str,
72
+ **kwargs,
73
+ ) -> dict:
74
+ """
75
+ Read secret data from the backend.
76
+
77
+ Retrieves secret data stored in the backend for a specific
78
+ project and entity type.
79
+
80
+ Parameters
81
+ ----------
82
+ project : str
83
+ The project name containing the secrets.
84
+ entity_type : str
85
+ The type of entity (typically 'secret').
86
+ **kwargs : dict
87
+ Additional parameters to pass to the API call.
88
+
89
+ Returns
90
+ -------
91
+ dict
92
+ Secret data retrieved from the backend.
93
+ """
94
+ context = get_context(project)
95
+ api = context.client.build_api(
96
+ ApiCategories.CONTEXT.value,
97
+ BackendOperations.DATA.value,
98
+ project=context.name,
99
+ entity_type=entity_type,
100
+ )
101
+ return context.client.read_object(api, **kwargs)
102
+
103
+ def update_secret_data(
104
+ self,
105
+ project: str,
106
+ entity_type: str,
107
+ data: dict,
108
+ **kwargs,
109
+ ) -> None:
110
+ """
111
+ Update secret data in the backend.
112
+
113
+ Stores or updates secret data in the backend for a specific
114
+ project and entity type.
115
+
116
+ Parameters
117
+ ----------
118
+ project : str
119
+ The project name to store secrets in.
120
+ entity_type : str
121
+ The type of entity (typically 'secret').
122
+ data : dict
123
+ The secret data dictionary to store.
124
+ **kwargs : dict
125
+ Additional parameters to pass to the API call.
126
+ """
127
+ context = get_context(project)
128
+ api = context.client.build_api(
129
+ ApiCategories.CONTEXT.value,
130
+ BackendOperations.DATA.value,
131
+ project=context.name,
132
+ entity_type=entity_type,
133
+ )
134
+ context.client.update_object(api, data, **kwargs)
135
+
136
+ def read_run_logs(
137
+ self,
138
+ project: str,
139
+ entity_type: str,
140
+ entity_id: str,
141
+ **kwargs,
142
+ ) -> dict:
143
+ """
144
+ Read execution logs from the backend.
145
+
146
+ Retrieves logs for a specific run or task execution from
147
+ the backend.
148
+
149
+ Parameters
150
+ ----------
151
+ project : str
152
+ The project name containing the entity.
153
+ entity_type : str
154
+ The type of entity (typically 'run' or 'task').
155
+ entity_id : str
156
+ The unique identifier of the entity to get logs for.
157
+ **kwargs : dict
158
+ Additional parameters to pass to the API call.
159
+
160
+ Returns
161
+ -------
162
+ dict
163
+ Log data retrieved from the backend.
164
+ """
165
+ context = get_context(project)
166
+ api = context.client.build_api(
167
+ ApiCategories.CONTEXT.value,
168
+ BackendOperations.LOGS.value,
169
+ project=context.name,
170
+ entity_type=entity_type,
171
+ entity_id=entity_id,
172
+ )
173
+ return context.client.read_object(api, **kwargs)
174
+
175
+ def stop_entity(
176
+ self,
177
+ project: str,
178
+ entity_type: str,
179
+ entity_id: str,
180
+ **kwargs,
181
+ ) -> None:
182
+ """
183
+ Stop a running entity in the backend.
184
+
185
+ Sends a stop signal to halt execution of a running entity
186
+ such as a workflow or long-running task.
187
+
188
+ Parameters
189
+ ----------
190
+ project : str
191
+ The project name containing the entity.
192
+ entity_type : str
193
+ The type of entity to stop.
194
+ entity_id : str
195
+ The unique identifier of the entity to stop.
196
+ **kwargs : dict
197
+ Additional parameters to pass to the API call.
198
+ """
199
+ context = get_context(project)
200
+ api = context.client.build_api(
201
+ ApiCategories.CONTEXT.value,
202
+ BackendOperations.STOP.value,
203
+ project=context.name,
204
+ entity_type=entity_type,
205
+ entity_id=entity_id,
206
+ )
207
+ context.client.create_object(api, obj={}, **kwargs)
208
+
209
+ def resume_entity(
210
+ self,
211
+ project: str,
212
+ entity_type: str,
213
+ entity_id: str,
214
+ **kwargs,
215
+ ) -> None:
216
+ """
217
+ Resume a stopped entity in the backend.
218
+
219
+ Sends a resume signal to restart execution of a previously
220
+ stopped entity such as a workflow or task.
221
+
222
+ Parameters
223
+ ----------
224
+ project : str
225
+ The project name containing the entity.
226
+ entity_type : str
227
+ The type of entity to resume.
228
+ entity_id : str
229
+ The unique identifier of the entity to resume.
230
+ **kwargs : dict
231
+ Additional parameters to pass to the API call.
232
+ """
233
+ context = get_context(project)
234
+ api = context.client.build_api(
235
+ ApiCategories.CONTEXT.value,
236
+ BackendOperations.RESUME.value,
237
+ project=context.name,
238
+ entity_type=entity_type,
239
+ entity_id=entity_id,
240
+ )
241
+ context.client.create_object(api, obj={}, **kwargs)
242
+
243
+ def read_files_info(
244
+ self,
245
+ project: str,
246
+ entity_type: str,
247
+ entity_id: str,
248
+ **kwargs,
249
+ ) -> list[dict]:
250
+ """
251
+ Read file information from the backend.
252
+
253
+ Retrieves metadata about files associated with an entity,
254
+ including file paths, sizes, and other attributes.
255
+
256
+ Parameters
257
+ ----------
258
+ project : str
259
+ The project name containing the entity.
260
+ entity_type : str
261
+ The type of entity to get file info for.
262
+ entity_id : str
263
+ The unique identifier of the entity.
264
+ **kwargs : dict
265
+ Additional parameters to pass to the API call.
266
+
267
+ Returns
268
+ -------
269
+ list[dict]
270
+ List of file information dictionaries from the backend.
271
+ """
272
+ context = get_context(project)
273
+ api = context.client.build_api(
274
+ ApiCategories.CONTEXT.value,
275
+ BackendOperations.FILES.value,
276
+ project=context.name,
277
+ entity_type=entity_type,
278
+ entity_id=entity_id,
279
+ )
280
+ return context.client.read_object(api, **kwargs)
281
+
282
+ def update_files_info(
283
+ self,
284
+ project: str,
285
+ entity_type: str,
286
+ entity_id: str,
287
+ entity_list: list[dict],
288
+ **kwargs,
289
+ ) -> None:
290
+ """
291
+ Get files info from backend.
292
+
293
+ Parameters
294
+ ----------
295
+ project : str
296
+ Project name.
297
+ entity_type : str
298
+ Entity type.
299
+ entity_id : str
300
+ Entity ID.
301
+ entity_list : list[dict]
302
+ Entity list.
303
+ **kwargs : dict
304
+ Parameters to pass to the API call.
305
+ """
306
+ context = get_context(project)
307
+ api = context.client.build_api(
308
+ ApiCategories.CONTEXT.value,
309
+ BackendOperations.FILES.value,
310
+ project=context.name,
311
+ entity_type=entity_type,
312
+ entity_id=entity_id,
313
+ )
314
+ return context.client.update_object(api, entity_list, **kwargs)
315
+
316
+ def read_metrics(
317
+ self,
318
+ project: str,
319
+ entity_type: str,
320
+ entity_id: str,
321
+ metric_name: str | None = None,
322
+ **kwargs,
323
+ ) -> dict:
324
+ """
325
+ Read metrics from the backend for a specific entity.
326
+
327
+ Retrieves metrics data associated with an entity. Can fetch either
328
+ all metrics or a specific metric by name. Used for performance
329
+ monitoring and analysis of entity operations.
330
+
331
+ Parameters
332
+ ----------
333
+ project : str
334
+ The project name containing the entity.
335
+ entity_type : str
336
+ The type of entity to read metrics from.
337
+ entity_id : str
338
+ The unique identifier of the entity.
339
+ metric_name : str
340
+ The name of a specific metric to retrieve.
341
+ If None, retrieves all available metrics.
342
+ **kwargs : dict
343
+ Additional parameters to pass to the API call.
344
+
345
+ Returns
346
+ -------
347
+ dict
348
+ Dictionary containing metric data from the backend.
349
+ """
350
+ context = get_context(project)
351
+ api = context.client.build_api(
352
+ ApiCategories.CONTEXT.value,
353
+ BackendOperations.METRICS.value,
354
+ project=context.name,
355
+ entity_type=entity_type,
356
+ entity_id=entity_id,
357
+ metric_name=metric_name,
358
+ )
359
+ return context.client.read_object(api, **kwargs)
360
+
361
+ def update_metric(
362
+ self,
363
+ project: str,
364
+ entity_type: str,
365
+ entity_id: str,
366
+ metric_name: str,
367
+ metric_value: Any,
368
+ **kwargs,
369
+ ) -> None:
370
+ """
371
+ Update or create a metric value for an entity in the backend.
372
+
373
+ Updates an existing metric or creates a new one with the specified
374
+ value. Metrics are used for tracking performance, status, and
375
+ other quantitative aspects of entity operations.
376
+
377
+ Parameters
378
+ ----------
379
+ project : str
380
+ The project name containing the entity.
381
+ entity_type : str
382
+ The type of entity to update metrics for.
383
+ entity_id : str
384
+ The unique identifier of the entity.
385
+ metric_name : str
386
+ The name of the metric to update or create.
387
+ metric_value : Any
388
+ The value to set for the metric.
389
+ Can be numeric, string, or other supported types.
390
+ **kwargs : dict
391
+ Additional parameters to pass to the API call.
392
+ """
393
+ context = get_context(project)
394
+ api = context.client.build_api(
395
+ ApiCategories.CONTEXT.value,
396
+ BackendOperations.METRICS.value,
397
+ project=context.name,
398
+ entity_type=entity_type,
399
+ entity_id=entity_id,
400
+ metric_name=metric_name,
401
+ )
402
+ context.client.update_object(api, metric_value, **kwargs)
403
+
404
+ def search_entity(
405
+ self,
406
+ crud_processor: ContextEntityCRUDProcessor,
407
+ project: str,
408
+ query: str | None = None,
409
+ entity_types: list[str] | None = None,
410
+ name: str | None = None,
411
+ kind: str | None = None,
412
+ created: str | None = None,
413
+ updated: str | None = None,
414
+ description: str | None = None,
415
+ labels: list[str] | None = None,
416
+ **kwargs,
417
+ ) -> list[ContextEntity]:
418
+ """
419
+ Search for entities in the backend using various criteria.
420
+
421
+ Performs a flexible search across multiple entity attributes,
422
+ allowing for complex queries and filtering. Returns matching
423
+ entities from the project context.
424
+
425
+ Parameters
426
+ ----------
427
+ crud_processor : ContextEntityCRUDProcessor
428
+ The CRUD processor instance for entity operations.
429
+ project : str
430
+ The project name to search within.
431
+ query : str
432
+ Free-text search query to match against entity content.
433
+ entity_types : list[str]
434
+ List of entity types to filter by.
435
+ If None, searches all entity types.
436
+ name : str
437
+ Entity name pattern to match.
438
+ kind : str
439
+ Entity kind to filter by.
440
+ created : str
441
+ Creation date filter (ISO format).
442
+ updated : str
443
+ Last update date filter (ISO format).
444
+ description : str
445
+ Description pattern to match.
446
+ labels : list[str]
447
+ List of label patterns to match.
448
+ **kwargs : dict
449
+ Additional search parameters to pass to the API call.
450
+
451
+ Returns
452
+ -------
453
+ list[ContextEntity]
454
+ List of matching entity instances from the search.
455
+ """
456
+ context = get_context(project)
457
+ kwargs = context.client.build_parameters(
458
+ ApiCategories.CONTEXT.value,
459
+ BackendOperations.SEARCH.value,
460
+ query=query,
461
+ entity_types=entity_types,
462
+ name=name,
463
+ kind=kind,
464
+ created=created,
465
+ updated=updated,
466
+ description=description,
467
+ labels=labels,
468
+ **kwargs,
469
+ )
470
+ api = context.client.build_api(
471
+ ApiCategories.CONTEXT.value,
472
+ BackendOperations.SEARCH.value,
473
+ project=context.name,
474
+ )
475
+ entities_dict = context.client.read_object(api, **kwargs)
476
+ return [crud_processor.read_context_entity(entity["key"]) for entity in entities_dict["content"]]
@@ -0,0 +1,12 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from digitalhub.entities._processors.base.processor import BaseEntityOperationsProcessor
6
+ from digitalhub.entities._processors.context.processor import ContextEntityOperationsProcessor
7
+
8
+ # Base processor singleton instance
9
+ base_processor = BaseEntityOperationsProcessor()
10
+
11
+ # Context processor singleton instance
12
+ context_processor = ContextEntityOperationsProcessor()
@@ -7,15 +7,11 @@ from __future__ import annotations
7
7
  import typing
8
8
 
9
9
  from digitalhub.context.api import get_context
10
- from digitalhub.entities._commons.enums import ApiCategories, BackendOperations, EntityTypes
11
- from digitalhub.entities._commons.utils import get_project_from_key, parse_entity_key
12
- from digitalhub.factory.factory import factory
13
- from digitalhub.stores.client.api import get_client
14
- from digitalhub.utils.exceptions import ContextError, EntityError, EntityNotExistsError
10
+ from digitalhub.entities._commons.utils import get_project_from_key, is_valid_key, parse_entity_key
11
+ from digitalhub.utils.exceptions import EntityError
15
12
 
16
13
  if typing.TYPE_CHECKING:
17
14
  from digitalhub.context.context import Context
18
- from digitalhub.stores.client._base.client import Client
19
15
 
20
16
 
21
17
  def parse_identifier(
@@ -26,25 +22,38 @@ def parse_identifier(
26
22
  entity_id: str | None = None,
27
23
  ) -> tuple[str, str, str | None, str | None, str | None]:
28
24
  """
29
- Parse entity identifier.
25
+ Parse and validate entity identifier into its components.
26
+
27
+ Processes an entity identifier that can be either a full entity key
28
+ (store://) or a simple entity name. When using a simple name,
29
+ additional parameters must be provided for proper identification.
30
30
 
31
31
  Parameters
32
32
  ----------
33
33
  identifier : str
34
- Entity key (store://...) or entity name.
34
+ The entity identifier to parse. Can be either a full entity key
35
+ (store://project/entity_type/kind/name:id) or a simple entity name.
35
36
  project : str
36
- Project name.
37
+ The project name. Required when identifier is not a full key.
37
38
  entity_type : str
38
- Entity type.
39
+ The entity type. Required when identifier is not a full key.
40
+ entity_kind : str
41
+ The entity kind specification.
39
42
  entity_id : str
40
- Entity ID.
43
+ The entity version identifier.
41
44
 
42
45
  Returns
43
46
  -------
44
47
  tuple[str, str, str | None, str | None, str | None]
45
- Project name, entity type, entity kind, entity name, entity ID.
48
+ A tuple containing (project_name, entity_type, entity_kind,
49
+ entity_name, entity_id) parsed from the identifier.
50
+
51
+ Raises
52
+ ------
53
+ ValueError
54
+ If identifier is not a full key and project or entity_type is None.
46
55
  """
47
- if not identifier.startswith("store://"):
56
+ if not is_valid_key(identifier):
48
57
  if project is None or entity_type is None:
49
58
  raise ValueError("Project and entity type must be specified.")
50
59
  return project, entity_type, entity_kind, identifier, entity_id
@@ -56,107 +65,34 @@ def get_context_from_identifier(
56
65
  project: str | None = None,
57
66
  ) -> Context:
58
67
  """
59
- Get context from project.
68
+ Retrieve context instance from entity identifier or project name.
69
+
70
+ Extracts project information from the identifier and returns the
71
+ corresponding context. If the identifier is not a full key, the
72
+ project parameter must be provided explicitly.
60
73
 
61
74
  Parameters
62
75
  ----------
63
76
  identifier : str
64
- Entity key (store://...) or entity name.
77
+ The entity identifier to extract context from. Can be either
78
+ a full entity key (store://...) or a simple entity name.
65
79
  project : str
66
- Project name.
80
+ The project name. Required when identifier is not a full key.
67
81
 
68
82
  Returns
69
83
  -------
70
84
  Context
71
- Context.
85
+ The context instance associated with the identified project.
86
+
87
+ Raises
88
+ ------
89
+ EntityError
90
+ If identifier is not a full key and project parameter is None.
72
91
  """
73
- if not identifier.startswith("store://"):
92
+ if not is_valid_key(identifier):
74
93
  if project is None:
75
94
  raise EntityError("Specify project if you do not specify entity key.")
76
95
  else:
77
96
  project = get_project_from_key(identifier)
78
97
 
79
- return get_context_from_project(project)
80
-
81
-
82
- def get_context_from_project(
83
- project: str,
84
- ) -> Context:
85
- """
86
- Check if the given project is in the context.
87
- Otherwise try to get the project from remote.
88
- Finally return the client.
89
-
90
- Parameters
91
- ----------
92
- project : str
93
- Project name.
94
-
95
- Returns
96
- -------
97
- Context
98
- Context.
99
- """
100
- try:
101
- return get_context(project)
102
- except ContextError:
103
- return get_context_from_remote(project)
104
-
105
-
106
- def get_context_from_remote(
107
- project: str,
108
- ) -> Client:
109
- """
110
- Get context from remote.
111
-
112
- Parameters
113
- ----------
114
- project : str
115
- Project name.
116
-
117
- Returns
118
- -------
119
- Client
120
- Client.
121
- """
122
- try:
123
- client = get_client()
124
- obj = _read_base_entity(client, EntityTypes.PROJECT.value, project)
125
- factory.build_entity_from_dict(obj)
126
- return get_context(project)
127
- except EntityNotExistsError:
128
- raise ContextError(f"Project '{project}' not found.")
129
-
130
-
131
- def _read_base_entity(
132
- client: Client,
133
- entity_type: str,
134
- entity_name: str,
135
- **kwargs,
136
- ) -> dict:
137
- """
138
- Read object from backend.
139
-
140
- Parameters
141
- ----------
142
- client : Client
143
- Client instance.
144
- entity_type : str
145
- Entity type.
146
- entity_name : str
147
- Entity name.
148
- **kwargs : dict
149
- Parameters to pass to the API call.
150
-
151
- Returns
152
- -------
153
- dict
154
- Object instance.
155
- """
156
- api = client.build_api(
157
- ApiCategories.BASE.value,
158
- BackendOperations.READ.value,
159
- entity_type=entity_type,
160
- entity_name=entity_name,
161
- )
162
- return client.read_object(api, **kwargs)
98
+ return get_context(project)