digitalhub 0.11.0b7__py3-none-any.whl → 0.13.0__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 (272) hide show
  1. digitalhub/__init__.py +4 -1
  2. digitalhub/context/api.py +9 -5
  3. digitalhub/context/builder.py +7 -5
  4. digitalhub/context/context.py +13 -1
  5. digitalhub/entities/__init__.py +3 -0
  6. digitalhub/entities/_base/__init__.py +3 -0
  7. digitalhub/entities/_base/_base/__init__.py +3 -0
  8. digitalhub/entities/_base/_base/entity.py +4 -0
  9. digitalhub/entities/_base/context/__init__.py +3 -0
  10. digitalhub/entities/_base/context/entity.py +4 -0
  11. digitalhub/entities/_base/entity/__init__.py +3 -0
  12. digitalhub/entities/_base/entity/_constructors/__init__.py +3 -0
  13. digitalhub/entities/_base/entity/_constructors/metadata.py +4 -0
  14. digitalhub/entities/_base/entity/_constructors/name.py +4 -0
  15. digitalhub/entities/_base/entity/_constructors/spec.py +4 -0
  16. digitalhub/entities/_base/entity/_constructors/status.py +4 -0
  17. digitalhub/entities/_base/entity/_constructors/uuid.py +4 -0
  18. digitalhub/entities/_base/entity/builder.py +4 -0
  19. digitalhub/entities/_base/entity/entity.py +4 -0
  20. digitalhub/entities/_base/entity/metadata.py +4 -0
  21. digitalhub/entities/_base/entity/spec.py +4 -0
  22. digitalhub/entities/_base/entity/status.py +4 -0
  23. digitalhub/entities/_base/executable/__init__.py +3 -0
  24. digitalhub/entities/_base/executable/entity.py +109 -57
  25. digitalhub/entities/_base/material/__init__.py +3 -0
  26. digitalhub/entities/_base/material/entity.py +15 -18
  27. digitalhub/entities/_base/material/spec.py +4 -0
  28. digitalhub/entities/_base/material/status.py +4 -0
  29. digitalhub/entities/_base/material/utils.py +5 -1
  30. digitalhub/entities/_base/runtime_entity/__init__.py +3 -0
  31. digitalhub/entities/_base/runtime_entity/builder.py +4 -0
  32. digitalhub/entities/_base/unversioned/__init__.py +3 -0
  33. digitalhub/entities/_base/unversioned/builder.py +4 -0
  34. digitalhub/entities/_base/unversioned/entity.py +4 -0
  35. digitalhub/entities/_base/versioned/__init__.py +3 -0
  36. digitalhub/entities/_base/versioned/builder.py +4 -0
  37. digitalhub/entities/_base/versioned/entity.py +4 -0
  38. digitalhub/entities/_commons/__init__.py +3 -0
  39. digitalhub/entities/_commons/enums.py +4 -0
  40. digitalhub/entities/_commons/metrics.py +68 -30
  41. digitalhub/entities/_commons/utils.py +40 -9
  42. digitalhub/entities/_processors/__init__.py +3 -0
  43. digitalhub/entities/_processors/base.py +154 -79
  44. digitalhub/entities/_processors/context.py +370 -215
  45. digitalhub/entities/_processors/utils.py +78 -30
  46. digitalhub/entities/artifact/__init__.py +3 -0
  47. digitalhub/entities/artifact/_base/__init__.py +3 -0
  48. digitalhub/entities/artifact/_base/builder.py +4 -0
  49. digitalhub/entities/artifact/_base/entity.py +4 -0
  50. digitalhub/entities/artifact/_base/spec.py +4 -0
  51. digitalhub/entities/artifact/_base/status.py +4 -0
  52. digitalhub/entities/artifact/artifact/__init__.py +3 -0
  53. digitalhub/entities/artifact/artifact/builder.py +4 -0
  54. digitalhub/entities/artifact/artifact/entity.py +4 -0
  55. digitalhub/entities/artifact/artifact/spec.py +4 -0
  56. digitalhub/entities/artifact/artifact/status.py +4 -0
  57. digitalhub/entities/artifact/crud.py +8 -0
  58. digitalhub/entities/artifact/utils.py +32 -13
  59. digitalhub/entities/builders.py +4 -0
  60. digitalhub/entities/dataitem/__init__.py +3 -0
  61. digitalhub/entities/dataitem/_base/__init__.py +3 -0
  62. digitalhub/entities/dataitem/_base/builder.py +4 -0
  63. digitalhub/entities/dataitem/_base/entity.py +4 -0
  64. digitalhub/entities/dataitem/_base/spec.py +4 -0
  65. digitalhub/entities/dataitem/_base/status.py +4 -0
  66. digitalhub/entities/dataitem/crud.py +18 -2
  67. digitalhub/entities/dataitem/dataitem/__init__.py +3 -0
  68. digitalhub/entities/dataitem/dataitem/builder.py +4 -0
  69. digitalhub/entities/dataitem/dataitem/entity.py +4 -0
  70. digitalhub/entities/dataitem/dataitem/spec.py +4 -0
  71. digitalhub/entities/dataitem/dataitem/status.py +4 -0
  72. digitalhub/entities/dataitem/iceberg/__init__.py +3 -0
  73. digitalhub/entities/dataitem/iceberg/builder.py +4 -0
  74. digitalhub/entities/dataitem/iceberg/entity.py +4 -0
  75. digitalhub/entities/dataitem/iceberg/spec.py +4 -0
  76. digitalhub/entities/dataitem/iceberg/status.py +4 -0
  77. digitalhub/entities/dataitem/table/__init__.py +3 -0
  78. digitalhub/entities/dataitem/table/builder.py +4 -0
  79. digitalhub/entities/dataitem/table/entity.py +7 -3
  80. digitalhub/entities/dataitem/table/models.py +4 -0
  81. digitalhub/entities/dataitem/table/spec.py +4 -0
  82. digitalhub/entities/dataitem/table/status.py +4 -0
  83. digitalhub/entities/dataitem/table/utils.py +4 -0
  84. digitalhub/entities/dataitem/utils.py +88 -35
  85. digitalhub/entities/function/__init__.py +3 -0
  86. digitalhub/entities/function/_base/__init__.py +3 -0
  87. digitalhub/entities/function/_base/builder.py +4 -0
  88. digitalhub/entities/function/_base/entity.py +4 -0
  89. digitalhub/entities/function/_base/spec.py +4 -0
  90. digitalhub/entities/function/_base/status.py +4 -0
  91. digitalhub/entities/function/crud.py +4 -0
  92. digitalhub/entities/model/__init__.py +3 -0
  93. digitalhub/entities/model/_base/__init__.py +3 -0
  94. digitalhub/entities/model/_base/builder.py +4 -0
  95. digitalhub/entities/model/_base/entity.py +4 -0
  96. digitalhub/entities/model/_base/spec.py +4 -0
  97. digitalhub/entities/model/_base/status.py +4 -0
  98. digitalhub/entities/model/crud.py +8 -0
  99. digitalhub/entities/model/huggingface/__init__.py +3 -0
  100. digitalhub/entities/model/huggingface/builder.py +4 -0
  101. digitalhub/entities/model/huggingface/entity.py +4 -0
  102. digitalhub/entities/model/huggingface/spec.py +4 -0
  103. digitalhub/entities/model/huggingface/status.py +4 -0
  104. digitalhub/entities/model/mlflow/__init__.py +3 -0
  105. digitalhub/entities/model/mlflow/builder.py +4 -0
  106. digitalhub/entities/model/mlflow/entity.py +4 -0
  107. digitalhub/entities/model/mlflow/models.py +4 -0
  108. digitalhub/entities/model/mlflow/spec.py +4 -0
  109. digitalhub/entities/model/mlflow/status.py +4 -0
  110. digitalhub/entities/model/mlflow/utils.py +4 -0
  111. digitalhub/entities/model/model/__init__.py +3 -0
  112. digitalhub/entities/model/model/builder.py +4 -0
  113. digitalhub/entities/model/model/entity.py +4 -0
  114. digitalhub/entities/model/model/spec.py +4 -0
  115. digitalhub/entities/model/model/status.py +4 -0
  116. digitalhub/entities/model/sklearn/__init__.py +3 -0
  117. digitalhub/entities/model/sklearn/builder.py +4 -0
  118. digitalhub/entities/model/sklearn/entity.py +4 -0
  119. digitalhub/entities/model/sklearn/spec.py +4 -0
  120. digitalhub/entities/model/sklearn/status.py +4 -0
  121. digitalhub/entities/model/utils.py +32 -13
  122. digitalhub/entities/project/__init__.py +3 -0
  123. digitalhub/entities/project/_base/__init__.py +3 -0
  124. digitalhub/entities/project/_base/builder.py +4 -0
  125. digitalhub/entities/project/_base/entity.py +4 -2
  126. digitalhub/entities/project/_base/models.py +4 -0
  127. digitalhub/entities/project/_base/spec.py +4 -0
  128. digitalhub/entities/project/_base/status.py +4 -0
  129. digitalhub/entities/project/crud.py +4 -0
  130. digitalhub/entities/project/utils.py +4 -0
  131. digitalhub/entities/run/__init__.py +3 -0
  132. digitalhub/entities/run/_base/__init__.py +3 -0
  133. digitalhub/entities/run/_base/builder.py +4 -0
  134. digitalhub/entities/run/_base/entity.py +6 -2
  135. digitalhub/entities/run/_base/spec.py +4 -0
  136. digitalhub/entities/run/_base/status.py +4 -0
  137. digitalhub/entities/run/crud.py +4 -0
  138. digitalhub/entities/secret/__init__.py +3 -0
  139. digitalhub/entities/secret/_base/__init__.py +3 -0
  140. digitalhub/entities/secret/_base/builder.py +4 -0
  141. digitalhub/entities/secret/_base/entity.py +4 -0
  142. digitalhub/entities/secret/_base/spec.py +4 -0
  143. digitalhub/entities/secret/_base/status.py +4 -0
  144. digitalhub/entities/secret/crud.py +4 -0
  145. digitalhub/entities/task/__init__.py +3 -0
  146. digitalhub/entities/task/_base/__init__.py +3 -0
  147. digitalhub/entities/task/_base/builder.py +4 -0
  148. digitalhub/entities/task/_base/entity.py +4 -0
  149. digitalhub/entities/task/_base/models.py +16 -3
  150. digitalhub/entities/task/_base/spec.py +4 -0
  151. digitalhub/entities/task/_base/status.py +4 -0
  152. digitalhub/entities/task/_base/utils.py +4 -0
  153. digitalhub/entities/task/crud.py +4 -0
  154. digitalhub/entities/trigger/__init__.py +3 -0
  155. digitalhub/entities/trigger/_base/__init__.py +3 -0
  156. digitalhub/entities/trigger/_base/builder.py +4 -0
  157. digitalhub/entities/trigger/_base/entity.py +15 -0
  158. digitalhub/entities/trigger/_base/spec.py +4 -0
  159. digitalhub/entities/trigger/_base/status.py +4 -0
  160. digitalhub/entities/trigger/crud.py +4 -0
  161. digitalhub/entities/trigger/lifecycle/__init__.py +3 -0
  162. digitalhub/entities/trigger/lifecycle/builder.py +4 -0
  163. digitalhub/entities/trigger/lifecycle/entity.py +4 -0
  164. digitalhub/entities/trigger/lifecycle/spec.py +4 -0
  165. digitalhub/entities/trigger/lifecycle/status.py +4 -0
  166. digitalhub/entities/trigger/scheduler/__init__.py +3 -0
  167. digitalhub/entities/trigger/scheduler/builder.py +4 -0
  168. digitalhub/entities/trigger/scheduler/entity.py +4 -0
  169. digitalhub/entities/trigger/scheduler/spec.py +4 -0
  170. digitalhub/entities/trigger/scheduler/status.py +4 -0
  171. digitalhub/entities/workflow/__init__.py +3 -0
  172. digitalhub/entities/workflow/_base/__init__.py +3 -0
  173. digitalhub/entities/workflow/_base/builder.py +4 -0
  174. digitalhub/entities/workflow/_base/entity.py +4 -0
  175. digitalhub/entities/workflow/_base/spec.py +4 -0
  176. digitalhub/entities/workflow/_base/status.py +4 -0
  177. digitalhub/entities/workflow/crud.py +4 -0
  178. digitalhub/factory/__init__.py +3 -0
  179. digitalhub/factory/factory.py +29 -3
  180. digitalhub/factory/utils.py +15 -3
  181. digitalhub/runtimes/__init__.py +3 -0
  182. digitalhub/runtimes/_base.py +5 -1
  183. digitalhub/runtimes/builder.py +22 -1
  184. digitalhub/runtimes/enums.py +4 -0
  185. digitalhub/stores/__init__.py +3 -0
  186. digitalhub/stores/client/__init__.py +15 -0
  187. digitalhub/stores/client/_base/__init__.py +3 -0
  188. digitalhub/stores/client/_base/api_builder.py +18 -0
  189. digitalhub/stores/client/_base/client.py +97 -0
  190. digitalhub/stores/client/_base/key_builder.py +32 -0
  191. digitalhub/stores/client/_base/params_builder.py +18 -0
  192. digitalhub/stores/client/api.py +14 -5
  193. digitalhub/stores/client/builder.py +7 -1
  194. digitalhub/stores/client/dhcore/__init__.py +3 -0
  195. digitalhub/stores/client/dhcore/api_builder.py +21 -0
  196. digitalhub/stores/client/dhcore/client.py +329 -70
  197. digitalhub/stores/client/dhcore/configurator.py +489 -193
  198. digitalhub/stores/client/dhcore/enums.py +7 -0
  199. digitalhub/stores/client/dhcore/error_parser.py +39 -1
  200. digitalhub/stores/client/dhcore/key_builder.py +4 -0
  201. digitalhub/stores/client/dhcore/models.py +4 -0
  202. digitalhub/stores/client/dhcore/params_builder.py +117 -17
  203. digitalhub/stores/client/dhcore/utils.py +44 -22
  204. digitalhub/stores/client/local/__init__.py +3 -0
  205. digitalhub/stores/client/local/api_builder.py +21 -0
  206. digitalhub/stores/client/local/client.py +10 -8
  207. digitalhub/stores/client/local/enums.py +4 -0
  208. digitalhub/stores/client/local/key_builder.py +4 -0
  209. digitalhub/stores/client/local/params_builder.py +4 -0
  210. digitalhub/stores/credentials/__init__.py +3 -0
  211. digitalhub/stores/credentials/api.py +35 -0
  212. digitalhub/stores/credentials/configurator.py +210 -0
  213. digitalhub/stores/credentials/enums.py +68 -0
  214. digitalhub/stores/credentials/handler.py +176 -0
  215. digitalhub/stores/credentials/ini_module.py +164 -0
  216. digitalhub/stores/credentials/store.py +81 -0
  217. digitalhub/stores/data/__init__.py +3 -0
  218. digitalhub/stores/data/_base/__init__.py +3 -0
  219. digitalhub/stores/data/_base/store.py +31 -9
  220. digitalhub/stores/data/api.py +53 -9
  221. digitalhub/stores/data/builder.py +94 -41
  222. digitalhub/stores/data/enums.py +4 -0
  223. digitalhub/stores/data/local/__init__.py +3 -0
  224. digitalhub/stores/data/local/store.py +8 -7
  225. digitalhub/stores/data/remote/__init__.py +3 -0
  226. digitalhub/stores/data/remote/store.py +8 -7
  227. digitalhub/stores/data/s3/__init__.py +3 -0
  228. digitalhub/stores/data/s3/configurator.py +69 -80
  229. digitalhub/stores/data/s3/store.py +73 -81
  230. digitalhub/stores/data/s3/utils.py +14 -10
  231. digitalhub/stores/data/sql/__init__.py +3 -0
  232. digitalhub/stores/data/sql/configurator.py +80 -73
  233. digitalhub/stores/data/sql/store.py +195 -102
  234. digitalhub/stores/readers/__init__.py +3 -0
  235. digitalhub/stores/readers/data/__init__.py +3 -0
  236. digitalhub/stores/readers/data/_base/__init__.py +3 -0
  237. digitalhub/stores/readers/data/_base/builder.py +4 -0
  238. digitalhub/stores/readers/data/_base/reader.py +4 -0
  239. digitalhub/stores/readers/data/api.py +4 -0
  240. digitalhub/stores/readers/data/factory.py +4 -0
  241. digitalhub/stores/readers/data/pandas/__init__.py +3 -0
  242. digitalhub/stores/readers/data/pandas/builder.py +4 -0
  243. digitalhub/stores/readers/data/pandas/reader.py +4 -0
  244. digitalhub/stores/readers/query/__init__.py +3 -0
  245. digitalhub/utils/__init__.py +3 -0
  246. digitalhub/utils/enums.py +4 -0
  247. digitalhub/utils/exceptions.py +10 -0
  248. digitalhub/utils/file_utils.py +57 -30
  249. digitalhub/utils/generic_utils.py +45 -33
  250. digitalhub/utils/git_utils.py +28 -14
  251. digitalhub/utils/io_utils.py +23 -18
  252. digitalhub/utils/logger.py +4 -0
  253. digitalhub/utils/types.py +4 -0
  254. digitalhub/utils/uri_utils.py +35 -31
  255. digitalhub-0.13.0.dist-info/METADATA +301 -0
  256. digitalhub-0.13.0.dist-info/RECORD +259 -0
  257. digitalhub-0.13.0.dist-info/licenses/AUTHORS +5 -0
  258. digitalhub-0.13.0.dist-info/licenses/LICENSE +201 -0
  259. digitalhub/entities/_commons/types.py +0 -5
  260. digitalhub/stores/configurator/__init__.py +0 -0
  261. digitalhub/stores/configurator/api.py +0 -31
  262. digitalhub/stores/configurator/configurator.py +0 -198
  263. digitalhub/stores/configurator/credentials_store.py +0 -65
  264. digitalhub/stores/configurator/enums.py +0 -21
  265. digitalhub/stores/configurator/ini_module.py +0 -128
  266. digitalhub/stores/data/s3/enums.py +0 -16
  267. digitalhub/stores/data/sql/enums.py +0 -16
  268. digitalhub/stores/data/utils.py +0 -34
  269. digitalhub-0.11.0b7.dist-info/METADATA +0 -259
  270. digitalhub-0.11.0b7.dist-info/RECORD +0 -261
  271. digitalhub-0.11.0b7.dist-info/licenses/LICENSE.txt +0 -216
  272. {digitalhub-0.11.0b7.dist-info → digitalhub-0.13.0.dist-info}/WHEEL +0 -0
