digitalhub 0.14.0b2__py3-none-any.whl → 0.14.0b3__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 (63) hide show
  1. digitalhub/context/builder.py +0 -4
  2. digitalhub/context/context.py +12 -8
  3. digitalhub/entities/_base/_base/entity.py +0 -4
  4. digitalhub/entities/_base/context/entity.py +1 -1
  5. digitalhub/entities/_base/entity/entity.py +0 -8
  6. digitalhub/entities/_base/executable/entity.py +5 -25
  7. digitalhub/entities/_base/material/entity.py +3 -23
  8. digitalhub/entities/_base/unversioned/entity.py +1 -1
  9. digitalhub/entities/_base/versioned/entity.py +1 -1
  10. digitalhub/entities/_processors/base/__init__.py +3 -0
  11. digitalhub/entities/_processors/{base.py → base/crud.py} +6 -226
  12. digitalhub/entities/_processors/base/import_export.py +122 -0
  13. digitalhub/entities/_processors/base/processor.py +302 -0
  14. digitalhub/entities/_processors/base/special_ops.py +108 -0
  15. digitalhub/entities/_processors/context/__init__.py +3 -0
  16. digitalhub/entities/_processors/context/crud.py +654 -0
  17. digitalhub/entities/_processors/context/import_export.py +242 -0
  18. digitalhub/entities/_processors/context/material.py +123 -0
  19. digitalhub/entities/_processors/context/processor.py +400 -0
  20. digitalhub/entities/_processors/context/special_ops.py +476 -0
  21. digitalhub/entities/_processors/processors.py +12 -0
  22. digitalhub/entities/artifact/crud.py +8 -24
  23. digitalhub/entities/dataitem/crud.py +8 -24
  24. digitalhub/entities/dataitem/table/entity.py +2 -6
  25. digitalhub/entities/function/crud.py +8 -24
  26. digitalhub/entities/model/_base/entity.py +3 -23
  27. digitalhub/entities/model/crud.py +8 -22
  28. digitalhub/entities/project/_base/entity.py +40 -129
  29. digitalhub/entities/project/crud.py +7 -22
  30. digitalhub/entities/run/_base/builder.py +0 -4
  31. digitalhub/entities/run/_base/entity.py +3 -59
  32. digitalhub/entities/run/crud.py +7 -19
  33. digitalhub/entities/secret/_base/entity.py +1 -5
  34. digitalhub/entities/secret/crud.py +8 -22
  35. digitalhub/entities/task/_base/builder.py +0 -4
  36. digitalhub/entities/task/_base/entity.py +1 -1
  37. digitalhub/entities/task/crud.py +7 -19
  38. digitalhub/entities/trigger/_base/entity.py +1 -5
  39. digitalhub/entities/trigger/crud.py +8 -24
  40. digitalhub/entities/workflow/crud.py +8 -24
  41. digitalhub/factory/registry.py +0 -24
  42. digitalhub/stores/client/dhcore/client.py +0 -18
  43. digitalhub/stores/client/dhcore/configurator.py +5 -28
  44. digitalhub/stores/client/dhcore/error_parser.py +0 -4
  45. digitalhub/stores/credentials/configurator.py +0 -24
  46. digitalhub/stores/credentials/handler.py +0 -12
  47. digitalhub/stores/credentials/store.py +0 -4
  48. digitalhub/stores/data/_base/store.py +0 -16
  49. digitalhub/stores/data/builder.py +0 -4
  50. digitalhub/stores/data/remote/store.py +0 -4
  51. digitalhub/stores/data/s3/configurator.py +0 -8
  52. digitalhub/stores/data/s3/store.py +0 -12
  53. digitalhub/stores/data/sql/configurator.py +0 -8
  54. digitalhub/stores/data/sql/store.py +0 -4
  55. digitalhub/stores/readers/data/factory.py +0 -8
  56. digitalhub/stores/readers/data/pandas/reader.py +0 -16
  57. digitalhub/utils/io_utils.py +0 -4
  58. {digitalhub-0.14.0b2.dist-info → digitalhub-0.14.0b3.dist-info}/METADATA +1 -1
  59. {digitalhub-0.14.0b2.dist-info → digitalhub-0.14.0b3.dist-info}/RECORD +62 -52
  60. digitalhub/entities/_processors/context.py +0 -1499
  61. {digitalhub-0.14.0b2.dist-info → digitalhub-0.14.0b3.dist-info}/WHEEL +0 -0
  62. {digitalhub-0.14.0b2.dist-info → digitalhub-0.14.0b3.dist-info}/licenses/AUTHORS +0 -0
  63. {digitalhub-0.14.0b2.dist-info → digitalhub-0.14.0b3.dist-info}/licenses/LICENSE +0 -0
