digitalhub 0.9.1__py3-none-any.whl → 0.10.0__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 (121) hide show
  1. digitalhub/__init__.py +2 -3
  2. digitalhub/client/_base/api_builder.py +1 -1
  3. digitalhub/client/_base/client.py +25 -2
  4. digitalhub/client/_base/params_builder.py +16 -0
  5. digitalhub/client/dhcore/api_builder.py +10 -4
  6. digitalhub/client/dhcore/client.py +30 -398
  7. digitalhub/client/dhcore/configurator.py +361 -0
  8. digitalhub/client/dhcore/error_parser.py +107 -0
  9. digitalhub/client/dhcore/models.py +13 -23
  10. digitalhub/client/dhcore/params_builder.py +178 -0
  11. digitalhub/client/dhcore/utils.py +4 -44
  12. digitalhub/client/local/api_builder.py +13 -18
  13. digitalhub/client/local/client.py +18 -2
  14. digitalhub/client/local/enums.py +11 -0
  15. digitalhub/client/local/params_builder.py +116 -0
  16. digitalhub/configurator/api.py +31 -0
  17. digitalhub/configurator/configurator.py +195 -0
  18. digitalhub/configurator/credentials_store.py +65 -0
  19. digitalhub/configurator/ini_module.py +74 -0
  20. digitalhub/entities/_base/_base/entity.py +2 -2
  21. digitalhub/entities/_base/context/entity.py +4 -4
  22. digitalhub/entities/_base/entity/builder.py +5 -5
  23. digitalhub/entities/_base/executable/entity.py +2 -2
  24. digitalhub/entities/_base/material/entity.py +12 -12
  25. digitalhub/entities/_base/material/status.py +1 -1
  26. digitalhub/entities/_base/material/utils.py +2 -2
  27. digitalhub/entities/_base/unversioned/entity.py +2 -2
  28. digitalhub/entities/_base/versioned/entity.py +2 -2
  29. digitalhub/entities/_commons/enums.py +2 -0
  30. digitalhub/entities/_commons/metrics.py +164 -0
  31. digitalhub/entities/_commons/types.py +5 -0
  32. digitalhub/entities/_commons/utils.py +2 -2
  33. digitalhub/entities/_processors/base.py +527 -0
  34. digitalhub/entities/{_operations/processor.py → _processors/context.py} +212 -837
  35. digitalhub/entities/_processors/utils.py +158 -0
  36. digitalhub/entities/artifact/artifact/spec.py +3 -1
  37. digitalhub/entities/artifact/crud.py +13 -12
  38. digitalhub/entities/artifact/utils.py +1 -1
  39. digitalhub/entities/builders.py +6 -18
  40. digitalhub/entities/dataitem/_base/entity.py +0 -41
  41. digitalhub/entities/dataitem/crud.py +27 -15
  42. digitalhub/entities/dataitem/table/entity.py +49 -35
  43. digitalhub/entities/dataitem/table/models.py +4 -3
  44. digitalhub/{utils/data_utils.py → entities/dataitem/table/utils.py} +46 -54
  45. digitalhub/entities/dataitem/utils.py +58 -10
  46. digitalhub/entities/function/crud.py +9 -9
  47. digitalhub/entities/model/_base/entity.py +120 -0
  48. digitalhub/entities/model/_base/spec.py +6 -17
  49. digitalhub/entities/model/_base/status.py +10 -0
  50. digitalhub/entities/model/crud.py +13 -12
  51. digitalhub/entities/model/huggingface/spec.py +9 -4
  52. digitalhub/entities/model/mlflow/models.py +2 -2
  53. digitalhub/entities/model/mlflow/spec.py +7 -7
  54. digitalhub/entities/model/mlflow/utils.py +44 -5
  55. digitalhub/entities/project/_base/entity.py +317 -9
  56. digitalhub/entities/project/_base/spec.py +8 -6
  57. digitalhub/entities/project/crud.py +12 -11
  58. digitalhub/entities/run/_base/entity.py +103 -6
  59. digitalhub/entities/run/_base/spec.py +4 -2
  60. digitalhub/entities/run/_base/status.py +12 -0
  61. digitalhub/entities/run/crud.py +8 -8
  62. digitalhub/entities/secret/_base/entity.py +3 -3
  63. digitalhub/entities/secret/_base/spec.py +4 -2
  64. digitalhub/entities/secret/crud.py +11 -9
  65. digitalhub/entities/task/_base/entity.py +4 -4
  66. digitalhub/entities/task/_base/models.py +51 -40
  67. digitalhub/entities/task/_base/spec.py +2 -0
  68. digitalhub/entities/task/_base/utils.py +2 -2
  69. digitalhub/entities/task/crud.py +12 -8
  70. digitalhub/entities/workflow/crud.py +9 -9
  71. digitalhub/factory/utils.py +9 -9
  72. digitalhub/readers/{_base → data/_base}/builder.py +1 -1
  73. digitalhub/readers/{_base → data/_base}/reader.py +16 -4
  74. digitalhub/readers/{api.py → data/api.py} +2 -2
  75. digitalhub/readers/{factory.py → data/factory.py} +3 -3
  76. digitalhub/readers/{pandas → data/pandas}/builder.py +2 -2
  77. digitalhub/readers/{pandas → data/pandas}/reader.py +110 -30
  78. digitalhub/readers/query/__init__.py +0 -0
  79. digitalhub/stores/_base/store.py +59 -69
  80. digitalhub/stores/api.py +8 -33
  81. digitalhub/stores/builder.py +44 -161
  82. digitalhub/stores/local/store.py +106 -89
  83. digitalhub/stores/remote/store.py +86 -11
  84. digitalhub/stores/s3/configurator.py +108 -0
  85. digitalhub/stores/s3/enums.py +17 -0
  86. digitalhub/stores/s3/models.py +21 -0
  87. digitalhub/stores/s3/store.py +154 -70
  88. digitalhub/{utils/s3_utils.py → stores/s3/utils.py} +7 -3
  89. digitalhub/stores/sql/configurator.py +88 -0
  90. digitalhub/stores/sql/enums.py +16 -0
  91. digitalhub/stores/sql/models.py +24 -0
  92. digitalhub/stores/sql/store.py +106 -85
  93. digitalhub/{readers/_commons → utils}/enums.py +5 -1
  94. digitalhub/utils/exceptions.py +6 -0
  95. digitalhub/utils/file_utils.py +8 -7
  96. digitalhub/utils/generic_utils.py +28 -15
  97. digitalhub/utils/git_utils.py +16 -9
  98. digitalhub/utils/types.py +5 -0
  99. digitalhub/utils/uri_utils.py +2 -2
  100. {digitalhub-0.9.1.dist-info → digitalhub-0.10.0.dist-info}/METADATA +25 -31
  101. {digitalhub-0.9.1.dist-info → digitalhub-0.10.0.dist-info}/RECORD +108 -99
  102. {digitalhub-0.9.1.dist-info → digitalhub-0.10.0.dist-info}/WHEEL +1 -2
  103. digitalhub/client/dhcore/env.py +0 -23
  104. digitalhub/entities/_base/project/entity.py +0 -341
  105. digitalhub-0.9.1.dist-info/top_level.txt +0 -2
  106. test/local/CRUD/test_artifacts.py +0 -96
  107. test/local/CRUD/test_dataitems.py +0 -96
  108. test/local/CRUD/test_models.py +0 -95
  109. test/local/imports/test_imports.py +0 -66
  110. test/local/instances/test_validate.py +0 -55
  111. test/test_crud_functions.py +0 -109
  112. test/test_crud_runs.py +0 -86
  113. test/test_crud_tasks.py +0 -81
  114. test/testkfp.py +0 -37
  115. test/testkfp_pipeline.py +0 -22
  116. /digitalhub/{entities/_base/project → configurator}/__init__.py +0 -0
  117. /digitalhub/entities/{_operations → _processors}/__init__.py +0 -0
  118. /digitalhub/readers/{_base → data}/__init__.py +0 -0
  119. /digitalhub/readers/{_commons → data/_base}/__init__.py +0 -0
  120. /digitalhub/readers/{pandas → data/pandas}/__init__.py +0 -0
  121. {digitalhub-0.9.1.dist-info → digitalhub-0.10.0.dist-info/licenses}/LICENSE.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from digitalhub.utils.generic_utils import dict_to_json
