digitalhub 0.14.0b5__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 (93) hide show
  1. digitalhub/__init__.py +2 -2
  2. digitalhub/context/api.py +43 -6
  3. digitalhub/context/builder.py +1 -1
  4. digitalhub/context/context.py +3 -6
  5. digitalhub/entities/_base/context/entity.py +0 -3
  6. digitalhub/entities/_base/executable/entity.py +29 -11
  7. digitalhub/entities/_base/material/entity.py +2 -2
  8. digitalhub/entities/_base/material/utils.py +0 -4
  9. digitalhub/entities/_commons/enums.py +1 -0
  10. digitalhub/entities/_commons/utils.py +19 -0
  11. digitalhub/entities/_processors/base/crud.py +15 -24
  12. digitalhub/entities/_processors/base/import_export.py +3 -7
  13. digitalhub/entities/_processors/base/processor.py +4 -7
  14. digitalhub/entities/_processors/base/special_ops.py +4 -8
  15. digitalhub/entities/_processors/context/crud.py +27 -29
  16. digitalhub/entities/_processors/context/import_export.py +7 -7
  17. digitalhub/entities/_processors/context/material.py +2 -2
  18. digitalhub/entities/_processors/context/special_ops.py +25 -25
  19. digitalhub/entities/_processors/utils.py +7 -116
  20. digitalhub/entities/artifact/crud.py +3 -3
  21. digitalhub/entities/artifact/utils.py +2 -2
  22. digitalhub/entities/builders.py +2 -0
  23. digitalhub/entities/dataitem/crud.py +3 -3
  24. digitalhub/entities/dataitem/utils.py +10 -14
  25. digitalhub/entities/function/_base/entity.py +0 -3
  26. digitalhub/entities/function/crud.py +3 -3
  27. digitalhub/entities/model/crud.py +3 -3
  28. digitalhub/entities/model/mlflow/utils.py +29 -20
  29. digitalhub/entities/model/utils.py +2 -2
  30. digitalhub/entities/project/_base/builder.py +0 -6
  31. digitalhub/entities/project/_base/entity.py +264 -114
  32. digitalhub/entities/project/_base/spec.py +4 -4
  33. digitalhub/entities/project/crud.py +16 -51
  34. digitalhub/entities/project/utils.py +7 -3
  35. digitalhub/entities/secret/crud.py +2 -2
  36. digitalhub/entities/task/_base/models.py +13 -16
  37. digitalhub/entities/trigger/crud.py +28 -9
  38. digitalhub/entities/workflow/_base/entity.py +0 -5
  39. digitalhub/entities/workflow/crud.py +3 -6
  40. digitalhub/stores/client/{dhcore/api_builder.py → api_builder.py} +2 -3
  41. digitalhub/stores/client/builder.py +20 -32
  42. digitalhub/stores/client/client.py +322 -0
  43. digitalhub/stores/client/{dhcore/configurator.py → configurator.py} +148 -195
  44. digitalhub/stores/client/{_base/enums.py → enums.py} +11 -0
  45. digitalhub/stores/client/header_manager.py +61 -0
  46. digitalhub/stores/client/http_handler.py +152 -0
  47. digitalhub/stores/client/{_base/key_builder.py → key_builder.py} +14 -14
  48. digitalhub/stores/client/{dhcore/params_builder.py → params_builder.py} +51 -12
  49. digitalhub/stores/client/response_processor.py +102 -0
  50. digitalhub/stores/client/utils.py +35 -0
  51. digitalhub/stores/{credentials → configurator}/api.py +5 -9
  52. digitalhub/stores/configurator/configurator.py +123 -0
  53. digitalhub/stores/{credentials → configurator}/enums.py +26 -10
  54. digitalhub/stores/configurator/handler.py +213 -0
  55. digitalhub/stores/{credentials → configurator}/ini_module.py +31 -6
  56. digitalhub/stores/data/_base/store.py +0 -4
  57. digitalhub/stores/data/api.py +4 -6
  58. digitalhub/stores/data/builder.py +6 -38
  59. digitalhub/stores/data/s3/configurator.py +30 -114
  60. digitalhub/stores/data/s3/store.py +9 -22
  61. digitalhub/stores/data/sql/configurator.py +49 -71
  62. digitalhub/stores/data/sql/store.py +26 -61
  63. digitalhub/utils/generic_utils.py +0 -12
  64. digitalhub/utils/git_utils.py +0 -8
  65. digitalhub/utils/io_utils.py +0 -8
  66. digitalhub/utils/store_utils.py +1 -1
  67. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/METADATA +3 -3
  68. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/RECORD +73 -86
  69. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/WHEEL +1 -1
  70. digitalhub/stores/client/_base/api_builder.py +0 -34
  71. digitalhub/stores/client/_base/client.py +0 -243
  72. digitalhub/stores/client/_base/params_builder.py +0 -82
  73. digitalhub/stores/client/api.py +0 -32
  74. digitalhub/stores/client/dhcore/__init__.py +0 -3
  75. digitalhub/stores/client/dhcore/client.py +0 -553
  76. digitalhub/stores/client/dhcore/enums.py +0 -18
  77. digitalhub/stores/client/dhcore/key_builder.py +0 -62
  78. digitalhub/stores/client/dhcore/utils.py +0 -86
  79. digitalhub/stores/client/local/__init__.py +0 -3
  80. digitalhub/stores/client/local/api_builder.py +0 -116
  81. digitalhub/stores/client/local/client.py +0 -605
  82. digitalhub/stores/client/local/enums.py +0 -15
  83. digitalhub/stores/client/local/key_builder.py +0 -62
  84. digitalhub/stores/client/local/params_builder.py +0 -97
  85. digitalhub/stores/credentials/__init__.py +0 -3
  86. digitalhub/stores/credentials/configurator.py +0 -185
  87. digitalhub/stores/credentials/handler.py +0 -164
  88. digitalhub/stores/credentials/store.py +0 -77
  89. digitalhub/stores/data/enums.py +0 -15
  90. /digitalhub/stores/client/{dhcore/error_parser.py → error_parser.py} +0 -0
  91. /digitalhub/stores/{client/_base → configurator}/__init__.py +0 -0
  92. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/licenses/AUTHORS +0 -0
  93. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,82 +0,0 @@
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 abc import abstractmethod
8
- from typing import Any
9
-
10
-
11
- class ClientParametersBuilder:
12
- """
13
- This class is used to build the parameters for the client call.
14
- Depending on the client, the parameters are built differently.
15
- """
16
-
17
- @abstractmethod
18
- def build_parameters(self, category: str, operation: str, **kwargs) -> dict:
19
- """
20
- Build the parameters for the client call.
21
-
22
- Parameters
23
- ----------
24
- category : str
25
- The API category.
26
- operation : str
27
- The API operation.
28
- **kwargs : dict
29
- Additional keyword arguments to build parameters from.
30
-
31
- Returns
32
- -------
33
- dict
34
- The formatted parameters for the client call.
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
@@ -1,32 +0,0 @@
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
-
9
- from digitalhub.stores.client.builder import client_builder
10
-
11
- if typing.TYPE_CHECKING:
12
- from digitalhub.stores.client.dhcore.client import ClientDHCore
13
- from digitalhub.stores.client.local.client import ClientLocal
14
-
15
-
16
- def get_client(local: bool = False) -> ClientLocal | ClientDHCore:
17
- """
18
- Wrapper around ClientBuilder.build.
19
-
20
- Parameters
21
- ----------
22
- local : bool, default False
23
- Whether to create a local client or not. If True, creates a
24
- ClientLocal instance that operates in-memory. If False, creates
25
- a ClientDHCore instance that communicates with a remote backend.
26
-
27
- Returns
28
- -------
29
- ClientLocal | ClientDHCore
30
- The client instance.
31
- """
32
- return client_builder.build(local)
@@ -1,3 +0,0 @@
1
- # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
- #
3
- # SPDX-License-Identifier: Apache-2.0
@@ -1,553 +0,0 @@
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 typing import Any
9
- from warnings import warn
10
-
11
- from requests import request
12
- from requests.exceptions import JSONDecodeError
13
-
14
- from digitalhub.stores.client._base.client import Client
15
- from digitalhub.stores.client.dhcore.api_builder import ClientDHCoreApiBuilder
16
- from digitalhub.stores.client.dhcore.configurator import ClientDHCoreConfigurator
17
- from digitalhub.stores.client.dhcore.error_parser import ErrorParser
18
- from digitalhub.stores.client.dhcore.key_builder import ClientDHCoreKeyBuilder
19
- from digitalhub.stores.client.dhcore.params_builder import ClientDHCoreParametersBuilder
20
- from digitalhub.utils.exceptions import BackendError, ClientError
21
- from digitalhub.utils.generic_utils import dump_json
22
-
23
- if typing.TYPE_CHECKING:
24
- from requests import Response
25
-
26
-
27
- # API levels that are supported
28
- MAX_API_LEVEL = 20
29
- MIN_API_LEVEL = 14
30
- LIB_VERSION = 14
31
-
32
- # Default timeout for requests (in seconds)
33
- DEFAULT_TIMEOUT = 60
34
-
35
-
36
- class ClientDHCore(Client):
37
- """
38
- DHCore client for remote DigitalHub Core backend communication.
39
-
40
- Provides REST API communication with DigitalHub Core backend supporting
41
- multiple authentication methods: Basic (username/password), OAuth2 (token
42
- with refresh), and Personal Access Token exchange. Automatically handles
43
- API version compatibility, pagination, token refresh, error parsing, and
44
- JSON serialization. Supports API versions {MIN_API_LEVEL} to {MAX_API_LEVEL}.
45
-
46
- Parameters
47
- ----------
48
- config : dict, optional
49
- DHCore environment configuration. If None, loads from environment
50
- variables and configuration files.
51
-
52
- Attributes
53
- ----------
54
- _api_builder : ClientDHCoreApiBuilder
55
- Builds API endpoint URLs for different operations.
56
- _key_builder : ClientDHCoreKeyBuilder
57
- Builds storage keys for entities.
58
- _params_builder : ClientDHCoreParametersBuilder
59
- Builds request parameters for API calls.
60
- _error_parser : ErrorParser
61
- Parses backend responses and raises appropriate exceptions.
62
- _configurator : ClientDHCoreConfigurator
63
- Manages client configuration and authentication.
64
- """
65
-
66
- def __init__(self, config: dict | None = None) -> None:
67
- """
68
- Initialize DHCore client with API builders and configurators.
69
-
70
- Parameters
71
- ----------
72
- config : dict, optional
73
- DHCore environment configuration. If None, loads from environment
74
- variables and configuration files.
75
- """
76
- super().__init__()
77
-
78
- # API builder
79
- self._api_builder: ClientDHCoreApiBuilder = ClientDHCoreApiBuilder()
80
-
81
- # Key builder
82
- self._key_builder: ClientDHCoreKeyBuilder = ClientDHCoreKeyBuilder()
83
-
84
- # Parameters builder
85
- self._params_builder: ClientDHCoreParametersBuilder = ClientDHCoreParametersBuilder()
86
-
87
- # Error parser
88
- self._error_parser = ErrorParser()
89
-
90
- # Client Configurator
91
- self._configurator = ClientDHCoreConfigurator()
92
-
93
- ##############################
94
- # CRUD methods
95
- ##############################
96
-
97
- def create_object(self, api: str, obj: Any, **kwargs) -> dict:
98
- """
99
- Create an object in DHCore via POST request.
100
-
101
- Automatically sets Content-Type header and serializes object to JSON.
102
-
103
- Parameters
104
- ----------
105
- api : str
106
- API endpoint path for creating the object.
107
- obj : Any
108
- Object to create. Will be serialized to JSON.
109
- **kwargs : dict
110
- Additional HTTP request arguments.
111
-
112
- Returns
113
- -------
114
- dict
115
- Created object as returned by the backend.
116
-
117
- Raises
118
- ------
119
- BackendError
120
- If the backend returns an error response.
121
- ClientError
122
- If there are client-side configuration issues.
123
- """
124
- kwargs = self._set_application_json_header(**kwargs)
125
- kwargs["data"] = dump_json(obj)
126
- return self._prepare_call("POST", api, **kwargs)
127
-
128
- def read_object(self, api: str, **kwargs) -> dict:
129
- """
130
- Get an object from DHCore.
131
-
132
- Sends a GET request to the DHCore backend to retrieve an existing object.
133
-
134
- Parameters
135
- ----------
136
- api : str
137
- API endpoint path for reading the object.
138
- **kwargs : dict
139
- Additional HTTP request arguments.
140
-
141
- Returns
142
- -------
143
- dict
144
- Retrieved object as returned by the backend.
145
-
146
- Raises
147
- ------
148
- BackendError
149
- If the backend returns an error response.
150
- EntityNotExistsError
151
- If the requested object does not exist.
152
- """
153
- return self._prepare_call("GET", api, **kwargs)
154
-
155
- def update_object(self, api: str, obj: Any, **kwargs) -> dict:
156
- """
157
- Update an object in DHCore via PUT request.
158
-
159
- Automatically sets Content-Type header and serializes object to JSON.
160
-
161
- Parameters
162
- ----------
163
- api : str
164
- API endpoint path for updating the object.
165
- obj : Any
166
- Updated object data. Will be serialized to JSON.
167
- **kwargs : dict
168
- Additional HTTP request arguments.
169
-
170
- Returns
171
- -------
172
- dict
173
- Updated object as returned by the backend.
174
-
175
- Raises
176
- ------
177
- BackendError
178
- If the backend returns an error response.
179
- EntityNotExistsError
180
- If the object to update does not exist.
181
- """
182
- kwargs = self._set_application_json_header(**kwargs)
183
- kwargs["data"] = dump_json(obj)
184
- return self._prepare_call("PUT", api, **kwargs)
185
-
186
- def delete_object(self, api: str, **kwargs) -> dict:
187
- """
188
- Delete an object from DHCore.
189
-
190
- Sends DELETE request to remove an object. Wraps boolean responses
191
- in {"deleted": True/False} dictionary.
192
-
193
- Parameters
194
- ----------
195
- api : str
196
- API endpoint path for deleting the object.
197
- **kwargs : dict
198
- Additional HTTP request arguments.
199
-
200
- Returns
201
- -------
202
- dict
203
- Deletion result from backend or {"deleted": bool} wrapper.
204
-
205
- Raises
206
- ------
207
- BackendError
208
- If the backend returns an error response.
209
- EntityNotExistsError
210
- If the object to delete does not exist.
211
- """
212
- resp = self._prepare_call("DELETE", api, **kwargs)
213
- if isinstance(resp, bool):
214
- resp = {"deleted": resp}
215
- return resp
216
-
217
- def list_objects(self, api: str, **kwargs) -> list[dict]:
218
- """
219
- List objects from DHCore with automatic pagination.
220
-
221
- Sends GET requests to retrieve paginated objects, automatically handling
222
- pagination (starting from page 0) until all objects are retrieved.
223
-
224
- Parameters
225
- ----------
226
- api : str
227
- API endpoint path for listing objects.
228
- **kwargs : dict
229
- Additional HTTP request arguments. Can include 'params' dict
230
- with pagination parameters.
231
-
232
- Returns
233
- -------
234
- list[dict]
235
- List containing all objects from all pages.
236
-
237
- Raises
238
- ------
239
- BackendError
240
- If the backend returns an error response.
241
- """
242
- kwargs = self._params_builder.set_pagination(partial=True, **kwargs)
243
-
244
- objects = []
245
- while True:
246
- resp = self._prepare_call("GET", api, **kwargs)
247
- contents = resp["content"]
248
- total_pages = resp["totalPages"]
249
- objects.extend(contents)
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)
253
-
254
- return objects
255
-
256
- def list_first_object(self, api: str, **kwargs) -> dict:
257
- """
258
- Get the first object from a DHCore list.
259
-
260
- Retrieves the first object by calling list_objects and returning
261
- the first item.
262
-
263
- Parameters
264
- ----------
265
- api : str
266
- API endpoint path for listing objects.
267
- **kwargs : dict
268
- Additional HTTP request arguments.
269
-
270
- Returns
271
- -------
272
- dict
273
- First object from the list.
274
-
275
- Raises
276
- ------
277
- BackendError
278
- If no objects found or backend returns an error.
279
- """
280
- try:
281
- return self.list_objects(api, **kwargs)[0]
282
- except IndexError:
283
- raise BackendError("No object found.")
284
-
285
- def search_objects(self, api: str, **kwargs) -> list[dict]:
286
- """
287
- Search objects from DHCore using Solr capabilities.
288
-
289
- Performs search query with pagination and removes search highlights.
290
- Sets default pagination (page=0, size=10) and sorting (metadata.updated DESC)
291
- if not provided.
292
-
293
- Parameters
294
- ----------
295
- api : str
296
- API endpoint path for searching objects (usually Solr search).
297
- **kwargs : dict
298
- Additional HTTP request arguments including search parameters,
299
- filters, and pagination options.
300
-
301
- Returns
302
- -------
303
- list[dict]
304
- List of matching objects with search highlights removed.
305
-
306
- Raises
307
- ------
308
- BackendError
309
- If the backend returns an error response.
310
- """
311
- kwargs = self._params_builder.set_pagination(**kwargs)
312
- objects_with_highlights: list[dict] = []
313
- while True:
314
- resp = self._prepare_call("GET", api, **kwargs)
315
- contents = resp["content"]
316
- total_pages = resp["totalPages"]
317
- objects_with_highlights.extend(contents)
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)
321
-
322
- objects = []
323
- for obj in objects_with_highlights:
324
- obj.pop("highlights", None)
325
- objects.append(obj)
326
-
327
- return objects
328
-
329
- ##############################
330
- # Call methods
331
- ##############################
332
-
333
- def _prepare_call(self, call_type: str, api: str, **kwargs) -> dict:
334
- """
335
- Prepare DHCore API call with configuration and authentication.
336
-
337
- Checks configuration, builds URL, and adds authentication parameters.
338
-
339
- Parameters
340
- ----------
341
- call_type : str
342
- HTTP method type (GET, POST, PUT, DELETE, etc.).
343
- api : str
344
- API endpoint path to call.
345
- **kwargs : dict
346
- Additional HTTP request arguments.
347
-
348
- Returns
349
- -------
350
- dict
351
- Response from the API call.
352
-
353
- Raises
354
- ------
355
- ClientError
356
- If client configuration is invalid.
357
- BackendError
358
- If backend returns an error response.
359
- """
360
- self._configurator.check_config()
361
- url = self._build_url(api)
362
- full_kwargs = self._configurator.get_auth_parameters(kwargs)
363
- return self._make_call(call_type, url, **full_kwargs)
364
-
365
- def _build_url(self, api: str) -> str:
366
- """
367
- Build complete URL for API call.
368
-
369
- Combines configured endpoint with API path, automatically removing
370
- leading slashes for proper URL construction.
371
-
372
- Parameters
373
- ----------
374
- api : str
375
- API endpoint path. Leading slashes are automatically handled.
376
-
377
- Returns
378
- -------
379
- str
380
- Complete URL for the API call.
381
- """
382
- endpoint = self._configurator.get_endpoint()
383
- return f"{endpoint}/{api.removeprefix('/')}"
384
-
385
- def _make_call(self, call_type: str, url: str, refresh: bool = True, **kwargs) -> dict:
386
- """
387
- Execute HTTP request to DHCore API with automatic handling.
388
-
389
- Handles API version checking, token refresh on 401 errors, response parsing,
390
- and error handling with 60-second timeout.
391
-
392
- Parameters
393
- ----------
394
- call_type : str
395
- HTTP method type (GET, POST, PUT, DELETE, etc.).
396
- url : str
397
- Complete URL to call.
398
- refresh : bool, default True
399
- Whether to attempt token refresh on authentication errors.
400
- Set to False to prevent infinite recursion during refresh.
401
- **kwargs : dict
402
- Additional HTTP request arguments.
403
-
404
- Returns
405
- -------
406
- dict
407
- Parsed response from backend as dictionary.
408
-
409
- Raises
410
- ------
411
- ClientError
412
- If backend API version is not supported.
413
- BackendError
414
- If backend returns error response or response parsing fails.
415
- UnauthorizedError
416
- If authentication fails and token refresh not possible.
417
- """
418
- # Call the API
419
- response = request(call_type, url, timeout=DEFAULT_TIMEOUT, **kwargs)
420
-
421
- # Evaluate DHCore API version
422
- self._check_core_version(response)
423
-
424
- # Handle token refresh (redo call)
425
- if (response.status_code in [401]) and (refresh) and self._configurator.refreshable_auth_types():
426
- self._configurator.refresh_credentials(change_origin=True)
427
- kwargs = self._configurator.get_auth_parameters(kwargs)
428
- return self._make_call(call_type, url, refresh=False, **kwargs)
429
-
430
- self._error_parser.parse(response)
431
- return self._dictify_response(response)
432
-
433
- def _check_core_version(self, response: Response) -> None:
434
- """
435
- Validate DHCore API version compatibility.
436
-
437
- Checks backend API version against supported range and warns if backend
438
- version is newer than library. Supported: {MIN_API_LEVEL} to {MAX_API_LEVEL}.
439
-
440
- Parameters
441
- ----------
442
- response : Response
443
- HTTP response containing X-Api-Level header.
444
-
445
- Raises
446
- ------
447
- ClientError
448
- If backend API level is not supported by this client.
449
- """
450
- if "X-Api-Level" in response.headers:
451
- core_api_level = int(response.headers["X-Api-Level"])
452
- if not (MIN_API_LEVEL <= core_api_level <= MAX_API_LEVEL):
453
- raise ClientError("Backend API level not supported.")
454
- if LIB_VERSION < core_api_level:
455
- warn("Backend API level is higher than library version. You should consider updating the library.")
456
-
457
- def _dictify_response(self, response: Response) -> dict:
458
- """
459
- Parse HTTP response body to dictionary.
460
-
461
- Converts JSON response to Python dictionary, treating empty responses
462
- as valid and returning empty dict.
463
-
464
- Parameters
465
- ----------
466
- response : Response
467
- HTTP response object to parse.
468
-
469
- Returns
470
- -------
471
- dict
472
- Parsed response body as dictionary, or empty dict if body is empty.
473
-
474
- Raises
475
- ------
476
- BackendError
477
- If response cannot be parsed as JSON.
478
- """
479
- try:
480
- return response.json()
481
- except JSONDecodeError:
482
- if response.text == "":
483
- return {}
484
- raise BackendError("Backend response could not be parsed.")
485
-
486
- ##############################
487
- # Interface methods
488
- ##############################
489
-
490
- @staticmethod
491
- def is_local() -> bool:
492
- """
493
- Check if this client operates locally.
494
-
495
- Used to distinguish between ClientDHCore (remote) and ClientLocal
496
- implementations.
497
-
498
- Returns
499
- -------
500
- bool
501
- False, indicating this client communicates with remote DHCore backend.
502
- """
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
@@ -1,18 +0,0 @@
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 AuthType(Enum):
11
- """
12
- Authentication types.
13
- """
14
-
15
- BASIC = "basic"
16
- OAUTH2 = "oauth2"
17
- EXCHANGE = "exchange"
18
- ACCESS_TOKEN = "access_token_only"