digitalhub 0.14.0b3__py3-none-any.whl → 0.14.0b4__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 (38) hide show
  1. digitalhub/entities/_base/executable/entity.py +160 -58
  2. digitalhub/entities/_base/material/entity.py +4 -0
  3. digitalhub/entities/_base/material/utils.py +28 -0
  4. digitalhub/entities/_commons/enums.py +0 -31
  5. digitalhub/entities/_constructors/_resources.py +151 -0
  6. digitalhub/entities/_constructors/name.py +18 -0
  7. digitalhub/entities/_processors/base/crud.py +1 -1
  8. digitalhub/entities/_processors/base/special_ops.py +1 -1
  9. digitalhub/entities/_processors/context/crud.py +25 -25
  10. digitalhub/entities/_processors/context/special_ops.py +1 -1
  11. digitalhub/entities/_processors/utils.py +2 -1
  12. digitalhub/entities/artifact/crud.py +37 -17
  13. digitalhub/entities/dataitem/crud.py +37 -13
  14. digitalhub/entities/dataitem/table/entity.py +3 -0
  15. digitalhub/entities/function/crud.py +39 -19
  16. digitalhub/entities/model/crud.py +37 -17
  17. digitalhub/entities/project/_base/entity.py +5 -5
  18. digitalhub/entities/project/crud.py +6 -20
  19. digitalhub/entities/run/_base/entity.py +1 -1
  20. digitalhub/entities/run/crud.py +54 -21
  21. digitalhub/entities/secret/crud.py +6 -20
  22. digitalhub/entities/task/crud.py +40 -25
  23. digitalhub/entities/trigger/crud.py +43 -19
  24. digitalhub/entities/workflow/crud.py +39 -16
  25. digitalhub/stores/client/_base/enums.py +39 -0
  26. digitalhub/stores/client/_base/key_builder.py +1 -1
  27. digitalhub/stores/client/_base/params_builder.py +48 -0
  28. digitalhub/stores/client/dhcore/api_builder.py +2 -1
  29. digitalhub/stores/client/dhcore/client.py +67 -55
  30. digitalhub/stores/client/dhcore/params_builder.py +130 -75
  31. digitalhub/stores/client/local/api_builder.py +1 -1
  32. digitalhub/stores/client/local/params_builder.py +18 -41
  33. digitalhub/stores/data/s3/store.py +8 -5
  34. {digitalhub-0.14.0b3.dist-info → digitalhub-0.14.0b4.dist-info}/METADATA +1 -1
  35. {digitalhub-0.14.0b3.dist-info → digitalhub-0.14.0b4.dist-info}/RECORD +38 -36
  36. {digitalhub-0.14.0b3.dist-info → digitalhub-0.14.0b4.dist-info}/WHEEL +0 -0
  37. {digitalhub-0.14.0b3.dist-info → digitalhub-0.14.0b4.dist-info}/licenses/AUTHORS +0 -0
  38. {digitalhub-0.14.0b3.dist-info → digitalhub-0.14.0b4.dist-info}/licenses/LICENSE +0 -0
@@ -75,7 +75,6 @@ def get_workflow(
75
75
  identifier: str,
76
76
  project: str | None = None,
77
77
  entity_id: str | None = None,
78
- **kwargs,
79
78
  ) -> Workflow:
80
79
  """
81
80
  Get object from backend.
@@ -88,8 +87,6 @@ def get_workflow(
88
87
  Project name.
89
88
  entity_id : str
90
89
  Entity ID.
91
- **kwargs : dict
92
- Parameters to pass to the API call.
93
90
 
94
91
  Returns
95
92
  -------
@@ -107,18 +104,16 @@ def get_workflow(
107
104
  >>> entity_id="my-workflow-id")
108
105
  """
109
106
  return context_processor.read_context_entity(
110
- identifier,
107
+ identifier=identifier,
111
108
  entity_type=ENTITY_TYPE,
112
109
  project=project,
113
110
  entity_id=entity_id,
114
- **kwargs,
115
111
  )
116
112
 
117
113
 
118
114
  def get_workflow_versions(
119
115
  identifier: str,
120
116
  project: str | None = None,
121
- **kwargs,
122
117
  ) -> list[Workflow]:
123
118
  """
124
119
  Get object versions from backend.
@@ -129,8 +124,6 @@ def get_workflow_versions(
129
124
  Entity key (store://...) or entity name.
130
125
  project : str
131
126
  Project name.
132
- **kwargs : dict
133
- Parameters to pass to the API call.
134
127
 
135
128
  Returns
136
129
  -------
@@ -147,14 +140,23 @@ def get_workflow_versions(
147
140
  >>> project="my-project")
148
141
  """
149
142
  return context_processor.read_context_entity_versions(
150
- identifier,
143
+ identifier=identifier,
151
144
  entity_type=ENTITY_TYPE,
152
145
  project=project,
153
- **kwargs,
154
146
  )