3
+ from digitalhub.utils.generic_utils import dump_json
4
4
 
5
5
 
6
6
  class Base:
@@ -40,7 +40,7 @@ class Base:
40
40
  str
41
41
  A json string containing the attributes of the entity instance.
42
42
  """
43
- return dict_to_json(self.to_dict())
43
+ return dump_json(self.to_dict())
44
44
 
45
45
  def _any_setter(self, **kwargs) -> None:
46
46
  """
@@ -4,7 +4,7 @@ import typing
4
4
 
5
5
  from digitalhub.context.api import get_context
6
6
  from digitalhub.entities._base.entity.entity import Entity
7
- from digitalhub.entities._operations.processor import processor
7
+ from digitalhub.entities._processors.context import context_processor
8
8
  from digitalhub.utils.generic_utils import get_timestamp
9
9
  from digitalhub.utils.io_utils import write_yaml
10
10
 
@@ -64,7 +64,7 @@ class ContextEntity(Entity):
64
64
  ContextEntity
65
65
  Entity saved.
66
66
  """
67
- new_obj = processor.create_context_entity(_entity=self)
67
+ new_obj = context_processor.create_context_entity(_entity=self)
68
68
  self._update_attributes(new_obj)
69
69
  return self
70
70
 
@@ -79,7 +79,7 @@ class ContextEntity(Entity):
79
79
  """
