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.
- digitalhub/__init__.py +2 -2
- digitalhub/context/api.py +43 -6
- digitalhub/context/builder.py +1 -1
- digitalhub/context/context.py +3 -6
- digitalhub/entities/_base/context/entity.py +0 -3
- digitalhub/entities/_base/executable/entity.py +29 -11
- digitalhub/entities/_base/material/entity.py +2 -2
- digitalhub/entities/_base/material/utils.py +0 -4
- digitalhub/entities/_commons/enums.py +1 -0
- digitalhub/entities/_commons/utils.py +19 -0
- digitalhub/entities/_processors/base/crud.py +15 -24
- digitalhub/entities/_processors/base/import_export.py +3 -7
- digitalhub/entities/_processors/base/processor.py +4 -7
- digitalhub/entities/_processors/base/special_ops.py +4 -8
- digitalhub/entities/_processors/context/crud.py +27 -29
- digitalhub/entities/_processors/context/import_export.py +7 -7
- digitalhub/entities/_processors/context/material.py +2 -2
- digitalhub/entities/_processors/context/special_ops.py +25 -25
- digitalhub/entities/_processors/utils.py +7 -116
- digitalhub/entities/artifact/crud.py +3 -3
- digitalhub/entities/artifact/utils.py +2 -2
- digitalhub/entities/builders.py +2 -0
- digitalhub/entities/dataitem/crud.py +3 -3
- digitalhub/entities/dataitem/utils.py +10 -14
- digitalhub/entities/function/_base/entity.py +0 -3
- digitalhub/entities/function/crud.py +3 -3
- digitalhub/entities/model/crud.py +3 -3
- digitalhub/entities/model/mlflow/utils.py +29 -20
- digitalhub/entities/model/utils.py +2 -2
- digitalhub/entities/project/_base/builder.py +0 -6
- digitalhub/entities/project/_base/entity.py +264 -114
- digitalhub/entities/project/_base/spec.py +4 -4
- digitalhub/entities/project/crud.py +16 -51
- digitalhub/entities/project/utils.py +7 -3
- digitalhub/entities/secret/crud.py +2 -2
- digitalhub/entities/task/_base/models.py +13 -16
- digitalhub/entities/trigger/crud.py +28 -9
- digitalhub/entities/workflow/_base/entity.py +0 -5
- digitalhub/entities/workflow/crud.py +3 -6
- digitalhub/stores/client/{dhcore/api_builder.py → api_builder.py} +2 -3
- digitalhub/stores/client/builder.py +20 -32
- digitalhub/stores/client/client.py +322 -0
- digitalhub/stores/client/{dhcore/configurator.py → configurator.py} +148 -195
- digitalhub/stores/client/{_base/enums.py → enums.py} +11 -0
- digitalhub/stores/client/header_manager.py +61 -0
- digitalhub/stores/client/http_handler.py +152 -0
- digitalhub/stores/client/{_base/key_builder.py → key_builder.py} +14 -14
- digitalhub/stores/client/{dhcore/params_builder.py → params_builder.py} +51 -12
- digitalhub/stores/client/response_processor.py +102 -0
- digitalhub/stores/client/utils.py +35 -0
- digitalhub/stores/{credentials → configurator}/api.py +5 -9
- digitalhub/stores/configurator/configurator.py +123 -0
- digitalhub/stores/{credentials → configurator}/enums.py +26 -10
- digitalhub/stores/configurator/handler.py +213 -0
- digitalhub/stores/{credentials → configurator}/ini_module.py +31 -6
- digitalhub/stores/data/_base/store.py +0 -4
- digitalhub/stores/data/api.py +4 -6
- digitalhub/stores/data/builder.py +6 -38
- digitalhub/stores/data/s3/configurator.py +30 -114
- digitalhub/stores/data/s3/store.py +9 -22
- digitalhub/stores/data/sql/configurator.py +49 -71
- digitalhub/stores/data/sql/store.py +26 -61
- digitalhub/utils/generic_utils.py +0 -12
- digitalhub/utils/git_utils.py +0 -8
- digitalhub/utils/io_utils.py +0 -8
- digitalhub/utils/store_utils.py +1 -1
- {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/METADATA +3 -3
- {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/RECORD +73 -86
- {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/WHEEL +1 -1
- digitalhub/stores/client/_base/api_builder.py +0 -34
- digitalhub/stores/client/_base/client.py +0 -243
- digitalhub/stores/client/_base/params_builder.py +0 -82
- digitalhub/stores/client/api.py +0 -32
- digitalhub/stores/client/dhcore/__init__.py +0 -3
- digitalhub/stores/client/dhcore/client.py +0 -553
- digitalhub/stores/client/dhcore/enums.py +0 -18
- digitalhub/stores/client/dhcore/key_builder.py +0 -62
- digitalhub/stores/client/dhcore/utils.py +0 -86
- digitalhub/stores/client/local/__init__.py +0 -3
- digitalhub/stores/client/local/api_builder.py +0 -116
- digitalhub/stores/client/local/client.py +0 -605
- digitalhub/stores/client/local/enums.py +0 -15
- digitalhub/stores/client/local/key_builder.py +0 -62
- digitalhub/stores/client/local/params_builder.py +0 -97
- digitalhub/stores/credentials/__init__.py +0 -3
- digitalhub/stores/credentials/configurator.py +0 -185
- digitalhub/stores/credentials/handler.py +0 -164
- digitalhub/stores/credentials/store.py +0 -77
- digitalhub/stores/data/enums.py +0 -15
- /digitalhub/stores/client/{dhcore/error_parser.py → error_parser.py} +0 -0
- /digitalhub/stores/{client/_base → configurator}/__init__.py +0 -0
- {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/licenses/AUTHORS +0 -0
- {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
|
digitalhub/stores/client/api.py
DELETED
|
@@ -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,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"
|