@@ -82,10 +82,6 @@ class ContextBuilder:
82
82
  ----------
83
83
  project : str
84
84
  The name of the project whose context should be removed.
85
-
86
- Returns
87
- -------
88
- None
89
85
  This method does not return anything.
90
86
 
91
87
  Notes
@@ -4,9 +4,12 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
+ import os
7
8
  import typing
8
9
  from pathlib import Path
9
10
 
11
+ from digitalhub.runtimes.enums import RuntimeEnvVar
12
+
10
13
  if typing.TYPE_CHECKING:
11
14
  from digitalhub.entities.project._base.entity import Project
12
15
  from digitalhub.stores.client._base.client import Client
@@ -47,6 +50,15 @@ class Context:
47
50
 
48
51
  self.is_running: bool = False
49
52
  self._run_ctx: str | None = None
53
+ self._search_run_ctx()
54
+
55
+ def _search_run_ctx(self) -> None:
56
+ """
57
+ Search for an existing run id in env.
58
+ """
59
+ run_id = os.getenv(RuntimeEnvVar.RUN_ID.value)
60
+ if run_id is not None:
61
+ self.set_run(run_id)
50
62
 
51
63
  def set_run(self, run_ctx: str) -> None:
52
64
  """
@@ -56,10 +68,6 @@ class Context:
56
68
  ----------
57
69
  run_ctx : str
58
70
  The run key to set.
59
-
60
- Returns
61
- -------
62
- None
63
71
  """
64
72
  self.is_running = True
65
73
  self._run_ctx = run_ctx
@@ -67,10 +75,6 @@ class Context:
67
75
  def unset_run(self) -> None:
68
76
  """
69
77
  Clear the current run key and reset running state.
70
-
71
- Returns
72
- -------
73
- None
74
78
  """
75
79
  self.is_running = False
76
80
  self._run_ctx = None
@@ -54,10 +54,6 @@ class Base:
54
54
  ----------
55
55
  **kwargs : dict
56
56
  Keyword arguments to be set as attributes.
57
-
58
- Returns
59
- -------
60
- None
61
57
  """
62
58
  for k, v in kwargs.items():
63
59
  if k not in self.__dict__:
@@ -8,7 +8,7 @@ import typing
8
8
 
9
9
  from digitalhub.context.api import get_context
10
10
  from digitalhub.entities._base.entity.entity import Entity
11
- from digitalhub.entities._processors.context import context_processor
11
+ from digitalhub.entities._processors.processors import context_processor
12
12
  from digitalhub.utils.generic_utils import get_timestamp
13
13
  from digitalhub.utils.io_utils import write_yaml
14
14
 
@@ -67,10 +67,6 @@ class Entity(Base):
67
67
  ----------
68
68
  obj : dict
69
69
  Mapping representation of object.
70
-
71
- Returns
72
- -------
73
- None
74
70
  """
75
71
  self.metadata = obj.metadata
76
72
  self.spec = obj.spec
@@ -95,10 +91,6 @@ class Entity(Base):
95
91
  The target entity.
96
92
  source : str
97
93
  The source entity.
98
-
99
- Returns
100
- -------
101
- None
102
94
  """
103
95
  if self.metadata.relationships is None:
104
96
  self.metadata.relationships = []
@@ -9,7 +9,7 @@ from abc import abstractmethod
9
9
 
10
10
  from digitalhub.entities._base.versioned.entity import VersionedEntity
11
11
  from digitalhub.entities._commons.enums import EntityTypes
12
- from digitalhub.entities._processors.context import context_processor
12
+ from digitalhub.entities._processors.processors import context_processor
13
13
  from digitalhub.entities.run.crud import list_runs
14
14
  from digitalhub.entities.task.crud import delete_task, list_tasks
15
15
  from digitalhub.entities.trigger.crud import list_triggers
@@ -94,10 +94,6 @@ class ExecutableEntity(VersionedEntity):
94
94
  ----------
95
95
  tasks : list[dict]
96
96
  List of tasks to import.
97
-
98
- Returns
99
- -------
100
- None
101
97
  """
102
98
  # Loop over tasks list, in the case where the function
103
99
  # is imported from local file.