155
147
 
156
148
 
157
- def list_workflows(project: str, **kwargs) -> list[Workflow]:
149
+ def list_workflows(
150
+ project: str,
151
+ q: str | None = None,
152
+ name: str | None = None,
153
+ kind: str | None = None,
154
+ user: str | None = None,
155
+ state: str | None = None,
156
+ created: str | None = None,
157
+ updated: str | None = None,
158
+ version: str | None = None,
159
+ ) -> list[Workflow]:
158
160
  """
159
161
  List all latest version objects from backend.
160
162
 
@@ -162,8 +164,22 @@ def list_workflows(project: str, **kwargs) -> list[Workflow]:
162
164
  ----------
163
165
  project : str
164
166
  Project name.
165
- **kwargs : dict
166
- Parameters to pass to the API call.
167
+ q : str
168
+ Query string to filter objects.
169
+ name : str
170
+ Object name.
171
+ kind : str
172
+ Kind of the object.
173
+ user : str
174
+ User that created the object.
175
+ state : str
176
+ Object state.
177
+ created : str
178
+ Creation date filter.
179
+ updated : str
180
+ Update date filter.
181
+ version : str
182
+ Object version, default is latest.
167
183
 
168
184
  Returns
169
185
  -------
@@ -177,7 +193,14 @@ def list_workflows(project: str, **kwargs) -> list[Workflow]:
177
193
  return context_processor.list_context_entities(
178
194
  project=project,
179
195
  entity_type=ENTITY_TYPE,
180
- **kwargs,
196
+ q=q,
197
+ name=name,
198
+ kind=kind,
199
+ user=user,
200
+ state=state,
201
+ created=created,
202
+ updated=updated,
203
+ version=version,
181
204
  )
182
205
 
183
206
 
@@ -280,7 +303,8 @@ def delete_workflow(
280
303
  entity_id : str
281
304
  Entity ID.
282
305
  delete_all_versions : bool
283
- Delete all versions of the named entity. If True, use entity name instead of entity key as identifier.
306
+ Delete all versions of the named entity.
307
+ If True, use entity name instead of entity key as identifier.
284
308
  cascade : bool
285
309
  Cascade delete.
286
310
  **kwargs : dict
@@ -308,5 +332,4 @@ def delete_workflow(
308
332
  entity_id=entity_id,
309
333
  delete_all_versions=delete_all_versions,
310
334
  cascade=cascade,
311
- **kwargs,
312
335
  )
@@ -0,0 +1,39 @@
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 enum import Enum
8
+
9
+
10
+ class ApiCategories(Enum):
11
+ """
12
+ API categories.
13
+ """
14
+
15
+ BASE = "base"
16
+ CONTEXT = "context"
17
+
18
+
19
+ class BackendOperations(Enum):
20
+ """
21
+ Backend operations.
22
+ """
23
+
24
+ CREATE = "create"
25
+ READ = "read"
26
+ READ_ALL_VERSIONS = "read_all_versions"
27
+ UPDATE = "update"
28
+ DELETE = "delete"
29
+ DELETE_ALL_VERSIONS = "delete_all_versions"
30
+ LIST = "list"
31
+ LIST_FIRST = "list_first"
32
+ STOP = "stop"
33
+ RESUME = "resume"
34
+ DATA = "data"
35
+ FILES = "files"
36
+ LOGS = "logs"
37
+ SEARCH = "search"
38
+ SHARE = "share"
39
+ METRICS = "metrics"
@@ -6,7 +6,7 @@ from __future__ import annotations
6
6
 
7
7
  from abc import abstractmethod
8
8
 
9
- from digitalhub.entities._commons.enums import ApiCategories
9
+ from digitalhub.stores.client._base.enums import ApiCategories
10
10
 
11
11
 
12
12
  class ClientKeyBuilder:
@@ -5,6 +5,7 @@
5
5
  from __future__ import annotations
6
6
 
7
7
  from abc import abstractmethod
8
+ from typing import Any
8
9
 
9
10
 
10
11
  class ClientParametersBuilder:
@@ -32,3 +33,50 @@ class ClientParametersBuilder:
32
33
  dict
33
34
  The formatted parameters for the client call.
34
35
  """