@@ -1,7 +1,12 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
1
5
  from __future__ import annotations
2
6
 
3
7
  import typing
4
8
  from typing import Any
9
+ from warnings import warn
5
10
 
6
11
  from requests import request
7
12
  from requests.exceptions import JSONDecodeError
@@ -12,30 +17,91 @@ from digitalhub.stores.client.dhcore.configurator import ClientDHCoreConfigurato
12
17
  from digitalhub.stores.client.dhcore.error_parser import ErrorParser
13
18
  from digitalhub.stores.client.dhcore.key_builder import ClientDHCoreKeyBuilder
14
19
  from digitalhub.stores.client.dhcore.params_builder import ClientDHCoreParametersBuilder
15
- from digitalhub.utils.exceptions import BackendError
20
+ from digitalhub.utils.exceptions import BackendError, ClientError
16
21
  from digitalhub.utils.generic_utils import dump_json
17
22
 
18
23
  if typing.TYPE_CHECKING:
19
24
  from requests import Response
20
25
 
21
26
 
27
+ # API levels that are supported
28
+ MAX_API_LEVEL = 20
29
+ MIN_API_LEVEL = 13
30
+ LIB_VERSION = 13
31
+
32
+
22
33
  class ClientDHCore(Client):
23
34
  """
24
- DHCore client.
25
-
26
- The DHCore client is used to communicate with the Digitalhub Core
27
- backendAPI via REST. The client supports basic authentication and
28
- OAuth2 token authentication with token refresh.
29
- At creation, the client tries to get the endpoint and authentication
30
- parameters from the .dhcore file and the environment variables. In
31
- case the user incours into an authentication/endpoint error during
32
- the client creation, the user has the possibility to update the
33
- correct parameters using the `set_dhcore_env` function. If the DHCore
34
- client is already initialized, this function will override the
35
- configuration, otherwise it simply set the environment variables.
35
+ DHCore client for remote DigitalHub Core backend communication.
36
+
37
+ The DHCore client is used to communicate with the DigitalHub Core
38
+ backend API via REST. The client supports multiple authentication methods:
39
+ - Basic authentication (username/password)
40
+ - OAuth2 token authentication with automatic token refresh
41
+ - Personal access token exchange
42
+
43
+ At initialization, the client attempts to load endpoint and authentication
44
+ parameters from environment variables and the .dhcore configuration file.
45
+ If authentication or endpoint errors occur during client creation, users
46
+ can update the configuration using the `set_dhcore_env` function from
47
+ the utils module.
48
+
49
+ The client automatically handles:
50
+ - API version compatibility checking
51
+ - Pagination for list operations
52
+ - Token refresh on authentication errors
53
+ - Error parsing and exception mapping
54
+ - JSON serialization/deserialization
55
+
56
+ Parameters
57
+ ----------
58
+ config : dict, optional
59
+ DHCore environment configuration. If None, configuration will
60
+ be loaded from environment variables and configuration files.
61
+
62
+ Attributes
63
+ ----------
64
+ _api_builder : ClientDHCoreApiBuilder
65
+ Builds API endpoint URLs for different operations.
66
+ _key_builder : ClientDHCoreKeyBuilder
67
+ Builds storage keys for entities.
68
+ _params_builder : ClientDHCoreParametersBuilder
69
+ Builds request parameters for API calls.
70
+ _error_parser : ErrorParser
71
+ Parses backend responses and raises appropriate exceptions.
72
+ _configurator : ClientDHCoreConfigurator
73
+ Manages client configuration and authentication.
74
+
75
+ Notes
76
+ -----
77
+ Supported DHCore API versions: {MIN_API_LEVEL} to {MAX_API_LEVEL}
78
+ Current library API version: {LIB_VERSION}
79
+
80
+ Examples
81
+ --------
82
+ >>> from digitalhub.stores.client.api import get_client
83
+ >>> client = get_client(local=False)
84
+ >>> # Client is now ready for API operations
36
85
  """
