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
@@ -0,0 +1,210 @@
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
+
9
+ from digitalhub.stores.credentials.enums import CredsOrigin
10
+ from digitalhub.stores.credentials.handler import creds_handler
11
+ from digitalhub.utils.exceptions import ConfigError
12
+
13
+
14
+ class Configurator:
15
+ """
16
+ Base configurator for credentials management.
17
+
18
+ Attributes
19
+ ----------
20
+ keys : list of str
21
+ List of credential keys to manage.
22
+ required_keys : list of str
23
+ List of required credential keys.
24
+ _env : str
25
+ Environment origin identifier.
26
+ _file : str
27
+ File origin identifier.
28
+ _creds_handler : object
29
+ Credentials handler instance.
30
+ """
31
+
32
+ # Must be set in implementing class
33
+ keys: list[str] = []
34
+ required_keys: list[str] = []
35
+
36
+ # Origin of the credentials
37
+ _env = CredsOrigin.ENV.value
38
+ _file = CredsOrigin.FILE.value
39
+
40
+ # Credentials handler
41
+ _creds_handler = creds_handler
42
+
43
+ def __init__(self):
44
+ self._current_profile = self._creds_handler.get_current_profile()
45
+ self.load_configs()
46
+ self._changed_origin = False
47
+ self._origin = self.set_origin()
48
+
49
+ ##############################
50
+ # Configuration
51
+ ##############################
52
+
53
+ def load_configs(self) -> None:
54
+ """
55
+ Load the configuration from both environment and file sources.
56
+
57
+ Returns
58
+ -------
59
+ None
60
+ """
61
+ self.load_env_vars()
62
+ self.load_file_vars()
63
+
64
+ @abstractmethod
65
+ def load_env_vars(self) -> None:
66
+ ...
67
+
68
+ @abstractmethod
69
+ def load_file_vars(self) -> None:
70
+ ...
71
+
72
+ def check_config(self) -> None:
73
+ """
74
+ Check if the current profile has changed and reload
75
+ the file credentials if needed.
76
+
77
+ Returns
78
+ -------
79
+ None
80
+ """
81
+ if (current := self._creds_handler.get_current_profile()) != self._current_profile:
82
+ self.load_file_vars()
83
+ self._current_profile = current
84
+
85
+ def set_origin(self) -> str:
86
+ """
87
+ Determine the default origin for credentials (env or file).
88
+
89
+ Returns
90
+ -------
91
+ str
92
+ The selected origin ('env' or 'file').
93
+
94
+ Raises
95
+ ------
96
+ ConfigError
97
+ If required credentials are missing in both sources.
98
+ """
99
+ origin = self._env
100
+
101
+ env_creds = self._creds_handler.get_credentials(self._env)
102
+ missing_env = self._check_credentials(env_creds)
103
+
104
+ file_creds = self._creds_handler.get_credentials(self._file)
105
+ missing_file = self._check_credentials(file_creds)
106
+
107
+ msg = ""
108
+ if missing_env:
109
+ msg = f"Missing required vars in env: {', '.join(missing_env)}"
110
+ origin = self._file
111
+ self._changed_origin = True
112
+ elif missing_file:
113
+ msg += f"Missing required vars in .dhcore.ini file: {', '.join(missing_file)}"
114
+
115
+ if missing_env and missing_file:
116
+ raise ConfigError(msg)
117
+
118
+ return origin
119
+
120
+ def eval_change_origin(self) -> None:
121
+ """
122
+ Attempt to change the origin of credentials.
123
+ Raise error if already evaluated.
124
+
125
+ Returns
126
+ -------
127
+ None
128
+ """
129
+ try:
130
+ self.change_origin()
131
+ except ConfigError:
132
+ raise ConfigError("Credentials origin already evaluated. Please check your credentials.")
133
+
134
+ def change_origin(self) -> None:
135
+ """
136
+ Change the origin of credentials from env to file or vice versa.
137
+
138
+ Returns
139
+ -------
140
+ None
141
+ """
142
+ if self._changed_origin:
143
+ raise ConfigError("Origin has already been changed.")
144
+ if self._origin == self._env:
145
+ self.change_to_file()
146
+ self.change_to_env()
147
+
148
+ def change_to_file(self) -> None:
149
+ """
150
+ Set the credentials origin to file.
151
+
152
+ Returns
153
+ -------
154
+ None
155
+ """
156
+ if self._origin == self._env:
157
+ self._changed_origin = True
158
+ self._origin = CredsOrigin.FILE.value
159
+
160
+ def change_to_env(self) -> None:
161
+ """
162
+ Set the credentials origin to environment.
163
+
164
+ Returns
165
+ -------
166
+ None
167
+ """
168
+ if self._origin == self._file:
169
+ self._changed_origin = True
170
+ self._origin = CredsOrigin.ENV.value
171
+
172
+ ##############################
173
+ # Credentials
174
+ ##############################
175
+
176
+ def get_credentials(self, origin: str) -> dict:
177
+ """
178
+ Retrieve credentials for the specified origin.
179
+
180
+ Parameters
181
+ ----------
182
+ origin : str
183
+ The origin to retrieve credentials from ('env' or 'file').
184
+
185
+ Returns
186
+ -------
187
+ dict
188
+ Dictionary of credentials.
189
+ """
190
+ return self._creds_handler.get_credentials(origin)
191
+
192
+ def _check_credentials(self, creds: dict) -> list[str]:
193
+ """
194
+ Check for missing required credentials in a dictionary.
195
+
196
+ Parameters
197
+ ----------
198
+ creds : dict
199
+ Dictionary of credentials to check.
200
+
201
+ Returns
202
+ -------
203
+ list of str
204
+ List of missing required credential keys.
205
+ """
206
+ missing_keys = []
207
+ for k, v in creds.items():
208
+ if v is None and k in self.required_keys:
209
+ missing_keys.append(k)
210
+ return missing_keys
@@ -0,0 +1,68 @@
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 CredsOrigin(Enum):
11
+ """
12
+ Credential origins for configuration.
13
+
14
+ Attributes
15
+ ----------
16
+ ENV : str
17
+ Credentials from environment variables.
18
+ FILE : str
19
+ Credentials from configuration file.
20
+ """
21
+
22
+ ENV = "env"
23
+ FILE = "file"
24
+
25
+
26
+ class SetCreds(Enum):
27
+ """
28
+ Supported credential environments.
29
+ """
30
+
31
+ DEFAULT = "__default"
32
+ DH_PROFILE = "DH_NAME"
33
+
34
+
35
+ class CredsEnvVar(Enum):
36
+ """
37
+ Supported credential environment variables.
38
+ """
39
+
40
+ # S3
41
+ S3_ENDPOINT_URL = "AWS_ENDPOINT_URL"
42
+ S3_ACCESS_KEY_ID = "AWS_ACCESS_KEY_ID"
43
+ S3_SECRET_ACCESS_KEY = "AWS_SECRET_ACCESS_KEY"
44
+ S3_SESSION_TOKEN = "AWS_SESSION_TOKEN"
45
+ S3_REGION = "AWS_REGION"
46
+ S3_SIGNATURE_VERSION = "S3_SIGNATURE_VERSION"
47
+ S3_CREDENTIALS_EXPIRATION = "AWS_CREDENTIALS_EXPIRATION"
48
+ S3_PATH_STYLE = "S3_PATH_STYLE"
49
+
50
+ # SQL
51
+ DB_HOST = "DB_HOST"
52
+ DB_PORT = "DB_PORT"
53
+ DB_USERNAME = "DB_USERNAME"
54
+ DB_PASSWORD = "DB_PASSWORD"
55
+ DB_DATABASE = "DB_DATABASE"
56
+ DB_PLATFORM = "DB_PLATFORM"
57
+ DB_PG_SCHEMA = "DB_SCHEMA"
58
+
59
+ # DHCORE
60
+ DHCORE_ENDPOINT = "DHCORE_ENDPOINT"
61
+ DHCORE_ISSUER = "DHCORE_ISSUER"
62
+ DHCORE_USER = "DHCORE_USER"
63
+ DHCORE_PASSWORD = "DHCORE_PASSWORD"
64
+ DHCORE_CLIENT_ID = "DHCORE_CLIENT_ID"
65
+ DHCORE_ACCESS_TOKEN = "DHCORE_ACCESS_TOKEN"
66
+ DHCORE_REFRESH_TOKEN = "DHCORE_REFRESH_TOKEN"
67
+ DHCORE_PERSONAL_ACCESS_TOKEN = "DHCORE_PERSONAL_ACCESS_TOKEN"
68
+ DHCORE_WORKFLOW_IMAGE = "DHCORE_WORKFLOW_IMAGE"
@@ -0,0 +1,176 @@
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 os
8
+
9
+ from digitalhub.stores.credentials.enums import SetCreds
10
+ from digitalhub.stores.credentials.ini_module import (
11
+ load_file,
12
+ load_key,
13
+ load_profile,
14
+ set_current_profile,
15
+ write_config,
16
+ )
17
+ from digitalhub.stores.credentials.store import CredentialsStore
18
+
19
+
20
+ class CredentialHandler:
21
+ """
22
+ Handler for configuring clients and managing credentials.
23
+
24
+ Attributes
25
+ ----------
26
+ _creds_store : CredentialsStore
27
+ Store for credentials.
28
+ _profile : str
29
+ Current credentials profile name.
30
+ """
31
+
32
+ def __init__(self) -> None:
33
+ self._creds_store = CredentialsStore()
34
+ self._profile = self._read_current_profile()
35
+
36
+ @staticmethod
37
+ def _read_current_profile() -> str:
38
+ """
39
+ Read the current credentials profile name.
40
+
41
+ Returns
42
+ -------
43
+ str
44
+ Name of the credentials profile.
45
+ """
46
+ profile = os.getenv(SetCreds.DH_PROFILE.value)
47
+ if profile is not None:
48
+ return profile
49
+ file = load_file()
50
+ profile = load_profile(file)
51
+ if profile is not None:
52
+ return profile
53
+ return SetCreds.DEFAULT.value
54
+
55
+ ##############################
56
+ # Public methods
57
+ ##############################
58
+
59
+ def set_current_profile(self, creds_set: str) -> None:
60
+ """
61
+ Set the current credentials profile name.
62
+
63
+ Parameters
64
+ ----------
65
+ creds_set : str
66
+ Name of the credentials profile to set.
67
+
68
+ Returns
69
+ -------
70
+ None
71
+ """
72
+ self._profile = creds_set
73
+ set_current_profile(creds_set)
74
+
75
+ def get_current_profile(self) -> str:
76
+ """
77
+ Get the current credentials profile name.
78
+
79
+ Returns
80
+ -------
81
+ str
82
+ Name of the current credentials profile.
83
+ """
84
+ return self._profile
85
+
86
+ def load_from_env(self, vars: list[str]) -> dict:
87
+ """
88
+ Load variables from environment.
89
+
90
+ Parameters
91
+ ----------
92
+ vars : list of str
93
+ List of environment variable names to load.
94
+
95
+ Returns
96
+ -------
97
+ dict
98
+ Dictionary of environment variable values.
99
+ """
100
+ return {var: os.getenv(var) for var in vars}
101
+
102
+ def load_from_file(self, vars: list[str]) -> dict:
103
+ """
104
+ Load variables from credentials config file.
105
+
106
+ Parameters
107
+ ----------
108
+ vars : list of str
109
+ List of variable names to load from file.
110
+
111
+ Returns
112
+ -------
113
+ dict
114
+ Dictionary of variable values from file.
115
+ """
116
+ file = load_file()
117
+ profile = load_profile(file)
118
+ if profile is not None:
119
+ self._profile = profile
120
+ return {var: load_key(file, self._profile, var) for var in vars}
121
+
122
+ def write_env(self, creds: dict) -> None:
123
+ """
124
+ Write credentials to the .dhcore file for the current profile.
125
+
126
+ Parameters
127
+ ----------
128
+ creds : dict
129
+ Credentials to write.
130
+
131
+ Returns
132
+ -------
133
+ None
134
+ """
135
+ write_config(creds, self._profile)
136
+
137
+ ##############################
138
+ # Credentials store methods
139
+ ##############################
140
+
141
+ def set_credentials(self, origin: str, creds: dict) -> None:
142
+ """
143
+ Set credentials for the current profile and origin.
144
+
145
+ Parameters
146
+ ----------
147
+ origin : str
148
+ The origin of the credentials ('env' or 'file').
149
+ creds : dict
150
+ Credentials to set.
151
+
152
+ Returns
153
+ -------
154
+ None
155
+ """
156
+ self._creds_store.set_credentials(self._profile, origin, creds)
157
+
158
+ def get_credentials(self, origin: str) -> dict:
159
+ """
160
+ Get credentials for the current profile from the specified origin.
161
+
162
+ Parameters
163
+ ----------
164
+ origin : str
165
+ The origin to get credentials from ('env' or 'file').
166
+
167
+ Returns
168
+ -------
169
+ dict
170
+ Dictionary of credentials.
171
+ """
172
+ return self._creds_store.get_credentials(self._profile, origin)
173
+
174
+
175
+ # Define global credential handler
176
+ creds_handler = CredentialHandler()
@@ -0,0 +1,164 @@
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 configparser import ConfigParser
8
+ from pathlib import Path
9
+
10
+ from digitalhub.utils.exceptions import ClientError
11
+
12
+ # File where to write credementials
13
+ ENV_FILE = Path.home() / ".dhcore.ini"
14
+
15
+
16
+ def load_file() -> ConfigParser:
17
+ """
18
+ Load the credentials configuration from the .dhcore.ini file.
19
+
20
+ Returns
21
+ -------
22
+ ConfigParser
23
+ Parsed configuration file object.
24
+
25
+ Raises
26
+ ------
27
+ ClientError
28
+ If the file cannot be read.
29
+ """
30
+ try:
31
+ file = ConfigParser()
32
+ file.read(ENV_FILE)
33
+ return file
34
+ except Exception as e:
35
+ raise ClientError(f"Failed to read env file: {e}")
36
+
37
+
38
+ def load_profile(file: ConfigParser) -> str | None:
39
+ """
40
+ Load the current credentials profile name from the .dhcore.ini file.
41
+
42
+ Parameters
43
+ ----------
44
+ file : ConfigParser
45
+ Parsed configuration file object.
46
+
47
+ Returns
48
+ -------
49
+ str or None
50
+ Name of the credentials profile, or None if not found.
51
+ """
52
+ try:
53
+ return file["DEFAULT"]["current_environment"]
54
+ except KeyError:
55
+ return
56
+
57
+
58
+ def load_key(file: ConfigParser, profile: str, key: str) -> str | None:
59
+ """
60
+ Load a specific key value from the credentials profile in the
61
+ .dhcore.ini file.
62
+
63
+ Parameters
64
+ ----------
65
+ file : ConfigParser
66
+ Parsed configuration file object.
67
+ profile : str
68
+ Name of the credentials profile.
69
+ key : str
70
+ Name of the key to retrieve.
71
+
72
+ Returns
73
+ -------
74
+ str or None
75
+ Value of the key, or None if not found.
76
+ """
77
+ try:
78
+ return file[profile][key]
79
+ except KeyError:
80
+ return
81
+
82
+
83
+ def write_config(creds: dict, environment: str) -> None:
84
+ """
85
+ Write credentials to the .dhcore.ini file for the specified environment.
86
+ Overwrites any existing values for that environment.
87
+
88
+ Parameters
89
+ ----------
90
+ creds : dict
91
+ Dictionary of credentials to write.
92
+ environment : str
93
+ Name of the credentials profile/environment.
94
+
95
+ Returns
96
+ -------
97
+ None
98
+
99
+ Raises
100
+ ------
101
+ ClientError
102
+ If the file cannot be written.
103
+ """
104
+ try:
105
+ cfg = load_file()
106
+
107
+ sections = cfg.sections()
108
+ if environment not in sections:
109
+ cfg.add_section(environment)
110
+
111
+ cfg["DEFAULT"]["current_environment"] = environment
112
+ for k, v in creds.items():
113
+ cfg[environment][k] = str(v)
114
+
115
+ ENV_FILE.touch(exist_ok=True)
116
+ with open(ENV_FILE, "w") as inifile:
117
+ cfg.write(inifile)
118
+
119
+ except Exception as e:
120
+ raise ClientError(f"Failed to write env file: {e}")
121
+
122
+
123
+ def set_current_profile(environment: str) -> None:
124
+ """
125
+ Set the current credentials profile in the .dhcore.ini file.
126
+
127
+ Parameters
128
+ ----------
129
+ environment : str
130
+ Name of the credentials profile to set as current.
131
+
132
+ Returns
133
+ -------
134
+ None
135
+
136
+ Raises
137
+ ------
138
+ ClientError
139
+ If the file cannot be written.
140
+ """
141
+ try:
142
+ cfg = load_file()
143
+ cfg["DEFAULT"]["current_environment"] = environment
144
+ with open(ENV_FILE, "w") as inifile:
145
+ cfg.write(inifile)
146
+
147
+ except Exception as e:
148
+ raise ClientError(f"Failed to write env file: {e}")
149
+
150
+
151
+ def read_env_from_file() -> str | None:
152
+ """
153
+ Read the current credentials profile name from the .dhcore.ini file.
154
+
155
+ Returns
156
+ -------
157
+ str or None
158
+ Name of the current credentials profile, or None if not found.
159
+ """
160
+ try:
161
+ cfg = load_file()
162
+ return cfg["DEFAULT"]["current_environment"]
163
+ except Exception:
164
+ return None
@@ -0,0 +1,81 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from digitalhub.stores.credentials.enums import CredsOrigin
10
+
11
+
12
+ class CredentialsStore:
13
+ """
14
+ Store and retrieve credentials for different profiles and origins.
15
+
16
+ Attributes
17
+ ----------
18
+ _file_creds : dict of str to dict
19
+ Credentials stored by profile from file origin.
20
+ _env_creds : dict of str to Any
21
+ Credentials stored from environment origin.
22
+ """
23
+
24
+ def __init__(self) -> None:
25
+ self._file_creds: dict[str, dict[str, Any]] = {}
26
+ self._env_creds: dict[str, Any] = {}
27
+
28
+ def set_credentials(
29
+ self,
30
+ profile: str,
31
+ origin: str,
32
+ credentials: dict[str, Any],
33
+ ) -> None:
34
+ """
35
+ Set all credentials for a given profile and origin.
36
+
37
+ Parameters
38
+ ----------
39
+ profile : str
40
+ Name of the credentials profile.
41
+ origin : str
42
+ Origin of the credentials ('env' or 'file').
43
+ credentials : dict of str to Any
44
+ Dictionary of credentials to set.
45
+
46
+ Returns
47
+ -------
48
+ None
49
+ """
50
+ if origin == CredsOrigin.ENV.value:
51
+ for key, value in credentials.items():
52
+ self._env_creds[key] = value
53
+ return
54
+ if profile not in self._file_creds:
55
+ self._file_creds[profile] = {}
56
+ for key, value in credentials.items():
57
+ self._file_creds[profile][key] = value
58
+
59
+ def get_credentials(
60
+ self,
61
+ profile: str,
62
+ origin: str,
63
+ ) -> dict[str, Any]:
64
+ """
65
+ Get all credentials for a given profile and origin.
66
+
67
+ Parameters
68
+ ----------
69
+ profile : str
70
+ Name of the credentials profile.
71
+ origin : str
72
+ Origin of the credentials ('env' or 'file').
73
+
74
+ Returns
75
+ -------
76
+ dict of str to Any
77
+ Dictionary of credentials for the profile and origin.
78
+ """
79
+ if origin == CredsOrigin.ENV.value:
80
+ return self._env_creds
81
+ return self._file_creds[profile]
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0