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
@@ -4,53 +4,41 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- import typing
8
-
9
- from digitalhub.stores.client.dhcore.client import ClientDHCore
10
- from digitalhub.stores.client.local.client import ClientLocal
11
-
12
- if typing.TYPE_CHECKING:
13
- from digitalhub.stores.client._base.client import Client
7
+ from digitalhub.stores.client.client import Client
14
8
 
15
9
 
16
10
  class ClientBuilder:
17
11
  """
18
- Client builder class.
19
-
20
- This class is used to create two possible client instances:
21
- Local and DHCore.
22
- It saves the client instances in the class attributes using
23
- singleton pattern.
12
+ Client builder class. Creates and returns client instance.
24
13
  """
25
14
 
26
15
  def __init__(self) -> None:
27
- self._local = None
28
- self._dhcore = None
16
+ self._client: Client = None
29
17
 
30
- def build(self, local: bool = False, config: dict | None = None) -> Client:
18
+ def build(self) -> Client:
31
19
  """
32
20
  Method to create a client instance.
33
21
 
34
- Parameters
35
- ----------
36
- local : bool, default False
37
- Whether to create a local client or not.
38
- config : dict, optional
39
- DHCore environment configuration.
40
-
41
22
  Returns
42
23
  -------
43
24
  Client
44
25
  Returns the client instance.
45
26
  """
46
- if local:
47
- if self._local is None:
48
- self._local = ClientLocal()
49
- return self._local
50
-
51
- if self._dhcore is None:
52
- self._dhcore = ClientDHCore(config)
53
- return self._dhcore
27
+ if self._client is None:
28
+ self._client = Client()
29
+ return self._client
54
30
 
55
31
 
56
32
  client_builder = ClientBuilder()