37
86
 
38
87
  def __init__(self, config: dict | None = None) -> None:
88
+ """
89
+ Initialize DHCore client.
90
+
91
+ Creates a new DHCore client instance with all necessary components
92
+ for communicating with the DigitalHub Core backend. Sets up API
93
+ builders, configurators, and error handling.
94
+
95
+ Parameters
96
+ ----------
97
+ config : dict, optional
98
+ DHCore environment configuration. If None, configuration will
99
+ be loaded from environment variables and configuration files.
100
+
101
+ Returns
102
+ -------
103
+ None
104
+ """
39
105
  super().__init__()
40
106
 
41
107
  # API builder
@@ -52,7 +118,6 @@ class ClientDHCore(Client):
52
118
 
53
119
  # Client Configurator
54
120
  self._configurator = ClientDHCoreConfigurator()
55
- self._configurator.configure(config)
56
121
 
57
122
  ##############################
58
123
  # CRUD methods
@@ -62,19 +127,31 @@ class ClientDHCore(Client):
62
127
  """
63
128
  Create an object in DHCore.
64
129
 
130
+ Sends a POST request to the DHCore backend to create a new object.
131
+ Automatically sets the appropriate Content-Type header and serializes
132
+ the object to JSON format.
133
+
65
134
  Parameters
66
135
  ----------
67
136
  api : str
68
- Create API.
137
+ The API endpoint path for creating the object.
69
138
  obj : Any
70
- Object to create.
139
+ The object to create. Will be serialized to JSON.
71
140
  **kwargs : dict
72
- Keyword arguments to pass to the request.
141
+ Additional keyword arguments to pass to the HTTP request,
142
+ such as headers, params, etc.
73
143
 
74
144
  Returns
75
145
  -------
76
146
  dict
77
- Response object.
147
+ The created object as returned by the backend.
148
+
149
+ Raises
150
+ ------
151
+ BackendError
152
+ If the backend returns an error response.
153
+ ClientError
154
+ If there are client-side configuration issues.
78
155
  """