80
80
  if self._context().local:
81
81
  self.metadata.updated = self.metadata.updated = get_timestamp()
82
- new_obj = processor.update_context_entity(self.project, self.ENTITY_TYPE, self.id, self.to_dict())
82
+ new_obj = context_processor.update_context_entity(self.project, self.ENTITY_TYPE, self.id, self.to_dict())
83
83
  self._update_attributes(new_obj)
84
84
  return self
85
85
 
@@ -106,7 +106,7 @@ class ContextEntity(Entity):
106
106
  ContextEntity
107
107
  Entity refreshed.
108
108
  """
109
- new_obj = processor.read_context_entity(self.key)
109
+ new_obj = context_processor.read_context_entity(self.key)
110
110
  self._update_attributes(new_obj)
111
111
  return self
112
112
 
@@ -24,10 +24,10 @@ class EntityBuilder:
24
24
 
25
25
  # Class variables
26
26
  ENTITY_TYPE: str = None
27
- ENTITY_CLASS: Entity = None
28
- ENTITY_SPEC_CLASS: Spec = None
29
- ENTITY_SPEC_VALIDATOR: SpecValidator = None
30
- ENTITY_STATUS_CLASS: Status = None
27
+ ENTITY_CLASS: type[Entity] = None
28
+ ENTITY_SPEC_CLASS: type[Spec] = None
29
+ ENTITY_SPEC_VALIDATOR: type[SpecValidator] = None
30
+ ENTITY_STATUS_CLASS: type[Status] = None
31
31
  ENTITY_KIND: str = None
32
32
 
33
33
  def __init__(self) -> None:
@@ -60,7 +60,7 @@ class EntityBuilder:
60
60
  """
61
61
  return build_name(name)
62
62
 
63
- def build_uuid(self, uuid: str) -> str:
63
+ def build_uuid(self, uuid: str | None = None) -> str:
64
64
  """
65
65
  Build entity uuid.
66
66
 
@@ -4,7 +4,7 @@ import typing
4
4
 
5
5
  from digitalhub.entities._base.versioned.entity import VersionedEntity
6
6
  from digitalhub.entities._commons.enums import EntityTypes
7
- from digitalhub.entities._operations.processor import processor
7
+ from digitalhub.entities._processors.context import context_processor
8
8
  from digitalhub.entities.run.crud import delete_run, get_run, list_runs
9
9
  from digitalhub.entities.task.crud import delete_task
10
10
  from digitalhub.factory.api import build_entity_from_dict, build_entity_from_params
@@ -247,7 +247,7 @@ class ExecutableEntity(VersionedEntity):
247
247
  Response from backend.
248
248
  """
249
249
  params = {self.ENTITY_TYPE: self._get_executable_string(), "kind": kind}
250
- return processor.list_context_entities(self.project, EntityTypes.TASK.value, params=params)
250
+ return context_processor.list_context_entities(self.project, EntityTypes.TASK.value, params=params)
251
251
 