33
+
34
+
35
+ def get_client() -> Client:
36
+ """
37
+ Wrapper around ClientBuilder.build.
38
+
39
+ Returns
40
+ -------
41
+ Client
42
+ The client instance.
43
+ """
44
+ return client_builder.build()
@@ -0,0 +1,322 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from digitalhub.stores.client.api_builder import ClientApiBuilder
10
+ from digitalhub.stores.client.header_manager import HeaderManager
11
+ from digitalhub.stores.client.http_handler import HttpRequestHandler
12
+ from digitalhub.stores.client.key_builder import ClientKeyBuilder
13
+ from digitalhub.stores.client.params_builder import ClientParametersBuilder
14
+ from digitalhub.utils.exceptions import BackendError
15
+ from digitalhub.utils.generic_utils import dump_json
16
+
17
+
18
+ class Client:
19
+ """
20
+ DHCore client for remote DigitalHub Core backend communication.
21
+
22
+ Provides REST API communication with DigitalHub Core backend supporting
23
+ multiple authentication methods: Basic (username/password), OAuth2 (token
24
+ with refresh), and Personal Access Token exchange. Automatically handles
25
+ API version compatibility, pagination, token refresh, error parsing, and
26
+ JSON serialization.
27
+ """
28
+
29
+ def __init__(self) -> None:
30
+ # API, key and parameters builders
31
+ self._api_builder: ClientApiBuilder = ClientApiBuilder()
32
+ self._key_builder: ClientKeyBuilder = ClientKeyBuilder()
33
+ self._params_builder: ClientParametersBuilder = ClientParametersBuilder()
34
+
35
+ # HTTP request handling
36
+ self._http_handler = HttpRequestHandler()
37
+
38
+ ##############################
39
+ # CRUD methods
40
+ ##############################
41
+
42
+ def create_object(self, api: str, obj: Any, **kwargs) -> dict:
43
+ """
44
+ Create an object in DHCore via POST request.
45
+
46
+ Automatically sets Content-Type header and serializes object to JSON.
47
+
48
+ Parameters
49
+ ----------
50
+ api : str
51
+ API endpoint path for creating the object.
52
+ obj : Any
53
+ Object to create. Will be serialized to JSON.
54
+ **kwargs : dict
55
+ Additional HTTP request arguments.
56
+
57
+ Returns
58
+ -------
59
+ dict
60
+ Created object as returned by the backend.
61
+ """
62
+ kwargs = HeaderManager.set_json_content_type(**kwargs)
63
+ kwargs["data"] = dump_json(obj)
64
+ return self._http_handler.prepare_request("POST", api, **kwargs)
65
+
66
+ def read_object(self, api: str, **kwargs) -> dict:
67
+ """
68
+ Get an object from DHCore.
69
+
70
+ Sends a GET request to the DHCore backend to retrieve an existing object.
71
+
72
+ Parameters
73
+ ----------
74
+ api : str
75
+ API endpoint path for reading the object.
76
+ **kwargs : dict
77
+ Additional HTTP request arguments.
78
+
79
+ Returns
80
+ -------
81
+ dict
82
+ Retrieved object as returned by the backend.
83
+
84
+ Raises
85
+ ------
86
+ BackendError
87
+ If the backend returns an error response.
88
+ EntityNotExistsError
89
+ If the requested object does not exist.
90
+ """
91
+ return self._http_handler.prepare_request("GET", api, **kwargs)
92
+
93
+ def update_object(self, api: str, obj: Any, **kwargs) -> dict:
94
+ """
95
+ Update an object in DHCore via PUT request.
96
+
97
+ Automatically sets Content-Type header and serializes object to JSON.
98
+
99
+ Parameters
100
+ ----------
101
+ api : str
102
+ API endpoint path for updating the object.
103
+ obj : Any
104
+ Updated object data. Will be serialized to JSON.
105
+ **kwargs : dict
106
+ Additional HTTP request arguments.
107
+
108
+ Returns
109
+ -------
110
+ dict
111
+ Updated object as returned by the backend.
112
+ """
113
+ kwargs = HeaderManager.set_json_content_type(**kwargs)
114
+ kwargs["data"] = dump_json(obj)
115
+ return self._http_handler.prepare_request("PUT", api, **kwargs)
116
+
117
+ def delete_object(self, api: str, **kwargs) -> dict:
118
+ """
119
+ Delete an object from DHCore.
120
+
121
+ Sends DELETE request to remove an object. Wraps boolean responses
122
+ in {"deleted": True/False} dictionary.
123
+
124
+ Parameters
125
+ ----------
126
+ api : str
127
+ API endpoint path for deleting the object.
128
+ **kwargs : dict
129
+ Additional HTTP request arguments.
130
+
131
+ Returns
132
+ -------
133
+ dict
134
+ Deletion result from backend or {"deleted": bool} wrapper.
135
+ """
136
+ resp = self._http_handler.prepare_request("DELETE", api, **kwargs)
137
+ if isinstance(resp, bool):
138
+ resp = {"deleted": resp}
139
+ return resp
140
+
141
+ def list_objects(self, api: str, **kwargs) -> list[dict]:
142
+ """
143
+ List objects from DHCore with automatic pagination.
144
+
145
+ Sends GET requests to retrieve paginated objects, automatically handling
146
+ pagination (starting from page 0) until all objects are retrieved.
147
+
148
+ Parameters
149
+ ----------
150
+ api : str
151
+ API endpoint path for listing objects.
152
+ **kwargs : dict
153
+ Additional HTTP request arguments. Can include 'params' dict
154
+ with pagination parameters.
155
+
156
+ Returns
157
+ -------
158
+ list[dict]
159
+ List containing all objects from all pages.
160
+ """
161
+ kwargs = self._params_builder.set_pagination(partial=True, **kwargs)
162
+
163
+ objects = []
164
+ while True:
165
+ resp = self._http_handler.prepare_request("GET", api, **kwargs)
166
+ contents = resp["content"]
167
+ total_pages = resp["totalPages"]
168
+ objects.extend(contents)
169
+ if not contents or self._params_builder.read_page_number(**kwargs) >= (total_pages - 1):
170
+ break
171
+ self._params_builder.increment_page_number(**kwargs)
172
+
173
+ return objects
174
+
175
+ def list_first_object(self, api: str, **kwargs) -> dict:
176
+ """
177
+ Get the first object from a DHCore list.
178
+
179
+ Retrieves the first object by calling list_objects and returning
180
+ the first item.
181
+
182
+ Parameters
183
+ ----------
184
+ api : str
185
+ API endpoint path for listing objects.
186
+ **kwargs : dict
187
+ Additional HTTP request arguments.
188
+
189
+ Returns
190
+ -------
191
+ dict
192
+ First object from the list.
193
+ """
194
+ try:
195
+ return self.list_objects(api, **kwargs)[0]
196
+ except IndexError:
197
+ raise BackendError("No object found.")
198
+
199
+ def search_objects(self, api: str, **kwargs) -> list[dict]:
200
+ """
201
+ Search objects from DHCore using Solr capabilities.
202
+
203
+ Performs search query with pagination and removes search highlights.
204
+ Sets default pagination (page=0, size=10) and sorting (metadata.updated DESC)
205
+ if not provided.
206
+
207
+ Parameters
208
+ ----------
209
+ api : str
210
+ API endpoint path for searching objects (usually Solr search).
211
+ **kwargs : dict
212
+ Additional HTTP request arguments including search parameters,
213
+ filters, and pagination options.
214
+
215
+ Returns
216
+ -------
217
+ list[dict]
218
+ List of matching objects with search highlights removed.
219
+ """
220
+ kwargs = self._params_builder.set_pagination(**kwargs)
221
+ objects_with_highlights: list[dict] = []
222
+ while True:
223
+ resp = self._http_handler.prepare_request("GET", api, **kwargs)
224
+ contents = resp["content"]
225
+ total_pages = resp["totalPages"]
226
+ objects_with_highlights.extend(contents)
227
+ if not contents or self._params_builder.read_page_number(**kwargs) >= (total_pages - 1):
228
+ break
229
+ self._params_builder.increment_page_number(**kwargs)
230
+
231
+ objects = []
232
+ for obj in objects_with_highlights:
233
+ obj.pop("highlights", None)
234
+ objects.append(obj)
235
+
236
+ return objects
237
+
238
+ ##############################
239
+ # Build methods
240
+ ##############################
241
+
242
+ def build_api(self, category: str, operation: str, **kwargs) -> str:
243
+ """
244
+ Build the API for the client.
245
+
246
+ Parameters
247
+ ----------
248
+ category : str
249
+ API category.
250
+ operation : str
251
+ API operation.
252
+ **kwargs : dict
253
+ Additional parameters.
254
+
255
+ Returns
256
+ -------
257
+ str
258
+ API formatted.
259
+ """
260
+ return self._api_builder.build_api(category, operation, **kwargs)
261
+
262
+ def build_key(self, category: str, *args, **kwargs) -> str:
263
+ """
264
+ Build the key for the client.
265
+
266
+ Parameters
267
+ ----------
268
+ category : str
269
+ Key category.
270
+ *args : tuple
271
+ Additional arguments.
272
+ **kwargs : dict
273
+ Additional parameters.
274
+
275
+ Returns
276
+ -------
277
+ str
278
+ Key formatted.
279
+ """
280
+ return self._key_builder.build_key(category, *args, **kwargs)
281
+
282
+ def build_parameters(self, category: str, operation: str, **kwargs) -> dict:
283
+ """
284
+ Build the parameters for the client call.
285
+
286
+ Parameters
287
+ ----------
288
+ category : str
289
+ API category.
290
+ operation : str
291
+ API operation.
292
+ **kwargs : dict
293
+ Parameters to build.
294
+
295
+ Returns
296
+ -------
297
+ dict
298
+ Parameters formatted.
299
+ """
300
+ return self._params_builder.build_parameters(category, operation, **kwargs)
301
+
302
+ ##############################
303
+ # Utility methods
304
+ ##############################
305
+
306
+ def refresh_token(self) -> None:
307
+ """
308
+ Manually trigger OAuth2 token refresh.
309
+ """
310
+ self._http_handler.refresh_token()
311
+
312
+ def get_credentials_and_config(self) -> dict:
313
+ """
314
+ Get current authentication credentials and configuration.
315
+ Eventually refreshes token if expired.
316
+
317
+ Returns
318
+ -------
319
+ dict
320
+ Current authentication credentials and configuration.
321
+ """
322
+ return self._http_handler.get_credentials_and_config()