79
156
  if "headers" not in kwargs:
80
157
  kwargs["headers"] = {}
@@ -86,17 +163,27 @@ class ClientDHCore(Client):
86
163
  """
87
164
  Get an object from DHCore.
88
165
 
166
+ Sends a GET request to the DHCore backend to retrieve an existing object.
167
+
89
168
  Parameters
90
169
  ----------
91
170
  api : str
92
- Read API.
171
+ The API endpoint path for reading the object.
93
172
  **kwargs : dict
94
- Keyword arguments to pass to the request.
173
+ Additional keyword arguments to pass to the HTTP request,
174
+ such as headers, params, etc.
95
175
 
96
176
  Returns
97
177
  -------
98
178
  dict
99
- Response object.
179
+ The retrieved object as returned by the backend.
180
+
181
+ Raises
182
+ ------
183
+ BackendError
184
+ If the backend returns an error response.
185
+ EntityNotExistsError
186
+ If the requested object does not exist.
100
187
  """
101
188
  return self._prepare_call("GET", api, **kwargs)
102
189
 
@@ -104,19 +191,31 @@ class ClientDHCore(Client):
104
191
  """
105
192
  Update an object in DHCore.
106
193
 
194
+ Sends a PUT request to the DHCore backend to update an existing object.
195
+ Automatically sets the appropriate Content-Type header and serializes
196
+ the object to JSON format.
197
+
107
198
  Parameters
108
199
  ----------
109
200
  api : str
110
- Update API.
111
- obj : dict
112
- Object to update.
201
+ The API endpoint path for updating the object.
202
+ obj : Any
203
+ The updated object data. Will be serialized to JSON.
113
204
  **kwargs : dict
114
- Keyword arguments to pass to the request.
205
+ Additional keyword arguments to pass to the HTTP request,
206
+ such as headers, params, etc.
115
207
 
116
208
  Returns
117
209
  -------
118
210
  dict
119
- Response object.
211
+ The updated object as returned by the backend.
212
+
213
+ Raises
214
+ ------
215
+ BackendError
216
+ If the backend returns an error response.
217
+ EntityNotExistsError
218
+ If the object to update does not exist.
120
219
  """