@@ -295,10 +291,6 @@ class ExecutableEntity(VersionedEntity):
295
291
  kind : str
296
292
  Kind the object.
297
293
 
298
- Returns
299
- -------
300
- None
301
-
302
294
  Raises
303
295
  ------
304
296
  EntityError
@@ -316,10 +308,6 @@ class ExecutableEntity(VersionedEntity):
316
308
  kind : str
317
309
  Kind the object.
318
310
 
319
- Returns
320
- -------
321
- None
322
-
323
311
  Raises
324
312
  ------
325
313
  EntityError
@@ -361,14 +349,10 @@ class ExecutableEntity(VersionedEntity):
361
349
  Examples
362
350
  --------
363
351
  Using entity key:
364
- >>> obj = executable.get_run(
365
- ... "store://my-secret-key"
366
- ... )
352
+ >>> obj = executable.get_run("store://my-secret-key")
367
353
 
368
354
  Using entity ID:
369
- >>> obj = executable.get_run(
370
- ... "123"
371
- ... )
355
+ >>> obj = executable.get_run("123")
372
356
  """
373
357
  entities = self.list_runs(**kwargs)
374
358
  for entity in entities:
@@ -472,14 +456,10 @@ class ExecutableEntity(VersionedEntity):
472
456
  Examples
473
457
  --------
474
458
  Using entity key:
475
- >>> obj = executable.get_trigger(
476
- ... "store://my-trigger-key"
477
- ... )
459
+ >>> obj = executable.get_trigger("store://my-trigger-key")
478
460
 
479
461
  Using entity ID:
480
- >>> obj = executable.get_trigger(
481
- ... "123"
482
- ... )
462
+ >>> obj = executable.get_trigger("123")
483
463
  """
484
464
  entities = self.list_triggers(**kwargs)
485
465
  for entity in entities:
@@ -8,7 +8,7 @@ import typing
8
8
  from pathlib import Path
9
9
 
10
10
  from digitalhub.entities._base.versioned.entity import VersionedEntity
11
- from digitalhub.entities._processors.context import context_processor
11
+ from digitalhub.entities._processors.processors import context_processor
12
12
  from digitalhub.stores.data.api import get_store
13
13
  from digitalhub.utils.types import SourcesOrListOfSources
14
14
 
@@ -142,24 +142,16 @@ class MaterialEntity(VersionedEntity):
142
142
  source : str | list[str]
143
143
  Local filepath, directory or list of filepaths.
144
144
 
145
- Returns
146
- -------
147
- None
148
-
149
145
  Examples
150
146
  --------
151
147
  Upload a single file:
152
148
 
153
149
  >>> entity.spec.path = "s3://bucket/data.csv"
154
- >>> entity.upload(
155
- ... "./data.csv"
156
- ... )
150
+ >>> entity.upload("./data.csv")
157
151
 
158
152
  Upload a folder:
159
153
  >>> entity.spec.path = "s3://bucket/data/"
160
- >>> entity.upload(
161
- ... "./data"
162
- ... )
154
+ >>> entity.upload("./data")
163
155
  """
164
156
  # Get store and upload object
165
157
  store = get_store(self.spec.path)
@@ -181,10 +173,6 @@ class MaterialEntity(VersionedEntity):
181
173
  ----------
182
174
  files : list[dict]
183
175
  Files to add.
184
-
185
- Returns
186
- -------
187
- None
188
176
  """
189
177
  available = 100 - len(self.status.files)
190
178
  if len(files) > available:
@@ -218,10 +206,6 @@ class MaterialEntity(VersionedEntity):
218
206
  ----------
219
207
  files_info : list[dict] | None
220
208
  Files info.
221
-
222
- Returns
223
- -------
224
- None
225
209
  """
226
210
  if files_info is None:
227
211
  return
@@ -233,10 +217,6 @@ class MaterialEntity(VersionedEntity):
233
217
  def _get_files_info(self) -> None:
234
218
  """
235
219
  Get files info from backend.