252
252
  def _check_task_in_backend(self, kind: str) -> bool:
253
253
  """
@@ -4,8 +4,9 @@ import typing
4
4
  from pathlib import Path
5
5
 
6
6
  from digitalhub.entities._base.versioned.entity import VersionedEntity
7
- from digitalhub.entities._operations.processor import processor
7
+ from digitalhub.entities._processors.context import context_processor
8
8
  from digitalhub.stores.api import get_store
9
+ from digitalhub.utils.types import SourcesOrListOfSources
9
10
 
10
11
  if typing.TYPE_CHECKING:
11
12
  from digitalhub.entities._base.entity.metadata import Metadata
@@ -58,7 +59,7 @@ class MaterialEntity(VersionedEntity):
58
59
 
59
60
  # Handle files info
60
61
  if files is not None:
61
- processor.update_files_info(self.project, self.ENTITY_TYPE, self.id, files)
62
+ context_processor.update_files_info(self.project, self.ENTITY_TYPE, self.id, files)
62
63
  self.add_files_info(files)
63
64
 
64
65
  return obj
@@ -77,7 +78,7 @@ class MaterialEntity(VersionedEntity):
77
78
  list[str]
78
79
  List of file paths.
79
80
  """
80
- store = get_store(self.spec.path)
81
+ store = get_store(self.project, self.spec.path)
81
82
  paths = self.get_file_paths()
82
83
  dst = store._build_temp()
83
84
  return store.download(self.spec.path, dst=dst, src=paths)
@@ -126,7 +127,7 @@ class MaterialEntity(VersionedEntity):
126
127
  >>> print(path)
127
128
  dataitem/data.csv
128
129
  """
129
- store = get_store(self.spec.path)
130
+ store = get_store(self.project, self.spec.path)
130
131
  paths = self.get_file_paths()
131
132
 
132
133
  if destination is None:
@@ -136,7 +137,7 @@ class MaterialEntity(VersionedEntity):
136
137
 
137
138
  return store.download(self.spec.path, dst=dst, src=paths, overwrite=overwrite)
138
139
 
139
- def upload(self, source: str | list[str]) -> None:
140
+ def upload(self, source: SourcesOrListOfSources) -> None:
140
141
  """
141
142
  Upload object from given local path to spec path destination.
142
143
  Source must be a local path. If the path is a folder, destination
@@ -164,7 +165,7 @@ class MaterialEntity(VersionedEntity):
164
165
  >>> entity.upload('./data')
165
166
  """
166
167
  # Get store and upload object
167
- store = get_store(self.spec.path)
168
+ store = get_store(self.project, self.spec.path)
168
169
  paths = store.upload(source, self.spec.path)
169
170
 
170
171
  # Update files info
@@ -193,17 +194,15 @@ class MaterialEntity(VersionedEntity):
193
194
  if f.get("path") not in path_list:
194
195
  self.status.files.append(f)
195
196
 
196
- def get_file_paths(self) -> list[str]:
197
+ def get_file_paths(self) -> list:
197
198
  """
198
199
  Get the paths of the files in the status.
199
200
 
200
201
  Returns
201
202
  -------
202
- list[str]
203
+ list
203
204
  Paths of the files in the status.
204
205
  """
205
- if self.status.files is None:
206
- self.status.files = []
207
206
  return [f.get("path") for f in self.status.files]
208
207
 
209
208
  ##############################
@@ -225,7 +224,8 @@ class MaterialEntity(VersionedEntity):
225
224
  """
226
225
  if files_info is None:
227
226
  return
228
- self.refresh()
227
+ if self.status.files:
228
+ self.refresh()
229
229
  self.add_files_info(files_info)
230
230
  self.save(update=True)
231
231
 
@@ -238,7 +238,7 @@ class MaterialEntity(VersionedEntity):
238
238
  None