121
220
  if "headers" not in kwargs:
122
221
  kwargs["headers"] = {}
@@ -128,17 +227,30 @@ class ClientDHCore(Client):
128
227
  """
129
228
  Delete an object from DHCore.
130
229
 
230
+ Sends a DELETE request to the DHCore backend to remove an object.
231
+ If the backend returns a boolean response, it will be wrapped in
232
+ a dictionary with a "deleted" key.
233
+
131
234
  Parameters
132
235
  ----------
133
236
  api : str
134
- Delete API.
237
+ The API endpoint path for deleting the object.
135
238
  **kwargs : dict
136
- Keyword arguments to pass to the request.
239
+ Additional keyword arguments to pass to the HTTP request,
240
+ such as headers, params, cascade options, etc.
137
241
 
138
242
  Returns
139
243
  -------
140
244
  dict
141
- Response object.
245
+ The deletion result. Either the backend response or
246
+ {"deleted": True/False} if backend returns a boolean.
247
+
248
+ Raises
249
+ ------
250
+ BackendError
251
+ If the backend returns an error response.
252
+ EntityNotExistsError
253
+ If the object to delete does not exist.
142
254
  """
143
255
  resp = self._prepare_call("DELETE", api, **kwargs)
144
256
  if isinstance(resp, bool):