236
-
237
- Returns
238
- -------
239
- None
240
220
  """
241
221
  if not self._context().local and not self.status.files:
242
222
  files = context_processor.read_files_info(
@@ -7,7 +7,7 @@ from __future__ import annotations
7
7
  import typing
8
8
 
9
9
  from digitalhub.entities._base.context.entity import ContextEntity
10
- from digitalhub.entities._processors.context import context_processor
10
+ from digitalhub.entities._processors.processors import context_processor
11
11
 
12
12
  if typing.TYPE_CHECKING:
13
13
  from digitalhub.entities._base.entity.metadata import Metadata
@@ -7,7 +7,7 @@ from __future__ import annotations
7
7
  import typing
8
8
 
9
9
  from digitalhub.entities._base.context.entity import ContextEntity
10
- from digitalhub.entities._processors.context import context_processor
10
+ from digitalhub.entities._processors.processors import context_processor
11
11
 
12
12
  if typing.TYPE_CHECKING:
13
13
  from digitalhub.entities._base.entity.metadata import Metadata
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
@@ -5,34 +5,25 @@
5
5
  from __future__ import annotations
6
6
 
7
7
  import typing
8
- from warnings import warn
9
8
 
10
9
  from digitalhub.context.api import delete_context
11
10
  from digitalhub.entities._commons.enums import ApiCategories, BackendOperations
12
11
  from digitalhub.factory.entity import entity_factory
13
12
  from digitalhub.stores.client.api import get_client
14
- from digitalhub.utils.exceptions import EntityAlreadyExistsError, EntityError, EntityNotExistsError
15
- from digitalhub.utils.io_utils import read_yaml
16
13
 
17
14
  if typing.TYPE_CHECKING:
18
15
  from digitalhub.entities.project._base.entity import Project
19
16
  from digitalhub.stores.client._base.client import Client
20
17
 
21
18
 
22
- class BaseEntityOperationsProcessor:
19
+ class BaseEntityCRUDProcessor:
23
20
  """
24
- Processor for base entity operations.
21
+ Processor for core CRUD operations on base entities.
25
22
 