239
239
  """
240
240
  if not self._context().local and not self.status.files:
241
- files = processor.read_files_info(
241
+ files = context_processor.read_files_info(
242
242
  project=self.project,
243
243
  entity_type=self.ENTITY_TYPE,
244
244
  entity_id=self.id,
@@ -15,4 +15,4 @@ class MaterialStatus(Status):
15
15
  files: list[dict] | None = None,
16
16
  ) -> None:
17
17
  super().__init__(state, message)
18
- self.files = files
18
+ self.files = files if files is not None else []
@@ -2,8 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  from pathlib import Path
4
4
 
5
+ from digitalhub.stores.s3.utils import get_s3_bucket_from_env
5
6
  from digitalhub.utils.file_utils import eval_zip_type
6
- from digitalhub.utils.s3_utils import get_s3_bucket
7
7
  from digitalhub.utils.uri_utils import S3Schemes, has_local_scheme
8
8
 
9
9
 
@@ -91,7 +91,7 @@ def build_log_path_from_source(
91
91
  Log path.
92
92
  """
93
93
  scheme = eval_zip_sources(source)
94
- path = f"{scheme}://{get_s3_bucket()}/{project}/{entity_type}/{name}/{uuid}"
94
+ path = f"{scheme}://{get_s3_bucket_from_env()}/{project}/{entity_type}/{name}/{uuid}"
95
95
 
96
96
  if isinstance(source, list) and len(source) >= 1:
97
97
  if len(source) > 1:
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import typing
4
4
 
5
5
  from digitalhub.entities._base.context.entity import ContextEntity
6
- from digitalhub.entities._operations.processor import processor
6
+ from digitalhub.entities._processors.context import context_processor
7
7
 
8
8
  if typing.TYPE_CHECKING:
9
9
  from digitalhub.entities._base.entity.metadata import Metadata
@@ -25,4 +25,4 @@ class UnversionedEntity(ContextEntity):
25
25
  super().__init__(project, kind, metadata, spec, status, user)
26
26
  self.id = uuid
27
27
  self.name = uuid
28
- self.key = processor.build_context_entity_key(project, self.ENTITY_TYPE, kind, uuid)
28
+ self.key = context_processor.build_context_entity_key(project, self.ENTITY_TYPE, kind, uuid)
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import typing
4
4
 
5
5
  from digitalhub.entities._base.context.entity import ContextEntity
6
- from digitalhub.entities._operations.processor import processor
6
+ from digitalhub.entities._processors.context import context_processor
7
7
 
8
8
  if typing.TYPE_CHECKING:
9
9
  from digitalhub.entities._base.entity.metadata import Metadata
@@ -26,4 +26,4 @@ class VersionedEntity(ContextEntity):
26
26
  super().__init__(project, kind, metadata, spec, status, user)
27
27
  self.name = name
28
28
  self.id = uuid
29
- self.key = processor.build_context_entity_key(project, self.ENTITY_TYPE, kind, name, uuid)
29
+ self.key = context_processor.build_context_entity_key(project, self.ENTITY_TYPE, kind, name, uuid)
@@ -73,6 +73,7 @@ class BackendOperations(Enum):
73
73
 
74
74
  CREATE = "create"
75
75
  READ = "read"
76
+ READ_ALL_VERSIONS = "read_all_versions"
76
77
  UPDATE = "update"
77
78
  DELETE = "delete"
78
79
  LIST = "list"
@@ -84,6 +85,7 @@ class BackendOperations(Enum):
84
85
  LOGS = "logs"
85
86
  SEARCH = "search"
86
87
  SHARE = "share"
88
+ METRICS = "metrics"
87
89
 
88
90
 
89
91
  class EntityKinds(Enum):