@@ -149,21 +261,33 @@ class ClientDHCore(Client):
149
261
  """
150
262
  List objects from DHCore.
151
263
 
264
+ Sends GET requests to the DHCore backend to retrieve a paginated list
265
+ of objects. Automatically handles pagination by making multiple requests
266
+ until all objects are retrieved.
267
+
152
268
  Parameters
153
269
  ----------
154
270
  api : str
155
- List API.
271
+ The API endpoint path for listing objects.
156
272
  **kwargs : dict
157
- Keyword arguments to pass to the request.
273
+ Additional keyword arguments to pass to the HTTP request.
274
+ Can include 'params' dict with pagination parameters.
158
275
 
159
276
  Returns
160
277
  -------
161
278
  list[dict]
162
- Response objects.
163
- """
164
- if kwargs is None:
165
- kwargs = {}
279
+ A list containing all objects from all pages.
166
280
 
281
+ Raises
282
+ ------
283
+ BackendError
284
+ If the backend returns an error response.
285
+
286
+ Notes
287
+ -----
288
+ This method automatically handles pagination starting from page 0
289
+ and continues until all pages are retrieved.
290
+ """
167
291
  if "params" not in kwargs:
168
292
  kwargs["params"] = {}
169
293
 
@@ -185,19 +309,27 @@ class ClientDHCore(Client):
185
309
 
186
310
  def list_first_object(self, api: str, **kwargs) -> dict:
187
311
  """
188
- List first objects.
312
+ Get the first object from a list in DHCore.
313
+
314
+ Retrieves the first object from a paginated list by calling
315
+ list_objects and returning the first item.
189
316
 
190
317
  Parameters
191
318
  ----------
192
319
  api : str
193
- The api to list the objects with.
320
+ The API endpoint path for listing objects.
194
321
  **kwargs : dict
195
- Keyword arguments passed to the request.
322
+ Additional keyword arguments to pass to the HTTP request.
196
323
 
197
324
  Returns
198
325
  -------
199
326
  dict
200
- The list of objects.
327
+ The first object from the list.
328
+
329
+ Raises
330
+ ------
331
+ BackendError
332
+ If no objects are found or if the backend returns an error.
201
333
  """
202
334
  try:
203
335
  return self.list_objects(api, **kwargs)[0]
@@ -208,21 +340,35 @@ class ClientDHCore(Client):
208
340
  """
209
341
  Search objects from DHCore.
210
342
 
343
+ Performs a search query against the DHCore backend using Solr search
344
+ capabilities. Handles pagination and removes search highlights from
345
+ the returned objects.
346
+
211
347
  Parameters
212
348
  ----------
213
349
  api : str
214
- Search API.
350
+ The API endpoint path for searching objects (usually Solr search).
215
351
  **kwargs : dict
216
- Keyword arguments to pass to the request.
352
+ Additional keyword arguments to pass to the HTTP request.
353
+ Can include search parameters, filters, pagination options, etc.
217
354
 
218
355
  Returns
219
356
  -------
220
357
  list[dict]
221
- Response objects.
358
+ A list of objects matching the search criteria, with search
359
+ highlights removed.
360
+
361
+ Raises
362
+ ------
363
+ BackendError
364
+ If the backend returns an error response.
365
+
366
+ Notes
367
+ -----
368
+ This method sets default values for pagination (page=0, size=10)
369
+ and sorting (by metadata.updated descending) if not provided.
370
+ Search highlights are automatically removed from results.
222
371
  """
223
- if kwargs is None:
224
- kwargs = {}
225
-
226
372
  if "params" not in kwargs:
227
373
  kwargs["params"] = {}
228
374
 
@@ -262,73 +408,177 @@ class ClientDHCore(Client):
262
408
  """
263
409
  Prepare a call to the DHCore API.
264
410
 
411
+ Handles the preparation of an API call by checking configuration,
412
+ building the URL, and adding authentication parameters.
413
+
265
414
  Parameters
266
415
  ----------
267
416
  call_type : str
268
- The type of call to prepare.
417
+ The HTTP method type (GET, POST, PUT, DELETE, etc.).
269
418
  api : str
270
- The api to call.
419
+ The API endpoint path to call.
271
420
  **kwargs : dict
272
- Keyword arguments to pass to the request.
421
+ Additional keyword arguments to pass to the HTTP request.
273
422
 
274
423
  Returns
275
424
  -------
276
425
  dict
277
- Response object.
426
+ The response from the API call.
427
+
428
+ Raises
429
+ ------
430
+ ClientError
431
+ If the client configuration is invalid.
432
+ BackendError
433
+ If the backend returns an error response.
278
434
  """
279
435
  self._configurator.check_config()
280
- if kwargs is None:
281
- kwargs = {}
282
- url = self._configurator.build_url(api)
283
- kwargs = self._configurator.set_request_auth(kwargs)
284
- return self._make_call(call_type, url, **kwargs)
436
+ url = self._build_url(api)
437
+ full_kwargs = self._configurator.get_auth_parameters(kwargs)
438
+ return self._make_call(call_type, url, **full_kwargs)
285
439
 
286
- def _make_call(self, call_type: str, url: str, refresh_token: bool = True, **kwargs) -> dict:
440
+ def _build_url(self, api: str) -> str:
441
+ """
442
+ Build the complete URL for an API call.
443
+
444
+ Combines the configured endpoint with the API path to create
445
+ the full URL for the HTTP request.
446
+
447
+ Parameters
448
+ ----------
449
+ api : str
450
+ The API endpoint path. Leading slashes are automatically handled.
451
+
452
+ Returns
453
+ -------
454
+ str
455
+ The complete URL for the API call.
456
+
457
+ Notes
458
+ -----
459
+ This method automatically removes leading slashes from the API path
460
+ to ensure proper URL construction.
461
+ """
462
+ endpoint = self._configurator.get_endpoint()
463
+ return f"{endpoint}/{api.removeprefix('/')}"
464
+
465
+ def _make_call(self, call_type: str, url: str, refresh: bool = True, **kwargs) -> dict:
287
466
  """
288
467
  Make a call to the DHCore API.
289
468
 
469
+ Executes the actual HTTP request to the DHCore backend, handles
470
+ API version checking, automatic token refresh on 401 errors,
471
+ and error parsing.
472
+
290
473
  Parameters
291
474
  ----------
292
475
  call_type : str
293
- The type of call to make.
476
+ The HTTP method type (GET, POST, PUT, DELETE, etc.).
294
477
  url : str