36
+
37
+ @staticmethod
38
+ def _ensure_params(**kwargs) -> dict:
39
+ """
40
+ Initialize parameter dictionary with query parameters structure.
41
+
42
+ Ensures parameter dictionary has 'params' key for HTTP query parameters,
43
+ guaranteeing consistent structure for all parameter building methods.
44
+
45
+ Parameters
46
+ ----------
47
+ **kwargs : dict
48
+ Keyword arguments to format. May be empty or contain various
49
+ parameters for API operations.
50
+
51
+ Returns
52
+ -------
53
+ dict
54
+ Parameters dictionary with guaranteed 'params' key containing
55
+ empty dict if not already present.
56
+ """
57
+ if "params" not in kwargs:
58
+ kwargs["params"] = {}
59
+ return kwargs
60
+
61
+ @staticmethod
62
+ def _add_param(key: str, value: Any | None, **kwargs) -> dict:
63
+ """
64
+ Add a single query parameter to kwargs.
65
+
66
+ Parameters
67
+ ----------
68
+ key : str
69
+ Parameter key.
70
+ value : Any
71
+ Parameter value.
72
+ **kwargs : dict
73
+ Keyword arguments to format. May be empty or contain various
74
+ parameters for API operations.
75
+
76
+ Returns
77
+ -------
78
+ dict
79
+ Parameters dictionary with added key-value pair in 'params'.
80
+ """
81
+ kwargs["params"][key] = value
82
+ return kwargs
@@ -4,8 +4,8 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- from digitalhub.entities._commons.enums import ApiCategories, BackendOperations
8
7
  from digitalhub.stores.client._base.api_builder import ClientApiBuilder
8
+ from digitalhub.stores.client._base.enums import ApiCategories, BackendOperations
9
9
  from digitalhub.utils.exceptions import BackendError
10
10
 
11
11
  API_BASE = "/api/v1"
@@ -100,6 +100,7 @@ class ClientDHCoreApiBuilder(ClientApiBuilder):
100
100
  if operation in (
101
101
  BackendOperations.CREATE.value,
102
102
  BackendOperations.LIST.value,
103
+ BackendOperations.DELETE_ALL_VERSIONS.value,
103
104
  ):
104
105
  return f"{API_CONTEXT}/{project}/{entity_type}"