@@ -0,0 +1,164 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Union
4
+
5
+ from pydantic import BaseModel, ValidationError
6
+
7
+ MetricType = Union[float, int, list[Union[float, int]]]
8
+
9
+
10
+ class Metric(BaseModel):
11
+ """
12
+ Metric.
13
+ """
14
+
15
+ value: MetricType
16
+
17
+
18
+ def validate_metric_value(value: Any) -> MetricType:
19
+ """
20
+ Validate metric value.
21
+
22
+ Parameters
23
+ ----------
24
+ value : Any
25
+ The value to validate.
26
+
27
+ Returns
28
+ -------
29
+ MetricType
30
+ The validated value.
31
+ """
32
+ try:
33
+ return Metric(value=value).value
34
+ except ValidationError as e:
35
+ raise ValueError("Invalid metric value. Must be a list of floats or ints or a float or an int.") from e
36
+
37
+
38
+ def set_metrics(
39
+ metrics: dict[str, MetricType],
40
+ key: str,
41
+ value: Any,
42
+ overwrite: bool,
43
+ single_value: bool,
44
+ ) -> dict[str, MetricType]:
45
+ """
46
+ Set metric value.
47
+
48
+ Parameters
49
+ ----------
50
+ metrics : dict[str, MetricType]
51
+ The metrics dictionary.
52
+ key : str
53
+ The key of the entity.
54
+ value : Any
55
+ The value to set.
56
+ overwrite : bool
57
+ Whether to overwrite the metric.
58
+
59
+ Returns
60
+ -------
61
+ dict[str, MetricType]
62
+ The metrics dictionary.
63
+ """
64
+ if isinstance(value, list):
65
+ return handle_metric_list(metrics, key, value, overwrite)
66
+ elif single_value:
67
+ return handle_metric_single(metrics, key, value, overwrite)
68
+ return handle_metric_list_append(metrics, key, value, overwrite)
69
+
70
+
71
+ def handle_metric_single(
72
+ metrics: dict[str, MetricType],
73
+ key: str,
74
+ value: float | int,
75
+ overwrite: bool,
76
+ ) -> dict:
77
+ """
78
+ Handle metric single value.
79
+
80
+ Parameters
81
+ ----------
82
+ metrics : dict[str, MetricType]
83
+ Metrics dictionary.
84
+ key : str
85
+ Key of the metric.
86
+ value : float
87
+ Value of the metric.
88
+ overwrite : bool
89
+ If True, overwrite existing metric.
90
+
91
+ Returns
92
+ -------
93
+ dict
94
+ Metrics dictionary.
95
+ """
96
+ if key not in metrics or overwrite:
97
+ metrics[key] = value
98
+ return metrics
99
+
100
+
101
+ def handle_metric_list_append(
102
+ metrics: dict[str, MetricType],
103
+ key: str,
104
+ value: float | int,
105
+ overwrite: bool,
106
+ ) -> dict:
107
+ """
108
+ Handle metric list append.
109
+
110
+ Parameters
111
+ ----------
112
+ metrics : dict[str, MetricType]
113
+ Metrics dictionary.
114
+ key : str
115
+ Key of the metric.
116
+ value : float
117
+ Value of the metric.
118
+ overwrite : bool
119
+ If True, overwrite existing metric.
120
+
121
+ Returns
122
+ -------
123
+ dict
124
+ Metrics dictionary.
125
+ """
126
+ if key not in metrics or overwrite:
127
+ metrics[key] = [value]
128
+ elif isinstance(metrics[key], list):
129
+ metrics[key].append(value)
130
+ else:
131
+ metrics[key] = [metrics[key], value]
132
+ return metrics
133
+
134
+
135
+ def handle_metric_list(
136
+ metrics: dict[str, MetricType],
137
+ key: str,
138
+ value: list[int | float],
139
+ overwrite: bool,
140
+ ) -> dict:
141
+ """
142
+ Handle metric list.
143
+
144
+ Parameters
145
+ ----------
146
+ metrics : dict[str, MetricType]
147
+ Metrics dictionary.
148
+ key : str
149
+ Key of the metric.
150
+ value : list[int | float]
151
+ Value of the metric.
152
+ overwrite : bool
153
+ If True, overwrite existing metric.
154
+
155
+ Returns
156
+ -------
157
+ dict
158
+ Metrics dictionary.
159
+ """
160
+ if key not in metrics or overwrite:
161
+ metrics[key] = value
162
+ else:
163
+ metrics[key].extend(value)
164
+ return metrics
@@ -0,0 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Union
4
+
5
+ MetricType = Union[float, int, list[Union[float, int]]]
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from digitalhub.entities._commons.enums import EntityTypes
4
4
 
5
5
 
6
- def parse_entity_key(key: str) -> tuple[str]:
6
+ def parse_entity_key(key: str) -> tuple[str, str, str, str | None, str]:
7
7
  """
8
8
  Parse the entity key. Returns project, entity type, kind, name and uuid.
9
9
 
@@ -14,7 +14,7 @@ def parse_entity_key(key: str) -> tuple[str]:
14
14
 
15
15
  Returns
16
16
  -------
17
- tuple[str]
17
+ tuple[str, str, str, str | None, str]
18
18
  Project, entity type, kind, name and uuid.
19
19
  """
20
20
  try: