digitalhub 0.13.0b3__py3-none-any.whl → 0.14.0b0__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.
- digitalhub/__init__.py +3 -8
- digitalhub/entities/_base/_base/entity.py +0 -11
- digitalhub/entities/_base/entity/builder.py +5 -5
- digitalhub/entities/_base/executable/entity.py +1 -1
- digitalhub/entities/_base/runtime_entity/builder.py +53 -18
- digitalhub/entities/_commons/metrics.py +64 -30
- digitalhub/entities/_commons/utils.py +100 -30
- digitalhub/entities/_processors/base.py +160 -81
- digitalhub/entities/_processors/context.py +424 -224
- digitalhub/entities/_processors/utils.py +77 -33
- digitalhub/entities/artifact/crud.py +20 -4
- digitalhub/entities/artifact/utils.py +29 -14
- digitalhub/entities/dataitem/crud.py +20 -4
- digitalhub/entities/dataitem/table/entity.py +0 -21
- digitalhub/entities/dataitem/utils.py +84 -34
- digitalhub/entities/function/_base/entity.py +1 -1
- digitalhub/entities/function/crud.py +15 -4
- digitalhub/entities/model/_base/entity.py +21 -1
- digitalhub/entities/model/crud.py +21 -5
- digitalhub/entities/model/utils.py +29 -14
- digitalhub/entities/project/_base/entity.py +65 -33
- digitalhub/entities/project/crud.py +8 -1
- digitalhub/entities/run/_base/entity.py +21 -1
- digitalhub/entities/run/crud.py +22 -5
- digitalhub/entities/secret/crud.py +22 -5
- digitalhub/entities/task/crud.py +22 -5
- digitalhub/entities/trigger/crud.py +20 -4
- digitalhub/entities/workflow/_base/entity.py +1 -1
- digitalhub/entities/workflow/crud.py +15 -4
- digitalhub/factory/enums.py +18 -0
- digitalhub/factory/factory.py +136 -57
- digitalhub/factory/utils.py +3 -54
- digitalhub/stores/client/api.py +6 -10
- digitalhub/stores/client/builder.py +3 -3
- digitalhub/stores/client/dhcore/client.py +104 -162
- digitalhub/stores/client/dhcore/configurator.py +92 -289
- digitalhub/stores/client/dhcore/enums.py +0 -16
- digitalhub/stores/client/dhcore/params_builder.py +41 -83
- digitalhub/stores/client/dhcore/utils.py +14 -22
- digitalhub/stores/client/local/client.py +77 -45
- digitalhub/stores/credentials/enums.py +1 -0
- digitalhub/stores/credentials/ini_module.py +0 -16
- digitalhub/stores/data/api.py +1 -1
- digitalhub/stores/data/builder.py +66 -4
- digitalhub/stores/data/local/store.py +0 -103
- digitalhub/stores/data/s3/configurator.py +60 -6
- digitalhub/stores/data/s3/store.py +44 -2
- digitalhub/stores/data/sql/configurator.py +57 -7
- digitalhub/stores/data/sql/store.py +184 -78
- digitalhub/utils/file_utils.py +0 -17
- digitalhub/utils/generic_utils.py +1 -2
- digitalhub/utils/store_utils.py +44 -0
- {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.0b0.dist-info}/METADATA +3 -2
- {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.0b0.dist-info}/RECORD +63 -65
- digitalhub/entities/_commons/types.py +0 -9
- digitalhub/entities/task/_base/utils.py +0 -22
- digitalhub/stores/client/dhcore/models.py +0 -40
- digitalhub/stores/data/s3/utils.py +0 -78
- /digitalhub/entities/{_base/entity/_constructors → _constructors}/__init__.py +0 -0
- /digitalhub/entities/{_base/entity/_constructors → _constructors}/metadata.py +0 -0
- /digitalhub/entities/{_base/entity/_constructors → _constructors}/name.py +0 -0
- /digitalhub/entities/{_base/entity/_constructors → _constructors}/spec.py +0 -0
- /digitalhub/entities/{_base/entity/_constructors → _constructors}/status.py +0 -0
- /digitalhub/entities/{_base/entity/_constructors → _constructors}/uuid.py +0 -0
- {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.0b0.dist-info}/WHEEL +0 -0
- {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.0b0.dist-info}/licenses/AUTHORS +0 -0
- {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.0b0.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
import shutil
|
|
8
7
|
from pathlib import Path
|
|
9
8
|
from typing import Any
|
|
10
9
|
|
|
@@ -180,105 +179,3 @@ class LocalStore(Store):
|
|
|
180
179
|
reader = get_reader_by_object(df)
|
|
181
180
|
reader.write_df(df, dst, extension=extension, **kwargs)
|
|
182
181
|
return dst
|
|
183
|
-
|
|
184
|
-
##############################
|
|
185
|
-
# Private I/O methods
|
|
186
|
-
##############################
|
|
187
|
-
|
|
188
|
-
def _get_src_dst_files(self, src: Path, dst: Path) -> list[str]:
|
|
189
|
-
"""
|
|
190
|
-
Copy files from source to destination.
|
|
191
|
-
|
|
192
|
-
Parameters
|
|
193
|
-
----------
|
|
194
|
-
src : Path
|
|
195
|
-
The source path.
|
|
196
|
-
dst : Path
|
|
197
|
-
The destination path.
|
|
198
|
-
|
|
199
|
-
Returns
|
|
200
|
-
-------
|
|
201
|
-
list[str]
|
|
202
|
-
Returns the list of destination and source paths of the
|
|
203
|
-
copied files.
|
|
204
|
-
"""
|
|
205
|
-
return [self._get_src_dst_file(i, dst) for i in src.rglob("*") if i.is_file()]
|
|
206
|
-
|
|
207
|
-
def _get_src_dst_file(self, src: Path, dst: Path) -> str:
|
|
208
|
-
"""
|
|
209
|
-
Copy file from source to destination.
|
|
210
|
-
|
|
211
|
-
Parameters
|
|
212
|
-
----------
|
|
213
|
-
src : Path
|
|
214
|
-
The source path.
|
|
215
|
-
dst : Path
|
|
216
|
-
The destination path.
|
|
217
|
-
|
|
218
|
-
Returns
|
|
219
|
-
-------
|
|
220
|
-
str
|
|
221
|
-
"""
|
|
222
|
-
dst_pth = self._copy_file(src, dst, True)
|
|
223
|
-
return str(dst_pth), str(src)
|
|
224
|
-
|
|
225
|
-
def _copy_dir(self, src: Path, dst: Path, overwrite: bool) -> list[str]:
|
|
226
|
-
"""
|
|
227
|
-
Download file from source to destination.
|
|
228
|
-
|
|
229
|
-
Parameters
|
|
230
|
-
----------
|
|
231
|
-
src : Path
|
|
232
|
-
The source path.
|
|
233
|
-
dst : Path
|
|
234
|
-
The destination path.
|
|
235
|
-
|
|
236
|
-
Returns
|
|
237
|
-
-------
|
|
238
|
-
list[str]
|
|
239
|
-
"""
|
|
240
|
-
dst = self._rebuild_path(dst, src)
|
|
241
|
-
shutil.copytree(src, dst, dirs_exist_ok=overwrite)
|
|
242
|
-
return [str(i) for i in dst.rglob("*") if i.is_file()]
|
|
243
|
-
|
|
244
|
-
def _copy_file(self, src: Path, dst: Path, overwrite: bool) -> str:
|
|
245
|
-
"""
|
|
246
|
-
Copy file from source to destination.
|
|
247
|
-
|
|
248
|
-
Parameters
|
|
249
|
-
----------
|
|
250
|
-
src : Path
|
|
251
|
-
The source path.
|
|
252
|
-
dst : Path
|
|
253
|
-
The destination path.
|
|
254
|
-
|
|
255
|
-
Returns
|
|
256
|
-
-------
|
|
257
|
-
str
|
|
258
|
-
"""
|
|
259
|
-
dst = self._rebuild_path(dst, src)
|
|
260
|
-
self._check_overwrite(dst, overwrite)
|
|
261
|
-
return str(shutil.copy2(src, dst))
|
|
262
|
-
|
|
263
|
-
def _rebuild_path(self, dst: Path, src: Path) -> Path:
|
|
264
|
-
"""
|
|
265
|
-
Rebuild path.
|
|
266
|
-
|
|
267
|
-
Parameters
|
|
268
|
-
----------
|
|
269
|
-
dst : Path
|
|
270
|
-
The destination path.
|
|
271
|
-
src : Path
|
|
272
|
-
The source path.
|
|
273
|
-
|
|
274
|
-
Returns
|
|
275
|
-
-------
|
|
276
|
-
Path
|
|
277
|
-
The rebuilt path.
|
|
278
|
-
"""
|
|
279
|
-
if dst.is_dir():
|
|
280
|
-
if src.is_absolute():
|
|
281
|
-
raise StoreError("Source must be a relative path if the destination is a directory.")
|
|
282
|
-
dst = dst / src
|
|
283
|
-
self._build_path(dst)
|
|
284
|
-
return dst
|
|
@@ -74,12 +74,23 @@ class S3StoreConfigurator(Configurator):
|
|
|
74
74
|
dict
|
|
75
75
|
Dictionary containing S3 credentials and configuration.
|
|
76
76
|
"""
|
|
77
|
-
creds = self.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
creds = self.evaluate_credentials()
|
|
78
|
+
return self.get_creds_dict(creds)
|
|
79
|
+
|
|
80
|
+
def get_creds_dict(self, creds: dict) -> dict:
|
|
81
|
+
"""
|
|
82
|
+
Returns a dictionary containing the S3 credentials.
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
creds : dict
|
|
87
|
+
The credentials dictionary.
|
|
88
|
+
|
|
89
|
+
Returns
|
|
90
|
+
-------
|
|
91
|
+
dict
|
|
92
|
+
A dictionary containing the S3 credentials.
|
|
93
|
+
"""
|
|
83
94
|
return {
|
|
84
95
|
"endpoint_url": creds[CredsEnvVar.S3_ENDPOINT_URL.value],
|
|
85
96
|
"aws_access_key_id": creds[CredsEnvVar.S3_ACCESS_KEY_ID.value],
|
|
@@ -91,6 +102,49 @@ class S3StoreConfigurator(Configurator):
|
|
|
91
102
|
),
|
|
92
103
|
}
|
|
93
104
|
|
|
105
|
+
def evaluate_credentials(self) -> dict:
|
|
106
|
+
"""
|
|
107
|
+
Evaluates and returns the current valid credentials.
|
|
108
|
+
If the credentials are expired and were loaded from file,
|
|
109
|
+
it refreshes them.
|
|
110
|
+
|
|
111
|
+
Returns
|
|
112
|
+
-------
|
|
113
|
+
dict
|
|
114
|
+
The current valid credentials.
|
|
115
|
+
"""
|
|
116
|
+
creds = self.get_credentials(self._origin)
|
|
117
|
+
expired = creds[CredsEnvVar.S3_CREDENTIALS_EXPIRATION.value]
|
|
118
|
+
if self._origin == self._file and self._is_expired(expired):
|
|
119
|
+
refresh_token()
|
|
120
|
+
self.load_file_vars()
|
|
121
|
+
creds = self.get_credentials(self._origin)
|
|
122
|
+
return creds
|
|
123
|
+
|
|
124
|
+
def get_file_config(self) -> dict:
|
|
125
|
+
"""
|
|
126
|
+
Returns the credentials loaded from file.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
dict
|
|
131
|
+
The credentials loaded from file.
|
|
132
|
+
"""
|
|
133
|
+
creds = self.get_credentials(self._file)
|
|
134
|
+
return self.get_creds_dict(creds)
|
|
135
|
+
|
|
136
|
+
def get_env_config(self) -> dict:
|
|
137
|
+
"""
|
|
138
|
+
Returns the credentials loaded from environment variables.
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
dict
|
|
143
|
+
The credentials loaded from environment variables.
|
|
144
|
+
"""
|
|
145
|
+
creds = self.get_credentials(self._env)
|
|
146
|
+
return self.get_creds_dict(creds)
|
|
147
|
+
|
|
94
148
|
@staticmethod
|
|
95
149
|
def _is_expired(timestamp: str | None) -> bool:
|
|
96
150
|
"""
|
|
@@ -16,7 +16,6 @@ from boto3.s3.transfer import TransferConfig
|
|
|
16
16
|
from botocore.exceptions import ClientError, NoCredentialsError
|
|
17
17
|
|
|
18
18
|
from digitalhub.stores.data._base.store import Store
|
|
19
|
-
from digitalhub.stores.data.s3.utils import get_bucket_name
|
|
20
19
|
from digitalhub.stores.readers.data.api import get_reader_by_object
|
|
21
20
|
from digitalhub.utils.exceptions import ConfigError, StoreError
|
|
22
21
|
from digitalhub.utils.file_utils import get_file_info_from_s3, get_file_mime_type
|
|
@@ -337,6 +336,49 @@ class S3Store(Store):
|
|
|
337
336
|
reader.write_df(df, fileobj, extension=extension, **kwargs)
|
|
338
337
|
return self.upload_fileobject(fileobj, dst)
|
|
339
338
|
|
|
339
|
+
##############################
|
|
340
|
+
# Wrapper methods
|
|
341
|
+
##############################
|
|
342
|
+
|
|
343
|
+
def get_s3_source(self, src: str, filename: Path) -> None:
|
|
344
|
+
"""
|
|
345
|
+
Download a file from S3 and save it to a local file.
|
|
346
|
+
|
|
347
|
+
Parameters
|
|
348
|
+
----------
|
|
349
|
+
src : str
|
|
350
|
+
S3 path of the object to be downloaded (e.g., 's3://bucket
|
|
351
|
+
filename : Path
|
|
352
|
+
Local path where the downloaded object will be saved.
|
|
353
|
+
|
|
354
|
+
Returns
|
|
355
|
+
-------
|
|
356
|
+
None
|
|
357
|
+
"""
|
|
358
|
+
client, bucket = self._check_factory(src)
|
|
359
|
+
key = self._get_key(src)
|
|
360
|
+
self._download_file(key, filename, client, bucket)
|
|
361
|
+
|
|
362
|
+
def get_s3_client(self, file: bool = True) -> S3Client:
|
|
363
|
+
"""
|
|
364
|
+
Get an S3 client object.
|
|
365
|
+
|
|
366
|
+
Parameters
|
|
367
|
+
----------
|
|
368
|
+
file : bool
|
|
369
|
+
Whether to use file-based credentials. Default is True.
|
|
370
|
+
|
|
371
|
+
Returns
|
|
372
|
+
-------
|
|
373
|
+
S3Client
|
|
374
|
+
Returns a client object that interacts with the S3 storage service.
|
|
375
|
+
"""
|
|
376
|
+
if file:
|
|
377
|
+
cfg = self._configurator.get_file_config()
|
|
378
|
+
else:
|
|
379
|
+
cfg = self._configurator.get_env_config()
|
|
380
|
+
return self._get_client(cfg)
|
|
381
|
+
|
|
340
382
|
##############################
|
|
341
383
|
# Private I/O methods
|
|
342
384
|
##############################
|
|
@@ -595,7 +637,7 @@ class S3Store(Store):
|
|
|
595
637
|
str
|
|
596
638
|
The name of the S3 bucket.
|
|
597
639
|
"""
|
|
598
|
-
return
|
|
640
|
+
return urlparse(root).netloc
|
|
599
641
|
|
|
600
642
|
def _get_client(self, cfg: dict) -> S3Client:
|
|
601
643
|
"""
|
|
@@ -10,8 +10,19 @@ from digitalhub.stores.credentials.enums import CredsEnvVar
|
|
|
10
10
|
|
|
11
11
|
class SqlStoreConfigurator(Configurator):
|
|
12
12
|
"""
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
SQL store configuration manager for database connections.
|
|
14
|
+
|
|
15
|
+
Handles credential management and configuration for SQL database
|
|
16
|
+
connections. Loads credentials from environment variables or
|
|
17
|
+
configuration files and provides connection string generation
|
|
18
|
+
for database access.
|
|
19
|
+
|
|
20
|
+
Attributes
|
|
21
|
+
----------
|
|
22
|
+
keys : list[str]
|
|
23
|
+
List of all supported credential keys for SQL connections.
|
|
24
|
+
required_keys : list[str]
|
|
25
|
+
List of mandatory credential keys that must be provided.
|
|
15
26
|
"""
|
|
16
27
|
|
|
17
28
|
keys = [
|
|
@@ -40,31 +51,70 @@ class SqlStoreConfigurator(Configurator):
|
|
|
40
51
|
|
|
41
52
|
def load_env_vars(self) -> None:
|
|
42
53
|
"""
|
|
43
|
-
Load
|
|
54
|
+
Load database credentials from environment variables.
|
|
55
|
+
|
|
56
|
+
Retrieves SQL database connection credentials from the system
|
|
57
|
+
environment variables and stores them in the configurator's
|
|
58
|
+
credential handler for use in database connections.
|
|
59
|
+
|
|
60
|
+
Returns
|
|
61
|
+
-------
|
|
62
|
+
None
|
|
44
63
|
"""
|
|
45
64
|
env_creds = self._creds_handler.load_from_env(self.keys)
|
|
46
65
|
self._creds_handler.set_credentials(self._env, env_creds)
|
|
47
66
|
|
|
48
67
|
def load_file_vars(self) -> None:
|
|
49
68
|
"""
|
|
50
|
-
Load
|
|
69
|
+
Load database credentials from configuration file.
|
|
70
|
+
|
|
71
|
+
Retrieves SQL database connection credentials from a
|
|
72
|
+
configuration file and stores them in the configurator's
|
|
73
|
+
credential handler for use in database connections.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
None
|
|
51
78
|
"""
|
|
52
79
|
file_creds = self._creds_handler.load_from_file(self.keys)
|
|
53
80
|
self._creds_handler.set_credentials(self._file, file_creds)
|
|
54
81
|
|
|
55
82
|
def get_sql_conn_string(self) -> str:
|
|
56
83
|
"""
|
|
57
|
-
|
|
84
|
+
Generate PostgreSQL connection string from stored credentials.
|
|
85
|
+
|
|
86
|
+
Constructs a PostgreSQL connection string using the configured
|
|
87
|
+
database credentials including username, password, host, port,
|
|
88
|
+
and database name.
|
|
58
89
|
|
|
59
90
|
Returns
|
|
60
91
|
-------
|
|
61
92
|
str
|
|
62
|
-
|
|
93
|
+
A PostgreSQL connection string in the format:
|
|
94
|
+
'postgresql://username:password@host:port/database'
|
|
63
95
|
"""
|
|
64
|
-
creds = self.
|
|
96
|
+
creds = self.get_sql_credentials()
|
|
65
97
|
user = creds[CredsEnvVar.DB_USERNAME.value]
|
|
66
98
|
password = creds[CredsEnvVar.DB_PASSWORD.value]
|
|
67
99
|
host = creds[CredsEnvVar.DB_HOST.value]
|
|
68
100
|
port = creds[CredsEnvVar.DB_PORT.value]
|
|
69
101
|
database = creds[CredsEnvVar.DB_DATABASE.value]
|
|
70
102
|
return f"postgresql://{user}:{password}@{host}:{port}/{database}"
|
|
103
|
+
|
|
104
|
+
def get_sql_credentials(self) -> dict:
|
|
105
|
+
"""
|
|
106
|
+
Get all configured database credentials as a dictionary.
|
|
107
|
+
|
|
108
|
+
Retrieves all available database credentials from the configured
|
|
109
|
+
source and returns them as a dictionary with all credential keys
|
|
110
|
+
from self.keys mapped to their values.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
dict
|
|
115
|
+
Dictionary containing all credential key-value pairs from self.keys.
|
|
116
|
+
Keys correspond to database connection parameters such as
|
|
117
|
+
username, password, host, port, database, and platform.
|
|
118
|
+
"""
|
|
119
|
+
creds = self.get_credentials(self._origin)
|
|
120
|
+
return {key: creds.get(key) for key in self.keys}
|