105
106
  elif operation in (
@@ -29,6 +29,9 @@ MAX_API_LEVEL = 20
29
29
  MIN_API_LEVEL = 14
30
30
  LIB_VERSION = 14
31
31
 
32
+ # Default timeout for requests (in seconds)
33
+ DEFAULT_TIMEOUT = 60
34
+
32
35
 
33
36
  class ClientDHCore(Client):
34
37
  """
@@ -73,13 +76,13 @@ class ClientDHCore(Client):
73
76
  super().__init__()
74
77
 
75
78
  # API builder
76
- self._api_builder = ClientDHCoreApiBuilder()
79
+ self._api_builder: ClientDHCoreApiBuilder = ClientDHCoreApiBuilder()
77
80
 
78
81
  # Key builder
79
- self._key_builder = ClientDHCoreKeyBuilder()
82
+ self._key_builder: ClientDHCoreKeyBuilder = ClientDHCoreKeyBuilder()
80
83
 
81
84
  # Parameters builder
82
- self._params_builder = ClientDHCoreParametersBuilder()
85
+ self._params_builder: ClientDHCoreParametersBuilder = ClientDHCoreParametersBuilder()
83
86
 
84
87
  # Error parser
85
88
  self._error_parser = ErrorParser()
@@ -118,9 +121,7 @@ class ClientDHCore(Client):
118
121
  ClientError
119
122
  If there are client-side configuration issues.
120
123
  """
121
- if "headers" not in kwargs:
122
- kwargs["headers"] = {}
123
- kwargs["headers"]["Content-Type"] = "application/json"
124
+ kwargs = self._set_application_json_header(**kwargs)
124
125
  kwargs["data"] = dump_json(obj)
125
126
  return self._prepare_call("POST", api, **kwargs)
126
127
 
@@ -178,9 +179,7 @@ class ClientDHCore(Client):
178
179
  EntityNotExistsError
179
180
  If the object to update does not exist.
180
181
  """
181
- if "headers" not in kwargs:
182
- kwargs["headers"] = {}
183
- kwargs["headers"]["Content-Type"] = "application/json"
182
+ kwargs = self._set_application_json_header(**kwargs)
184
183
  kwargs["data"] = dump_json(obj)
185
184
  return self._prepare_call("PUT", api, **kwargs)
186
185
 
@@ -240,22 +239,17 @@ class ClientDHCore(Client):
240
239
  BackendError
241
240
  If the backend returns an error response.
242
241
  """
243
- if "params" not in kwargs:
244
- kwargs["params"] = {}
245
-
246
- start_page = 0
247
- if "page" not in kwargs["params"]:
248
- kwargs["params"]["page"] = start_page
242
+ kwargs = self._params_builder.set_pagination(partial=True, **kwargs)
249
243
 
250
244
  objects = []
251
245
  while True:
252
246
  resp = self._prepare_call("GET", api, **kwargs)
253
247
  contents = resp["content"]
254
248
  total_pages = resp["totalPages"]
255
- if not contents or kwargs["params"]["page"] >= total_pages:
256
- break
257
249
  objects.extend(contents)
258
- kwargs["params"]["page"] += 1
250
+ if not contents or self._params_builder.read_page_number(**kwargs) >= (total_pages - 1):
251
+ break
252
+ self._params_builder.increment_page_number(**kwargs)
259
253
 
260
254
  return objects
261
255
 
@@ -314,29 +308,16 @@ class ClientDHCore(Client):
314
308
  BackendError
315
309
  If the backend returns an error response.
316
310
  """
317
- if "params" not in kwargs:
318
- kwargs["params"] = {}
319
-
320
- start_page = 0
321
- if "page" not in kwargs["params"]:
322
- kwargs["params"]["page"] = start_page
323
-
324
- if "size" not in kwargs["params"]:
325
- kwargs["params"]["size"] = 10
326
-
327
- # Add sorting
328
- if "sort" not in kwargs["params"]:
329
- kwargs["params"]["sort"] = "metadata.updated,DESC"
330
-
311
+ kwargs = self._params_builder.set_pagination(**kwargs)
331
312
  objects_with_highlights: list[dict] = []
332
313
  while True:
333
314
  resp = self._prepare_call("GET", api, **kwargs)
334
315
  contents = resp["content"]
335
316
  total_pages = resp["totalPages"]
336
- if not contents or kwargs["params"]["page"] >= total_pages:
337
- break
338
317
  objects_with_highlights.extend(contents)
339
- kwargs["params"]["page"] += 1
318
+ if not contents or self._params_builder.read_page_number(**kwargs) >= (total_pages - 1):
319
+ break
320
+ self._params_builder.increment_page_number(**kwargs)
340
321
 
341
322
  objects = []
342
323
  for obj in objects_with_highlights:
@@ -381,25 +362,6 @@ class ClientDHCore(Client):
381
362
  full_kwargs = self._configurator.get_auth_parameters(kwargs)
382
363
  return self._make_call(call_type, url, **full_kwargs)
383
364
 
384
- def _build_url(self, api: str) -> str:
385
- """
386
- Build the complete URL for an API call.
387
-
388
- Combines the configured endpoint with the API path to create
389
- the full URL for the HTTP request. Automatically removes leading
390
- slashes from the API path to ensure proper URL construction.
391
-
392
- Parameters
393
- ----------
394
- api : str
395
- The API endpoint path. Leading slashes are automatically handled.
396
-
397
- Returns
398
- -------
399
- str
400
- The complete URL for the API call.
401
- """
402
-
403
365
  def _build_url(self, api: str) -> str:
404
366
  """
405
367
  Build complete URL for API call.
@@ -454,7 +416,7 @@ class ClientDHCore(Client):
454
416
  If authentication fails and token refresh not possible.
455
417
  """
456
418
  # Call the API
457
- response = request(call_type, url, timeout=60, **kwargs)
419
+ response = request(call_type, url, timeout=DEFAULT_TIMEOUT, **kwargs)
458
420
 
459
421
  # Evaluate DHCore API version
460
422
  self._check_core_version(response)
@@ -539,3 +501,53 @@ class ClientDHCore(Client):
539
501
  False, indicating this client communicates with remote DHCore backend.
540
502
  """
541
503
  return False
504
+
505
+ ##############################
506
+ # Utility methods
507
+ ##############################
508
+
509
+ @staticmethod
510
+ def _ensure_header(**kwargs) -> dict:
511
+ """
512
+ Initialize header dictionary.
513
+
514
+ Ensures parameter dictionary has 'headers' key for HTTP headers,
515
+ guaranteeing consistent structure for all parameter building methods.
516
+
517
+ Parameters
518
+ ----------
519
+ **kwargs : dict
520
+ Keyword arguments to format. May be empty or contain various
521
+ parameters for API operations.
522
+
523
+ Returns
524
+ -------
525
+ dict
526
+ Headers dictionary with guaranteed 'headers' key containing
527
+ empty dict if not already present.
528
+ """
529
+ if "headers" not in kwargs:
530
+ kwargs["headers"] = {}
531
+ return kwargs
532
+
533
+ def _set_application_json_header(self, **kwargs) -> dict:
534
+ """
535
+ Set Content-Type header to application/json.
536
+
537
+ Ensures that the 'Content-Type' header is set to 'application/json'
538
+ for requests that require JSON payloads.
539
+
540
+ Parameters
541
+ ----------
542
+ **kwargs : dict
543
+ Keyword arguments to format. May be empty or contain various
544
+ parameters for API operations.
545
+
546
+ Returns
547
+ -------
548
+ dict
549
+ Headers dictionary with 'Content-Type' set to 'application/json'.
550
+ """
551
+ kwargs = self._ensure_header(**kwargs)
552
+ kwargs["headers"]["Content-Type"] = "application/json"
553
+ return kwargs