295
- The URL to call.
478
+ The complete URL to call.
479
+ refresh : bool, default True
480
+ Whether to attempt token refresh on authentication errors.
481
+ Set to False to prevent infinite recursion during refresh.
296
482
  **kwargs : dict
297
- Keyword arguments to pass to the request.
483
+ Additional keyword arguments to pass to the HTTP request.
298
484
 
299
485
  Returns
300
486
  -------
301
487
  dict
302
- Response object.
488
+ The parsed response from the backend as a dictionary.
489
+
490
+ Raises
491
+ ------
492
+ ClientError
493
+ If the backend API version is not supported.
494
+ BackendError
495
+ If the backend returns an error response or response parsing fails.
496
+ UnauthorizedError
497
+ If authentication fails and token refresh is not possible.
498
+
499
+ Notes
500
+ -----
501
+ This method automatically handles:
502
+ - API version compatibility checking
503
+ - OAuth2 token refresh on 401 errors
504
+ - Response parsing and error handling
505
+ - 60-second timeout for all requests
303
506
  """
304
507
  # Call the API
305
508
  response = request(call_type, url, timeout=60, **kwargs)
306
509
 
307
510
  # Evaluate DHCore API version
308
- self._configurator.check_core_version(response)
511
+ self._check_core_version(response)
309
512
 
310
- # Handle token refresh
311
- if response.status_code in [401] and refresh_token and self._configurator.oauth2_auth():
312
- self._configurator.get_new_access_token()
313
- kwargs = self._configurator.set_request_auth(kwargs)
314
- return self._make_call(call_type, url, refresh_token=False, **kwargs)
513
+ # Handle token refresh (redo call)
514
+ if (response.status_code in [401]) and (refresh) and self._configurator.refreshable_auth_types():
515
+ self._configurator.refresh_credentials(change_origin=True)
516
+ kwargs = self._configurator.get_auth_parameters(kwargs)
517
+ return self._make_call(call_type, url, refresh=False, **kwargs)
315
518
 
316
519
  self._error_parser.parse(response)
317
520
  return self._dictify_response(response)
318
521
 
522
+ def _check_core_version(self, response: Response) -> None:
523
+ """
524
+ Check DHCore API version compatibility.
525
+
526
+ Validates that the DHCore backend API version is compatible with
527
+ this client library. Issues warnings if the backend version is
528
+ newer than the library version.
529
+
530
+ Parameters
531
+ ----------
532
+ response : Response
533
+ The HTTP response object containing the X-Api-Level header.
534
+
535
+ Returns
536
+ -------
537
+ None
538
+
539
+ Raises
540
+ ------
541
+ ClientError
542
+ If the backend API level is not supported by this client.
543
+
544
+ Notes
545
+ -----
546
+ Supported API levels: {MIN_API_LEVEL} to {MAX_API_LEVEL}
547
+ Current library version: {LIB_VERSION}
548
+ """
549
+ if "X-Api-Level" in response.headers:
550
+ core_api_level = int(response.headers["X-Api-Level"])
551
+ if not (MIN_API_LEVEL <= core_api_level <= MAX_API_LEVEL):
552
+ raise ClientError("Backend API level not supported.")
553
+ if LIB_VERSION < core_api_level:
554
+ warn("Backend API level is higher than library version. You should consider updating the library.")
555
+
319
556
  def _dictify_response(self, response: Response) -> dict:
320
557
  """
321
- Return dict from response.
558
+ Parse HTTP response to dictionary.
559
+
560
+ Converts the HTTP response body from JSON to a Python dictionary.
561
+ Handles empty responses gracefully.
322
562
 
323
563
  Parameters
324
564
  ----------
325
565
  response : Response
326
- The response object.
566
+ The HTTP response object to parse.
327
567
 
328
568
  Returns
329
569
  -------
330
570
  dict
331
- The parsed response object.
571
+ The parsed response body as a dictionary. Returns empty dict
572
+ if response body is empty.
573
+
574
+ Raises
575
+ ------
576
+ BackendError
577
+ If the response cannot be parsed as JSON.
578
+
579
+ Notes
580
+ -----
581
+ Empty response bodies are treated as valid and return an empty dict.
332
582
  """
333
583
  try:
334
584
  return response.json()
@@ -344,11 +594,20 @@ class ClientDHCore(Client):
344
594
  @staticmethod
345
595
  def is_local() -> bool:
346
596
  """
347
- Declare if Client is local.
597
+ Check if this client operates locally.
598
+
599
+ Returns a flag indicating whether this client instance operates
600
+ on local data or communicates with a remote backend.
348
601
 
349
602
  Returns
350
603
  -------
351
604
  bool
352
- False
605
+ False, indicating this client communicates with a remote
606
+ DHCore backend, not local storage.
607
+
608
+ Notes
609
+ -----
610
+ This method is used to distinguish between ClientDHCore (returns False)
611
+ and ClientLocal (returns True) implementations.
353
612
  """
354
613
  return False