digitalhub 0.8.1__py3-none-any.whl → 0.9.0b0__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 (128) hide show
  1. digitalhub/__init__.py +19 -2
  2. digitalhub/client/_base/api_builder.py +16 -0
  3. digitalhub/client/_base/client.py +31 -0
  4. digitalhub/client/api.py +2 -38
  5. digitalhub/client/dhcore/api_builder.py +100 -0
  6. digitalhub/client/dhcore/client.py +77 -24
  7. digitalhub/client/dhcore/enums.py +26 -0
  8. digitalhub/client/dhcore/env.py +2 -2
  9. digitalhub/client/dhcore/utils.py +17 -17
  10. digitalhub/client/local/api_builder.py +100 -0
  11. digitalhub/client/local/client.py +20 -0
  12. digitalhub/context/api.py +3 -38
  13. digitalhub/context/builder.py +10 -23
  14. digitalhub/context/context.py +20 -92
  15. digitalhub/entities/_base/context/entity.py +30 -22
  16. digitalhub/entities/_base/entity/_constructors/metadata.py +12 -1
  17. digitalhub/entities/_base/entity/_constructors/name.py +1 -1
  18. digitalhub/entities/_base/entity/_constructors/spec.py +1 -1
  19. digitalhub/entities/_base/entity/_constructors/status.py +3 -2
  20. digitalhub/entities/_base/entity/builder.py +6 -1
  21. digitalhub/entities/_base/entity/entity.py +30 -10
  22. digitalhub/entities/_base/entity/metadata.py +22 -0
  23. digitalhub/entities/_base/entity/spec.py +7 -2
  24. digitalhub/entities/_base/executable/entity.py +8 -8
  25. digitalhub/entities/_base/material/entity.py +48 -16
  26. digitalhub/entities/_base/material/status.py +0 -31
  27. digitalhub/entities/_base/material/utils.py +106 -0
  28. digitalhub/entities/_base/project/entity.py +341 -0
  29. digitalhub/entities/_base/unversioned/entity.py +1 -23
  30. digitalhub/entities/_base/versioned/entity.py +0 -25
  31. digitalhub/entities/_commons/enums.py +103 -0
  32. digitalhub/entities/_commons/utils.py +83 -0
  33. digitalhub/entities/_operations/processor.py +1747 -0
  34. digitalhub/entities/artifact/_base/builder.py +1 -1
  35. digitalhub/entities/artifact/_base/entity.py +1 -1
  36. digitalhub/entities/artifact/artifact/builder.py +2 -1
  37. digitalhub/entities/artifact/crud.py +46 -29
  38. digitalhub/entities/artifact/utils.py +62 -0
  39. digitalhub/entities/dataitem/_base/builder.py +1 -1
  40. digitalhub/entities/dataitem/_base/entity.py +6 -6
  41. digitalhub/entities/dataitem/crud.py +50 -66
  42. digitalhub/entities/dataitem/dataitem/builder.py +2 -1
  43. digitalhub/entities/dataitem/iceberg/builder.py +2 -1
  44. digitalhub/entities/dataitem/table/builder.py +2 -1
  45. digitalhub/entities/dataitem/table/entity.py +5 -10
  46. digitalhub/entities/dataitem/table/models.py +4 -5
  47. digitalhub/entities/dataitem/utils.py +137 -0
  48. digitalhub/entities/function/_base/builder.py +1 -1
  49. digitalhub/entities/function/_base/entity.py +5 -1
  50. digitalhub/entities/function/crud.py +36 -17
  51. digitalhub/entities/model/_base/builder.py +1 -1
  52. digitalhub/entities/model/_base/entity.py +1 -1
  53. digitalhub/entities/model/crud.py +46 -29
  54. digitalhub/entities/model/huggingface/builder.py +2 -1
  55. digitalhub/entities/model/huggingface/spec.py +4 -2
  56. digitalhub/entities/model/mlflow/builder.py +2 -1
  57. digitalhub/entities/model/mlflow/models.py +17 -9
  58. digitalhub/entities/model/mlflow/spec.py +6 -1
  59. digitalhub/entities/model/mlflow/utils.py +4 -2
  60. digitalhub/entities/model/model/builder.py +2 -1
  61. digitalhub/entities/model/sklearn/builder.py +2 -1
  62. digitalhub/entities/model/utils.py +62 -0
  63. digitalhub/entities/project/_base/builder.py +2 -2
  64. digitalhub/entities/project/_base/entity.py +82 -272
  65. digitalhub/entities/project/crud.py +110 -91
  66. digitalhub/entities/project/utils.py +35 -0
  67. digitalhub/entities/run/_base/builder.py +3 -1
  68. digitalhub/entities/run/_base/entity.py +52 -54
  69. digitalhub/entities/run/_base/spec.py +11 -7
  70. digitalhub/entities/run/crud.py +35 -17
  71. digitalhub/entities/secret/_base/builder.py +2 -2
  72. digitalhub/entities/secret/_base/entity.py +4 -10
  73. digitalhub/entities/secret/crud.py +36 -21
  74. digitalhub/entities/task/_base/builder.py +14 -14
  75. digitalhub/entities/task/_base/entity.py +6 -6
  76. digitalhub/entities/task/_base/models.py +29 -6
  77. digitalhub/entities/task/_base/spec.py +44 -13
  78. digitalhub/entities/task/_base/utils.py +18 -0
  79. digitalhub/entities/task/crud.py +35 -15
  80. digitalhub/entities/workflow/_base/builder.py +1 -1
  81. digitalhub/entities/workflow/_base/entity.py +14 -6
  82. digitalhub/entities/workflow/crud.py +36 -17
  83. digitalhub/factory/utils.py +1 -1
  84. digitalhub/readers/_base/reader.py +2 -2
  85. digitalhub/readers/_commons/enums.py +13 -0
  86. digitalhub/readers/api.py +3 -2
  87. digitalhub/readers/factory.py +12 -6
  88. digitalhub/readers/pandas/reader.py +20 -8
  89. digitalhub/runtimes/_base.py +0 -7
  90. digitalhub/stores/_base/store.py +53 -9
  91. digitalhub/stores/builder.py +5 -5
  92. digitalhub/stores/local/store.py +37 -2
  93. digitalhub/stores/remote/store.py +25 -3
  94. digitalhub/stores/s3/store.py +34 -7
  95. digitalhub/stores/sql/store.py +112 -45
  96. digitalhub/utils/exceptions.py +6 -0
  97. digitalhub/utils/file_utils.py +60 -2
  98. digitalhub/utils/generic_utils.py +45 -4
  99. digitalhub/utils/io_utils.py +18 -0
  100. digitalhub/utils/uri_utils.py +153 -15
  101. {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/METADATA +2 -2
  102. {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/RECORD +110 -113
  103. test/testkfp.py +4 -1
  104. digitalhub/datastores/_base/datastore.py +0 -85
  105. digitalhub/datastores/api.py +0 -37
  106. digitalhub/datastores/builder.py +0 -110
  107. digitalhub/datastores/local/datastore.py +0 -50
  108. digitalhub/datastores/remote/__init__.py +0 -0
  109. digitalhub/datastores/remote/datastore.py +0 -31
  110. digitalhub/datastores/s3/__init__.py +0 -0
  111. digitalhub/datastores/s3/datastore.py +0 -46
  112. digitalhub/datastores/sql/__init__.py +0 -0
  113. digitalhub/datastores/sql/datastore.py +0 -68
  114. digitalhub/entities/_base/api_utils.py +0 -620
  115. digitalhub/entities/_base/crud.py +0 -468
  116. digitalhub/entities/function/_base/models.py +0 -118
  117. digitalhub/entities/utils/__init__.py +0 -0
  118. digitalhub/entities/utils/api.py +0 -346
  119. digitalhub/entities/utils/entity_types.py +0 -19
  120. digitalhub/entities/utils/state.py +0 -31
  121. digitalhub/entities/utils/utils.py +0 -202
  122. /digitalhub/{context → entities/_base/project}/__init__.py +0 -0
  123. /digitalhub/{datastores → entities/_commons}/__init__.py +0 -0
  124. /digitalhub/{datastores/_base → entities/_operations}/__init__.py +0 -0
  125. /digitalhub/{datastores/local → readers/_commons}/__init__.py +0 -0
  126. {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/LICENSE.txt +0 -0
  127. {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/WHEEL +0 -0
  128. {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from pydantic import BaseModel, Field, ConfigDict
4
+
3
5
  from digitalhub.entities._base._base.entity import Base
6
+ from digitalhub.entities._commons.enums import Relationship
4
7
 
5
8
 
6
9
  class Metadata(Base):
@@ -24,6 +27,7 @@ class Metadata(Base):
24
27
  updated: str | None = None,
25
28
  updated_by: str | None = None,
26
29
  embedded: bool | None = None,
30
+ relationships: list[dict] | None = None,
27
31
  ref: str | None = None,
28
32
  **kwargs,
29
33
  ) -> None:
@@ -37,6 +41,7 @@ class Metadata(Base):
37
41
  self.created_by = created_by
38
42
  self.updated_by = updated_by
39
43
  self.embedded = embedded
44
+ self.relationships = relationships
40
45
  self.ref = ref
41
46
 
42
47
  self._any_setter(**kwargs)
@@ -57,3 +62,20 @@ class Metadata(Base):
57
62
  An entity metadata object.
58
63
  """
59
64
  return cls(**obj)
65
+
66
+
67
+ class RelationshipValidator(BaseModel):
68
+ """
69
+ A class representing the relationship of an entity.
70
+ """
71
+
72
+ model_config = ConfigDict(use_enum_values=True)
73
+
74
+ type_: Relationship = Field(default=None, alias="type")
75
+ """The type of relationship."""
76
+
77
+ source: str = None
78
+ """The source entity."""
79
+
80
+ dest: str = None
81
+ """The target entity."""
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from pydantic import BaseModel
3
+ from pydantic import BaseModel, ConfigDict
4
4
 
5
5
  from digitalhub.entities._base._base.entity import Base
6
6
 
@@ -30,7 +30,7 @@ class Spec(Base):
30
30
  return cls(**obj)
31
31
 
32
32
 
33
- class SpecValidator(BaseModel, extra="ignore"):
33
+ class SpecValidator(BaseModel):
34
34
  """
35
35
  A class representing the parameters of an entity.
36
36
  This base class is used to define the parameters of an entity
@@ -38,6 +38,11 @@ class SpecValidator(BaseModel, extra="ignore"):
38
38
  to the constructor.
39
39
  """
40
40
 
41
+ model_config = ConfigDict(extra="ignore", use_enum_values=True)
42
+
43
+ def to_dict(self) -> dict:
44
+ return self.model_dump(by_alias=True, exclude_none=True)
45
+
41
46
 
42
47
  class MaterialSpec(Spec):
43
48
  """
@@ -2,11 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  import typing
4
4
 
5
- from digitalhub.entities._base.api_utils import list_entity_api_ctx
6
5
  from digitalhub.entities._base.versioned.entity import VersionedEntity
6
+ from digitalhub.entities._commons.enums import EntityTypes
7
+ from digitalhub.entities._operations.processor import processor
7
8
  from digitalhub.entities.run.crud import delete_run, get_run, list_runs
8
9
  from digitalhub.entities.task.crud import delete_task
9
- from digitalhub.entities.utils.entity_types import EntityTypes
10
10
  from digitalhub.factory.api import build_entity_from_dict, build_entity_from_params
11
11
  from digitalhub.utils.exceptions import EntityAlreadyExistsError, EntityError
12
12
 
@@ -141,7 +141,7 @@ class ExecutableEntity(VersionedEntity):
141
141
 
142
142
  # Override kwargs
143
143
  kwargs["project"] = self.project
144
- kwargs["function"] = self._get_executable_string()
144
+ kwargs[self.ENTITY_TYPE] = self._get_executable_string()
145
145
  kwargs["kind"] = task_kind
146
146
 
147
147
  # Create object instance
@@ -176,7 +176,7 @@ class ExecutableEntity(VersionedEntity):
176
176
  resp = self._get_task_from_backend(kind)
177
177
  if not resp:
178
178
  raise EntityError(f"Task {kind} is not created")
179
- self._tasks[kind] = build_entity_from_dict(resp[0])
179
+ self._tasks[kind] = resp[0]
180
180
  return self._tasks[kind]
181
181
 
182
182
  def update_task(self, kind: str, **kwargs) -> Task:
@@ -203,7 +203,7 @@ class ExecutableEntity(VersionedEntity):
203
203
  # Update kwargs
204
204
  kwargs["project"] = self.project
205
205
  kwargs["kind"] = kind
206
- kwargs["function"] = self._get_executable_string()
206
+ kwargs[self.ENTITY_TYPE] = self._get_executable_string()
207
207
  kwargs["uuid"] = self._tasks[kind].id
208
208
 
209
209
  # Update task
@@ -246,8 +246,8 @@ class ExecutableEntity(VersionedEntity):
246
246
  list
247
247
  Response from backend.
248
248
  """
249
- params = {"function": self._get_executable_string(), "kind": kind}
250
- return list_entity_api_ctx(self.project, EntityTypes.TASK.value, params=params)
249
+ params = {self.ENTITY_TYPE: self._get_executable_string(), "kind": kind}
250
+ return 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
  """
@@ -370,7 +370,7 @@ class ExecutableEntity(VersionedEntity):
370
370
  """
371
371
  if kwargs is None:
372
372
  kwargs = {}
373
- kwargs["params"] = {"function": self._get_executable_string()}
373
+ kwargs["params"] = {self.ENTITY_TYPE: self._get_executable_string()}
374
374
  return list_runs(self.project, **kwargs)
375
375
 
376
376
  def delete_run(
@@ -3,8 +3,8 @@ from __future__ import annotations
3
3
  import typing
4
4
  from pathlib import Path
5
5
 
6
- from digitalhub.entities._base.api_utils import files_info_get_api, files_info_put_api
7
6
  from digitalhub.entities._base.versioned.entity import VersionedEntity
7
+ from digitalhub.entities._operations.processor import processor
8
8
  from digitalhub.stores.api import get_store
9
9
 
10
10
  if typing.TYPE_CHECKING:
@@ -48,23 +48,20 @@ class MaterialEntity(VersionedEntity):
48
48
  MaterialEntity
49
49
  Entity saved.
50
50
  """
51
- obj = self.to_dict()
52
-
51
+ # Evaluate files info list length
53
52
  files = None
54
53
  if self.status.files is not None and len(self.status.files) > 5 and not self._context().local:
55
- files = obj["status"].pop("files")
54
+ files = self.status.files
55
+ self.status.files = []
56
56
 
57
- if not update:
58
- new_obj: MaterialEntity = self._save(obj)
59
- else:
60
- new_obj: MaterialEntity = self._update(obj)
57
+ obj: MaterialEntity = super().save(update)
61
58
 
62
59
  # Handle files info
63
60
  if files is not None:
64
- files_info_put_api(self.project, self.ENTITY_TYPE, self.id, files)
65
- self.status.add_files_info(files)
61
+ processor.update_files_info(self.project, self.ENTITY_TYPE, self.id, files)
62
+ self.add_files_info(files)
66
63
 
67
- return new_obj
64
+ return obj
68
65
 
69
66
  ##############################
70
67
  # I/O Methods
@@ -81,7 +78,7 @@ class MaterialEntity(VersionedEntity):
81
78
  List of file paths.
82
79
  """
83
80
  store = get_store(self.spec.path)
84
- paths = self.status.get_file_paths()
81
+ paths = self.get_file_paths()
85
82
  dst = store._build_temp()
86
83
  return store.download(self.spec.path, dst=dst, src=paths)
87
84
 
@@ -130,7 +127,7 @@ class MaterialEntity(VersionedEntity):
130
127
  dataitem/data.csv
131
128
  """
132
129
  store = get_store(self.spec.path)
133
- paths = self.status.get_file_paths()
130
+ paths = self.get_file_paths()
134
131
 
135
132
  if destination is None:
136
133
  dst = self._context().root / self.ENTITY_TYPE
@@ -174,6 +171,41 @@ class MaterialEntity(VersionedEntity):
174
171
  files_info = store.get_file_info(paths)
175
172
  self._update_files_info(files_info)
176
173
 
174
+ ##############################
175
+ # Public Helpers
176
+ ##############################
177
+
178
+ def add_files_info(self, files: list[dict]) -> None:
179
+ """
180
+ Add a file to the status.
181
+
182
+ Parameters
183
+ ----------
184
+ files : list[dict]
185
+ Files to add.
186
+
187
+ Returns
188
+ -------
189
+ None
190
+ """
191
+ path_list = self.get_file_paths()
192
+ for f in files:
193
+ if f.get("path") not in path_list:
194
+ self.status.files.append(f)
195
+
196
+ def get_file_paths(self) -> list[str]:
197
+ """
198
+ Get the paths of the files in the status.
199
+
200
+ Returns
201
+ -------
202
+ list[str]
203
+ Paths of the files in the status.
204
+ """
205
+ if self.status.files is None:
206
+ self.status.files = []
207
+ return [f.get("path") for f in self.status.files]
208
+
177
209
  ##############################
178
210
  # Private Helpers
179
211
  ##############################
@@ -194,7 +226,7 @@ class MaterialEntity(VersionedEntity):
194
226
  if files_info is None:
195
227
  return
196
228
  self.refresh()
197
- self.status.add_files_info(files_info)
229
+ self.add_files_info(files_info)
198
230
  self.save(update=True)
199
231
 
200
232
  def _get_files_info(self) -> None:
@@ -206,9 +238,9 @@ class MaterialEntity(VersionedEntity):
206
238
  None
207
239
  """
208
240
  if not self._context().local and not self.status.files:
209
- files = files_info_get_api(
241
+ files = processor.read_files_info(
210
242
  project=self.project,
211
243
  entity_type=self.ENTITY_TYPE,
212
244
  entity_id=self.id,
213
245
  )
214
- self.status.add_files_info(files)
246
+ self.add_files_info(files)
@@ -15,35 +15,4 @@ class MaterialStatus(Status):
15
15
  files: list[dict] | None = None,
16
16
  ) -> None:
17
17
  super().__init__(state, message)
18
- if files is None:
19
- files = []
20
18
  self.files = files
21
-
22
- def add_files_info(self, files: list[dict]) -> None:
23
- """
24
- Add a file to the status.
25
-
26
- Parameters
27
- ----------
28
- files : list[dict]
29
- Files to add.
30
-
31
- Returns
32
- -------
33
- None
34
- """
35
- path_list = self.get_file_paths()
36
- for f in files:
37
- if f.get("path") not in path_list:
38
- self.files.append(f)
39
-
40
- def get_file_paths(self) -> list[str]:
41
- """
42
- Get the paths of the files in the status.
43
-
44
- Returns
45
- -------
46
- list[str]
47
- Paths of the files in the status.
48
- """
49
- return [f.get("path") for f in self.files]
@@ -0,0 +1,106 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ from digitalhub.utils.file_utils import eval_zip_type
6
+ from digitalhub.utils.s3_utils import get_s3_bucket
7
+ from digitalhub.utils.uri_utils import S3Schemes, has_local_scheme
8
+
9
+
10
+ def eval_local_source(source: str | list[str]) -> None:
11
+ """
12
+ Evaluate if source is local.
13
+
14
+ Parameters
15
+ ----------
16
+ source : str | list[str]
17
+ Source(s).
18
+
19
+ Returns
20
+ -------
21
+ None
22
+ """
23
+ if isinstance(source, list):
24
+ if not source:
25
+ raise ValueError("Empty list of sources.")
26
+ source_is_local = all(has_local_scheme(s) for s in source)
27
+ for s in source:
28
+ if Path(s).is_dir():
29
+ raise ValueError(f"Invalid source path: {s}. List of paths must be list of files, not directories.")
30
+ else:
31
+ source_is_local = has_local_scheme(source)
32
+
33
+ if not source_is_local:
34
+ raise ValueError("Invalid source path. Source must be a local path.")
35
+
36
+
37
+ def eval_zip_sources(source: str | list[str]) -> str:
38
+ """
39
+ Evaluate zip sources.
40
+
41
+ Parameters
42
+ ----------
43
+ source : str | list[str]
44
+ Source(s).
45
+
46
+ Returns
47
+ -------
48
+ str
49
+ S3Schemes.
50
+ """
51
+ if isinstance(source, list):
52
+ if len(source) > 1:
53
+ return S3Schemes.S3.value
54
+ path = source[0]
55
+ else:
56
+ if Path(source).is_dir():
57
+ return S3Schemes.S3.value
58
+ path = source
59
+
60
+ if not eval_zip_type(path):
61
+ return S3Schemes.S3.value
62
+ return S3Schemes.ZIP_S3.value
63
+
64
+
65
+ def build_log_path_from_source(
66
+ project: str,
67
+ entity_type: str,
68
+ name: str,
69
+ uuid: str,
70
+ source: str | list[str],
71
+ ) -> str:
72
+ """
73
+ Build log path.
74
+
75
+ Parameters
76
+ ----------
77
+ project : str
78
+ Project name.
79
+ entity_type : str
80
+ Entity type.
81
+ name : str
82
+ Object name.
83
+ uuid : str
84
+ Object UUID.
85
+ source : str | list[str]
86
+ Source(s).
87
+
88
+ Returns
89
+ -------
90
+ str
91
+ Log path.
92
+ """
93
+ scheme = eval_zip_sources(source)
94
+ path = f"{scheme}://{get_s3_bucket()}/{project}/{entity_type}/{name}/{uuid}"
95
+
96
+ if isinstance(source, list) and len(source) >= 1:
97
+ if len(source) > 1:
98
+ path += "/"
99
+ else:
100
+ path += f"/{Path(source[0]).name}"
101
+ elif Path(source).is_dir():
102
+ path += "/"
103
+ elif Path(source).is_file():
104
+ path += f"/{Path(source).name}"
105
+
106
+ return path