26
- This class handles CRUD operations and other entity management tasks
27
- for base-level entities (primarily projects). It interacts with the
28
- client layer to perform backend operations and manages entity lifecycle
29
- including creation, reading, updating, deletion, and sharing.
23
+ Handles creation, reading, updating, deletion, and listing of
24
+ base-level entities (primarily projects) within the backend.
30
25
  """
31
26
 
32
- ##############################
33
- # CRUD base entity
34
- ##############################
35
-
36
27
  def _create_base_entity(
37
28
  self,
38
29
  client: Client,
@@ -174,97 +165,6 @@ class BaseEntityOperationsProcessor:
174
165
  obj["local"] = client.is_local()
175
166
  return entity_factory.build_entity_from_dict(obj)
176
167
 
177
- def import_project_entity(
178
- self,
179
- file: str,
180
- **kwargs,
181
- ) -> Project:
182
- """
183
- Import a project entity from a YAML file and create it in the backend.
184
-
185
- Reads project configuration from a YAML file, creates a new project
186
- entity in the backend, and imports any related entities defined
187
- in the file. Raises an error if the project already exists.
188
-
189
- Parameters
190
- ----------
191
- file : str
192
- Path to the YAML file containing project configuration.
193
- **kwargs : dict
194
- Additional parameters including 'local' and 'reset_id' flags.
195
-
196
- Returns
197
- -------
198
- Project
199
- The imported and created project entity.
200
-
201
- Raises
202
- ------
203
- EntityError
204
- If the project already exists in the backend.
205
- """
206
- client = get_client(kwargs.pop("local", False))
207
- obj: dict = read_yaml(file)
208
- obj["status"] = {}
209
- obj["local"] = client.is_local()
210
- ent: Project = entity_factory.build_entity_from_dict(obj)
211
- reset_id = kwargs.pop("reset_id", False)
212
-
213
- try:
214
- self._create_base_entity(ent._client, ent.ENTITY_TYPE, ent.to_dict())
215
- except EntityAlreadyExistsError:
216
- msg = f"Entity {ent.name} already exists."
217
- if reset_id:
218
- ent._import_entities(obj, reset_id=reset_id)
219
- warn(f"{msg} Other entities ids have been imported.")
220
- ent.refresh()
221
- return ent
222
- raise EntityError(f"{msg} If you want to update it, use load instead.")
223
-
224
- # Import related entities
225
- ent._import_entities(obj, reset_id=reset_id)
226
- ent.refresh()
227
- return ent
228
-
229
- def load_project_entity(
230
- self,
231
- file: str,
232
- **kwargs,
233
- ) -> Project:
234
- """
235
- Load a project entity from a YAML file and update it in the backend.
236
-
237
- Reads project configuration from a YAML file and updates an existing
238
- project in the backend. If the project doesn't exist, it creates a
239
- new one. Also loads any related entities defined in the file.
240
-
241
- Parameters
242
- ----------
243
- file : str
244
- Path to the YAML file containing project configuration.
245
- **kwargs : dict
246
- Additional parameters including 'local' flag.
247
-
248
- Returns
249
- -------
250
- Project
251
- The loaded and updated project entity.
252
- """
253
- client = get_client(kwargs.pop("local", False))
254
- obj: dict = read_yaml(file)
255
- obj["local"] = client.is_local()
256
- ent: Project = entity_factory.build_entity_from_dict(obj)
257
-
258
- try:
259
- self._update_base_entity(ent._client, ent.ENTITY_TYPE, ent.name, ent.to_dict())
260
- except EntityNotExistsError:
261
- self._create_base_entity(ent._client, ent.ENTITY_TYPE, ent.to_dict())
262
-
263
- # Load related entities
264
- ent._load_entities(obj)
265
- ent.refresh()
266
- return ent
267
-
268
168
  def _list_base_entities(
269
169
  self,
270
170
  client: Client,
@@ -464,6 +364,8 @@ class BaseEntityOperationsProcessor:
464
364
 
465
365
  Parameters
466
366
  ----------
367
+ crud_processor : BaseEntityCRUDProcessor
368
+ The CRUD processor instance for entity operations.
467
369
  entity_type : str
468
370
  The type of entity to delete (typically 'project').
469
371
  entity_name : str
@@ -486,125 +388,3 @@ class BaseEntityOperationsProcessor:
486
388
  entity_name,
487
389
  **kwargs,
488
390
  )
489
-
490
- ##############################
491
- # Base entity operations
492
- ##############################
493
-
494
- def _build_base_entity_key(
495
- self,
496
- client: Client,
497
- entity_id: str,
498
- ) -> str:
499
- """
500
- Build a storage key for a base entity.
501
-
502
- Creates a standardized key string that can be used to identify
503
- and store the entity in various contexts.
504
-
505
- Parameters
506
- ----------
507
- client : Client
508
- The client instance to use for key building.
509
- entity_id : str
510
- The unique identifier of the entity.
511
-
512
- Returns
513
- -------
514
- str
515
- The constructed entity key string.
516
- """
517
- return client.build_key(ApiCategories.BASE.value, entity_id)
518
-
519
- def build_project_key(
520
- self,
521
- entity_id: str,
522
- **kwargs,
523
- ) -> str:
524
- """
525
- Build a storage key for a project entity.
526
-
527
- Creates a standardized key string for project identification
528
- and storage, handling both local and remote client contexts.
529
-
530
- Parameters
531
- ----------
532
- entity_id : str
533
- The unique identifier of the project entity.
534
- **kwargs : dict
535
- Additional parameters including 'local' flag.
536
-
537
- Returns
538
- -------
539
- str
540
- The constructed project entity key string.
541
- """
542
- client = get_client(kwargs.pop("local", False))
543
- return self._build_base_entity_key(client, entity_id)
544
-
545
- def share_project_entity(
546
- self,
547
- entity_type: str,
548
- entity_name: str,
549
- **kwargs,
550
- ) -> None:
551
- """
552
- Share or unshare a project entity with a user.
553
-
554
- Manages project access permissions by sharing the project with
555
- a specified user or removing user access. Handles both sharing
556
- and unsharing operations based on the 'unshare' parameter.
557
-
558
- Parameters
559
- ----------
560
- entity_type : str
561
- The type of entity to share (typically 'project').
562
- entity_name : str
563
- The name identifier of the project to share.
564
- **kwargs : dict
565
- Additional parameters including:
566
- - 'user': username to share with/unshare from
567
- - 'unshare': boolean flag for unsharing (default False)
568
- - 'local': boolean flag for local backend
569
-
570
- Returns
571
- -------
572
- None
573
-
574
- Raises
575
- ------
576
- ValueError
577
- If trying to unshare from a user who doesn't have access.
578
- """
579
- client = get_client(kwargs.pop("local", False))
580
- api = client.build_api(
581
- ApiCategories.BASE.value,
582
- BackendOperations.SHARE.value,
583
- entity_type=entity_type,
584
- entity_name=entity_name,
585
- )
586
-
587
- user = kwargs.pop("user", None)
588
- if unshare := kwargs.pop("unshare", False):
589
- users = client.read_object(api, **kwargs)
590
- for u in users:
591
- if u["user"] == user:
592
- kwargs["id"] = u["id"]
593
- break
594
- else:
595
- raise ValueError(f"User '{user}' does not have access to project.")
596
-
597
- kwargs = client.build_parameters(
598
- ApiCategories.BASE.value,
599
- BackendOperations.SHARE.value,
600
- unshare=unshare,
601
- user=user,
602
- **kwargs,
603
- )
604
- if unshare:
605
- client.delete_object(api, **kwargs)
606
- return
607
- client.create_object(api, obj={}, **kwargs)
608
-
609
-
610
- base_processor = BaseEntityOperationsProcessor()
@@ -0,0 +1,122 @@
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 warnings import warn
9
+
10
+ from digitalhub.factory.entity import entity_factory
11
+ from digitalhub.stores.client.api import get_client
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.project._base.entity import Project
17
+
18
+
19
+ class BaseEntityImportExportProcessor:
20
+ """
21
+ Processor for import and export operations on base entities.
22
+
23
+ Handles loading entities from YAML files and importing/exporting
24
+ entity configurations between local files and the backend.
25
+ """
26
+
27
+ def import_project_entity(
28
+ self,
29
+ crud_processor,
30
+ file: str,
31
+ **kwargs,
32
+ ) -> Project:
33
+ """
34
+ Import a project entity from a YAML file and create it in the backend.
35
+
36
+ Reads project configuration from a YAML file, creates a new project
37
+ entity in the backend, and imports any related entities defined
38
+ in the file. Raises an error if the project already exists.
39
+
40
+ Parameters
41
+ ----------
42
+ crud_processor : BaseEntityCRUDProcessor
43
+ The CRUD processor instance for entity operations.
44
+ file : str
45
+ Path to the YAML file containing project configuration.
46
+ **kwargs : dict
47
+ Additional parameters including 'local' and 'reset_id' flags.
48
+
49
+ Returns
50
+ -------
51
+ Project
52
+ The imported and created project entity.
53
+
54
+ Raises
55
+ ------
56
+ EntityError
57
+ If the project already exists in the backend.
58
+ """
59
+ client = get_client(kwargs.pop("local", False))
60
+ obj: dict = read_yaml(file)
61
+ obj["status"] = {}
62
+ obj["local"] = client.is_local()
63
+ ent: Project = entity_factory.build_entity_from_dict(obj)
64
+ reset_id = kwargs.pop("reset_id", False)
65
+
66
+ try:
67
+ crud_processor._create_base_entity(ent._client, ent.ENTITY_TYPE, ent.to_dict())
68
+ except EntityAlreadyExistsError:
69
+ msg = f"Entity {ent.name} already exists."
70
+ if reset_id:
71
+ ent._import_entities(obj, reset_id=reset_id)
72
+ warn(f"{msg} Other entities ids have been imported.")
73
+ ent.refresh()
74
+ return ent
75
+ raise EntityError(f"{msg} If you want to update it, use load instead.")
76
+
77
+ # Import related entities
78
+ ent._import_entities(obj, reset_id=reset_id)
79
+ ent.refresh()
80
+ return ent
81
+
82
+ def load_project_entity(
83
+ self,
84
+ crud_processor,
85
+ file: str,
86
+ **kwargs,
87
+ ) -> Project:
88
+ """
89
+ Load a project entity from a YAML file and update it in the backend.
90
+
91
+ Reads project configuration from a YAML file and updates an existing
92
+ project in the backend. If the project doesn't exist, it creates a
93
+ new one. Also loads any related entities defined in the file.
94
+
95
+ Parameters
96
+ ----------
97
+ crud_processor : BaseEntityCRUDProcessor
98
+ The CRUD processor instance for entity operations.
99
+ file : str
100
+ Path to the YAML file containing project configuration.
101
+ **kwargs : dict
102
+ Additional parameters including 'local' flag.
103
+
104
+ Returns
105
+ -------
106
+ Project
107
+ The loaded and updated project entity.
108
+ """
109
+ client = get_client(kwargs.pop("local", False))
110
+ obj: dict = read_yaml(file)
111
+ obj["local"] = client.is_local()
112
+ ent: Project = entity_factory.build_entity_from_dict(obj)
113
+
114
+ try:
115
+ crud_processor._update_base_entity(ent._client, ent.ENTITY_TYPE, ent.name, ent.to_dict())
116
+ except EntityNotExistsError:
117
+ crud_processor._create_base_entity(ent._client, ent.ENTITY_TYPE, ent.to_dict())
118
+
119
+ # Load related entities
120
+ ent._load_entities(obj)
121
+ ent.refresh()
122
+ return ent