digitalhub 0.12.0__py3-none-any.whl → 0.13.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 +1 -1
- digitalhub/entities/_base/executable/entity.py +7 -0
- digitalhub/entities/_base/material/entity.py +8 -15
- digitalhub/entities/_base/material/utils.py +1 -1
- digitalhub/entities/_processors/context.py +1 -1
- digitalhub/stores/client/dhcore/client.py +56 -19
- digitalhub/stores/client/dhcore/configurator.py +278 -183
- digitalhub/stores/client/dhcore/enums.py +2 -0
- digitalhub/stores/client/dhcore/utils.py +8 -8
- digitalhub/stores/{configurator → credentials}/api.py +3 -3
- digitalhub/stores/credentials/configurator.py +37 -0
- digitalhub/stores/credentials/enums.py +54 -0
- digitalhub/stores/{configurator/configurator.py → credentials/handler.py} +23 -77
- digitalhub/stores/{configurator → credentials}/ini_module.py +1 -1
- digitalhub/stores/credentials/store.py +49 -0
- digitalhub/stores/data/_base/store.py +19 -6
- digitalhub/stores/data/api.py +37 -1
- digitalhub/stores/data/builder.py +46 -53
- digitalhub/stores/data/local/store.py +4 -7
- digitalhub/stores/data/remote/store.py +4 -7
- digitalhub/stores/data/s3/configurator.py +36 -92
- digitalhub/stores/data/s3/store.py +42 -57
- digitalhub/stores/data/s3/utils.py +1 -1
- digitalhub/stores/data/sql/configurator.py +35 -83
- digitalhub/stores/data/sql/store.py +15 -15
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0b0.dist-info}/METADATA +1 -1
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0b0.dist-info}/RECORD +31 -33
- digitalhub/stores/configurator/credentials_store.py +0 -69
- digitalhub/stores/configurator/enums.py +0 -25
- digitalhub/stores/data/s3/enums.py +0 -20
- digitalhub/stores/data/sql/enums.py +0 -20
- digitalhub/stores/data/utils.py +0 -38
- /digitalhub/stores/{configurator → credentials}/__init__.py +0 -0
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0b0.dist-info}/WHEEL +0 -0
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0b0.dist-info}/licenses/AUTHORS +0 -0
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0b0.dist-info}/licenses/LICENSE +0 -0
|
@@ -8,7 +8,7 @@ import os
|
|
|
8
8
|
import typing
|
|
9
9
|
|
|
10
10
|
from digitalhub.stores.client.api import get_client
|
|
11
|
-
from digitalhub.stores.
|
|
11
|
+
from digitalhub.stores.credentials.enums import CredsEnvVar
|
|
12
12
|
|
|
13
13
|
if typing.TYPE_CHECKING:
|
|
14
14
|
from digitalhub.stores.client.dhcore.client import ClientDHCore
|
|
@@ -47,20 +47,20 @@ def set_dhcore_env(
|
|
|
47
47
|
None
|
|
48
48
|
"""
|
|
49
49
|
if endpoint is not None:
|
|
50
|
-
os.environ[
|
|
50
|
+
os.environ[CredsEnvVar.DHCORE_ENDPOINT.value] = endpoint
|
|
51
51
|
if user is not None:
|
|
52
|
-
os.environ[
|
|
52
|
+
os.environ[CredsEnvVar.DHCORE_USER.value] = user
|
|
53
53
|
if password is not None:
|
|
54
|
-
os.environ[
|
|
54
|
+
os.environ[CredsEnvVar.DHCORE_PASSWORD.value] = password
|
|
55
55
|
if access_token is not None:
|
|
56
|
-
os.environ[
|
|
56
|
+
os.environ[CredsEnvVar.DHCORE_ACCESS_TOKEN.value] = access_token
|
|
57
57
|
if refresh_token is not None:
|
|
58
|
-
os.environ[
|
|
58
|
+
os.environ[CredsEnvVar.DHCORE_REFRESH_TOKEN.value] = refresh_token
|
|
59
59
|
if client_id is not None:
|
|
60
|
-
os.environ[
|
|
60
|
+
os.environ[CredsEnvVar.DHCORE_CLIENT_ID.value] = client_id
|
|
61
61
|
|
|
62
62
|
client: ClientDHCore = get_client(local=False)
|
|
63
|
-
client._configurator.
|
|
63
|
+
client._configurator.load_env_vars()
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
def refresh_token() -> None:
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
from digitalhub.stores.
|
|
7
|
+
from digitalhub.stores.credentials.handler import creds_handler
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def set_current_env(environment: str) -> None:
|
|
@@ -20,7 +20,7 @@ def set_current_env(environment: str) -> None:
|
|
|
20
20
|
-------
|
|
21
21
|
None
|
|
22
22
|
"""
|
|
23
|
-
|
|
23
|
+
creds_handler.set_current_env(environment)
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def get_current_env() -> str:
|
|
@@ -32,4 +32,4 @@ def get_current_env() -> str:
|
|
|
32
32
|
str
|
|
33
33
|
Credentials set name.
|
|
34
34
|
"""
|
|
35
|
-
return
|
|
35
|
+
return creds_handler.get_current_env()
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
|
|
12
|
+
|
|
13
|
+
class Configurator:
|
|
14
|
+
# Must be set in implementing class
|
|
15
|
+
keys: list[str] = []
|
|
16
|
+
required_keys: list[str] = []
|
|
17
|
+
|
|
18
|
+
# Origin of the credentials
|
|
19
|
+
_env = CredsOrigin.ENV.value
|
|
20
|
+
_file = CredsOrigin.FILE.value
|
|
21
|
+
|
|
22
|
+
# Credentials handler
|
|
23
|
+
_creds_handler = creds_handler
|
|
24
|
+
|
|
25
|
+
def get_credentials(self, origin: str) -> dict:
|
|
26
|
+
return creds_handler.get_credentials(origin)
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def load_configs(self) -> None:
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
def _check_credentials(self, creds: dict) -> list[str]:
|
|
33
|
+
missing_keys = []
|
|
34
|
+
for k, v in creds.items():
|
|
35
|
+
if v is None and k in self.required_keys:
|
|
36
|
+
missing_keys.append(k)
|
|
37
|
+
return missing_keys
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
List credential origins.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
ENV = "env"
|
|
16
|
+
FILE = "file"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SetCreds(Enum):
|
|
20
|
+
"""
|
|
21
|
+
List supported environments.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
DEFAULT = "__default"
|
|
25
|
+
DH_ENV = "DH_NAME"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CredsEnvVar(Enum):
|
|
29
|
+
# S3
|
|
30
|
+
S3_ENDPOINT_URL = "AWS_ENDPOINT_URL"
|
|
31
|
+
S3_ACCESS_KEY_ID = "AWS_ACCESS_KEY_ID"
|
|
32
|
+
S3_SECRET_ACCESS_KEY = "AWS_SECRET_ACCESS_KEY"
|
|
33
|
+
S3_SESSION_TOKEN = "AWS_SESSION_TOKEN"
|
|
34
|
+
S3_REGION = "AWS_REGION"
|
|
35
|
+
S3_SIGNATURE_VERSION = "S3_SIGNATURE_VERSION"
|
|
36
|
+
|
|
37
|
+
# SQL
|
|
38
|
+
DB_HOST = "DB_HOST"
|
|
39
|
+
DB_PORT = "DB_PORT"
|
|
40
|
+
DB_USERNAME = "DB_USERNAME"
|
|
41
|
+
DB_PASSWORD = "DB_PASSWORD"
|
|
42
|
+
DB_DATABASE = "DB_DATABASE"
|
|
43
|
+
DB_PG_SCHEMA = "DB_SCHEMA"
|
|
44
|
+
|
|
45
|
+
# DHCORE
|
|
46
|
+
DHCORE_ENDPOINT = "DHCORE_ENDPOINT"
|
|
47
|
+
DHCORE_ISSUER = "DHCORE_ISSUER"
|
|
48
|
+
DHCORE_USER = "DHCORE_USER"
|
|
49
|
+
DHCORE_PASSWORD = "DHCORE_PASSWORD"
|
|
50
|
+
DHCORE_CLIENT_ID = "DHCORE_CLIENT_ID"
|
|
51
|
+
DHCORE_ACCESS_TOKEN = "DHCORE_ACCESS_TOKEN"
|
|
52
|
+
DHCORE_REFRESH_TOKEN = "DHCORE_REFRESH_TOKEN"
|
|
53
|
+
DHCORE_PERSONAL_ACCESS_TOKEN = "DHCORE_PERSONAL_ACCESS_TOKEN"
|
|
54
|
+
DHCORE_WORKFLOW_IMAGE = "DHCORE_WORKFLOW_IMAGE"
|
|
@@ -6,12 +6,12 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import os
|
|
8
8
|
|
|
9
|
-
from digitalhub.stores.
|
|
10
|
-
from digitalhub.stores.
|
|
11
|
-
from digitalhub.stores.
|
|
9
|
+
from digitalhub.stores.credentials.enums import SetCreds
|
|
10
|
+
from digitalhub.stores.credentials.ini_module import load_from_file, read_env_from_file, set_current_env, write_config
|
|
11
|
+
from digitalhub.stores.credentials.store import CredentialsStore
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class
|
|
14
|
+
class CredentialHandler:
|
|
15
15
|
"""
|
|
16
16
|
Configurator object used to configure clients and store credentials.
|
|
17
17
|
"""
|
|
@@ -54,31 +54,6 @@ class EnvConfigurator:
|
|
|
54
54
|
"""
|
|
55
55
|
return self._environment
|
|
56
56
|
|
|
57
|
-
##############################
|
|
58
|
-
# Private methods
|
|
59
|
-
##############################
|
|
60
|
-
|
|
61
|
-
def load_var(self, var_name: str) -> str | None:
|
|
62
|
-
"""
|
|
63
|
-
Get env variable from credentials store, env or file (in order).
|
|
64
|
-
|
|
65
|
-
Parameters
|
|
66
|
-
----------
|
|
67
|
-
var_name : str
|
|
68
|
-
Environment variable name.
|
|
69
|
-
|
|
70
|
-
Returns
|
|
71
|
-
-------
|
|
72
|
-
str | None
|
|
73
|
-
Environment variable value.
|
|
74
|
-
"""
|
|
75
|
-
var = self.get_credential(var_name)
|
|
76
|
-
if var is None:
|
|
77
|
-
var = self.load_from_env(var_name)
|
|
78
|
-
if var is None:
|
|
79
|
-
var = self.load_from_file(var_name)
|
|
80
|
-
return var
|
|
81
|
-
|
|
82
57
|
def load_from_env(self, var: str) -> str | None:
|
|
83
58
|
"""
|
|
84
59
|
Load variable from env.
|
|
@@ -111,92 +86,63 @@ class EnvConfigurator:
|
|
|
111
86
|
str | None
|
|
112
87
|
Environment variable value.
|
|
113
88
|
"""
|
|
114
|
-
|
|
89
|
+
env_from_file = read_env_from_file()
|
|
90
|
+
if env_from_file is not None:
|
|
91
|
+
self._environment = env_from_file
|
|
115
92
|
return load_from_file(var)
|
|
116
93
|
|
|
117
|
-
def write_env(self,
|
|
94
|
+
def write_env(self, creds: dict) -> None:
|
|
118
95
|
"""
|
|
119
96
|
Write the env variables to the .dhcore file.
|
|
120
|
-
It will overwrite any existing env variables.
|
|
121
97
|
|
|
122
98
|
Parameters
|
|
123
99
|
----------
|
|
124
|
-
|
|
125
|
-
|
|
100
|
+
creds : dict
|
|
101
|
+
Credentials.
|
|
126
102
|
|
|
127
103
|
Returns
|
|
128
104
|
-------
|
|
129
105
|
None
|
|
130
106
|
"""
|
|
131
|
-
if key_to_include is None:
|
|
132
|
-
key_to_include = []
|
|
133
|
-
creds = self.get_credential_list(key_to_include)
|
|
134
107
|
write_config(creds, self._environment)
|
|
135
108
|
|
|
136
109
|
##############################
|
|
137
110
|
# Credentials store methods
|
|
138
111
|
##############################
|
|
139
112
|
|
|
140
|
-
def
|
|
113
|
+
def set_credentials(self, origin: str, creds: dict) -> None:
|
|
141
114
|
"""
|
|
142
|
-
|
|
115
|
+
Set credentials.
|
|
143
116
|
|
|
144
117
|
Parameters
|
|
145
118
|
----------
|
|
146
|
-
|
|
147
|
-
The
|
|
148
|
-
|
|
149
|
-
The
|
|
119
|
+
origin : str
|
|
120
|
+
The origin of the credentials.
|
|
121
|
+
creds : dict
|
|
122
|
+
The credentials.
|
|
150
123
|
|
|
151
124
|
Returns
|
|
152
125
|
-------
|
|
153
126
|
None
|
|
154
127
|
"""
|
|
155
|
-
self._creds_store.
|
|
128
|
+
self._creds_store.set_credentials(self._environment, origin, creds)
|
|
156
129
|
|
|
157
|
-
def
|
|
130
|
+
def get_credentials(self, origin: str) -> dict:
|
|
158
131
|
"""
|
|
159
|
-
Get
|
|
132
|
+
Get credentials from origin.
|
|
160
133
|
|
|
161
134
|
Parameters
|
|
162
135
|
----------
|
|
163
|
-
|
|
164
|
-
The
|
|
165
|
-
|
|
166
|
-
Returns
|
|
167
|
-
-------
|
|
168
|
-
dict
|
|
169
|
-
The credential.
|
|
170
|
-
"""
|
|
171
|
-
return self._creds_store.get(self._environment, key)
|
|
172
|
-
|
|
173
|
-
def get_all_credentials(self) -> dict:
|
|
174
|
-
"""
|
|
175
|
-
Get all the credentials from the current credentials set.
|
|
136
|
+
origin : str
|
|
137
|
+
The origin of the credentials.
|
|
176
138
|
|
|
177
139
|
Returns
|
|
178
140
|
-------
|
|
179
141
|
dict
|
|
180
142
|
The credentials.
|
|
181
143
|
"""
|
|
182
|
-
return self._creds_store.
|
|
183
|
-
|
|
184
|
-
def get_credential_list(self, keys: list[str]) -> list[str]:
|
|
185
|
-
"""
|
|
186
|
-
Get the list of credentials.
|
|
187
|
-
|
|
188
|
-
Parameters
|
|
189
|
-
----------
|
|
190
|
-
keys : list[str]
|
|
191
|
-
The list of keys.
|
|
192
|
-
|
|
193
|
-
Returns
|
|
194
|
-
-------
|
|
195
|
-
list[str]
|
|
196
|
-
The list of credentials.
|
|
197
|
-
"""
|
|
198
|
-
return {k: v for k, v in self.get_all_credentials().items() if k in keys}
|
|
144
|
+
return self._creds_store.get_credentials(self._environment, origin)
|
|
199
145
|
|
|
200
146
|
|
|
201
147
|
# Define global configurator
|
|
202
|
-
|
|
148
|
+
creds_handler = CredentialHandler()
|
|
@@ -83,7 +83,7 @@ def write_config(creds: dict, environment: str) -> None:
|
|
|
83
83
|
|
|
84
84
|
cfg["DEFAULT"]["current_environment"] = environment
|
|
85
85
|
for k, v in creds.items():
|
|
86
|
-
cfg[environment][k] = v
|
|
86
|
+
cfg[environment][k] = str(v)
|
|
87
87
|
|
|
88
88
|
ENV_FILE.touch(exist_ok=True)
|
|
89
89
|
with open(ENV_FILE, "w") as inifile:
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
Credentials store to store and retrieve credentials.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self) -> None:
|
|
18
|
+
self._file_creds: dict[str, dict[str, Any]] = {}
|
|
19
|
+
self._env_creds: dict[str, Any] = {}
|
|
20
|
+
|
|
21
|
+
def set_credentials(
|
|
22
|
+
self,
|
|
23
|
+
profile: str,
|
|
24
|
+
origin: str,
|
|
25
|
+
credentials: dict[str, Any],
|
|
26
|
+
) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Set all credentials for a given profile and origin.
|
|
29
|
+
"""
|
|
30
|
+
if origin == CredsOrigin.ENV.value:
|
|
31
|
+
for key, value in credentials.items():
|
|
32
|
+
self._env_creds[key] = value
|
|
33
|
+
return
|
|
34
|
+
if profile not in self._file_creds:
|
|
35
|
+
self._file_creds[profile] = {}
|
|
36
|
+
for key, value in credentials.items():
|
|
37
|
+
self._file_creds[profile][key] = value
|
|
38
|
+
|
|
39
|
+
def get_credentials(
|
|
40
|
+
self,
|
|
41
|
+
profile: str,
|
|
42
|
+
origin: str,
|
|
43
|
+
) -> dict[str, Any]:
|
|
44
|
+
"""
|
|
45
|
+
Get all credentials for a given profile and origin.
|
|
46
|
+
"""
|
|
47
|
+
if origin == CredsOrigin.ENV.value:
|
|
48
|
+
return self._env_creds
|
|
49
|
+
return self._file_creds[profile]
|
|
@@ -16,6 +16,7 @@ from digitalhub.utils.types import SourcesOrListOfSources
|
|
|
16
16
|
from digitalhub.utils.uri_utils import has_local_scheme
|
|
17
17
|
|
|
18
18
|
if typing.TYPE_CHECKING:
|
|
19
|
+
from digitalhub.stores.credentials.configurator import Configurator
|
|
19
20
|
from digitalhub.stores.readers.data._base.reader import DataframeReader
|
|
20
21
|
|
|
21
22
|
|
|
@@ -24,6 +25,9 @@ class Store:
|
|
|
24
25
|
Store abstract class.
|
|
25
26
|
"""
|
|
26
27
|
|
|
28
|
+
def __init__(self, configurator: Configurator | None = None) -> None:
|
|
29
|
+
self._configurator = configurator
|
|
30
|
+
|
|
27
31
|
##############################
|
|
28
32
|
# I/O methods
|
|
29
33
|
##############################
|
|
@@ -31,19 +35,22 @@ class Store:
|
|
|
31
35
|
@abstractmethod
|
|
32
36
|
def download(
|
|
33
37
|
self,
|
|
34
|
-
|
|
38
|
+
src: str,
|
|
35
39
|
dst: Path,
|
|
36
|
-
src: list[str],
|
|
37
40
|
overwrite: bool = False,
|
|
38
41
|
) -> str:
|
|
39
42
|
"""
|
|
40
|
-
Method to download
|
|
43
|
+
Method to download material entity from storage.
|
|
41
44
|
"""
|
|
42
45
|
|
|
43
46
|
@abstractmethod
|
|
44
|
-
def upload(
|
|
47
|
+
def upload(
|
|
48
|
+
self,
|
|
49
|
+
src: SourcesOrListOfSources,
|
|
50
|
+
dst: str,
|
|
51
|
+
) -> list[tuple[str, str]]:
|
|
45
52
|
"""
|
|
46
|
-
Method to upload
|
|
53
|
+
Method to upload material entity to storage.
|
|
47
54
|
"""
|
|
48
55
|
|
|
49
56
|
@abstractmethod
|
|
@@ -83,7 +90,13 @@ class Store:
|
|
|
83
90
|
"""
|
|
84
91
|
|
|
85
92
|
@abstractmethod
|
|
86
|
-
def write_df(
|
|
93
|
+
def write_df(
|
|
94
|
+
self,
|
|
95
|
+
df: Any,
|
|
96
|
+
dst: str,
|
|
97
|
+
extension: str | None = None,
|
|
98
|
+
**kwargs,
|
|
99
|
+
) -> str:
|
|
87
100
|
"""
|
|
88
101
|
Write DataFrame as parquet or csv.
|
|
89
102
|
"""
|
digitalhub/stores/data/api.py
CHANGED
|
@@ -6,12 +6,48 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import typing
|
|
8
8
|
|
|
9
|
+
from digitalhub.context.api import get_context
|
|
10
|
+
from digitalhub.stores.credentials.handler import creds_handler
|
|
9
11
|
from digitalhub.stores.data.builder import store_builder
|
|
12
|
+
from digitalhub.stores.data.enums import StoreEnv
|
|
10
13
|
|
|
11
14
|
if typing.TYPE_CHECKING:
|
|
12
15
|
from digitalhub.stores.data._base.store import Store
|
|
13
16
|
|
|
14
17
|
|
|
18
|
+
def get_default_store(project: str) -> str:
|
|
19
|
+
"""
|
|
20
|
+
Get default store URI.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
project : str
|
|
25
|
+
Project name.
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
str
|
|
30
|
+
Default store URI.
|
|
31
|
+
"""
|
|
32
|
+
context = get_context(project)
|
|
33
|
+
store = context.config.get(StoreEnv.DEFAULT_FILES_STORE.value.lower())
|
|
34
|
+
if store is not None:
|
|
35
|
+
return store
|
|
36
|
+
|
|
37
|
+
store = creds_handler.load_from_env(StoreEnv.DEFAULT_FILES_STORE.value)
|
|
38
|
+
if store is None:
|
|
39
|
+
store = creds_handler.load_from_file(StoreEnv.DEFAULT_FILES_STORE.value)
|
|
40
|
+
|
|
41
|
+
if store is None or store == "":
|
|
42
|
+
raise ValueError(
|
|
43
|
+
"No default store found. "
|
|
44
|
+
"Please set a default store "
|
|
45
|
+
f"in your environment (e.g. export {StoreEnv.DEFAULT_FILES_STORE.value}=) "
|
|
46
|
+
"or set it in project config."
|
|
47
|
+
)
|
|
48
|
+
return store
|
|
49
|
+
|
|
50
|
+
|
|
15
51
|
def get_store(project: str, uri: str) -> Store:
|
|
16
52
|
"""
|
|
17
53
|
Get store instance by URI.
|
|
@@ -30,4 +66,4 @@ def get_store(project: str, uri: str) -> Store:
|
|
|
30
66
|
Store
|
|
31
67
|
Store instance.
|
|
32
68
|
"""
|
|
33
|
-
return store_builder.get(
|
|
69
|
+
return store_builder.get(uri)
|
|
@@ -6,40 +6,25 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import typing
|
|
8
8
|
|
|
9
|
-
from digitalhub.stores.
|
|
9
|
+
from digitalhub.stores.credentials.api import get_current_env
|
|
10
10
|
from digitalhub.stores.data.local.store import LocalStore
|
|
11
11
|
from digitalhub.stores.data.remote.store import RemoteStore
|
|
12
|
+
from digitalhub.stores.data.s3.configurator import S3StoreConfigurator
|
|
12
13
|
from digitalhub.stores.data.s3.store import S3Store
|
|
14
|
+
from digitalhub.stores.data.sql.configurator import SqlStoreConfigurator
|
|
13
15
|
from digitalhub.stores.data.sql.store import SqlStore
|
|
14
16
|
from digitalhub.utils.uri_utils import SchemeCategory, map_uri_scheme
|
|
15
17
|
|
|
16
18
|
if typing.TYPE_CHECKING:
|
|
19
|
+
from digitalhub.stores.credentials.configurator import Configurator
|
|
17
20
|
from digitalhub.stores.data._base.store import Store
|
|
21
|
+
from digitalhub.utils.exceptions import StoreError
|
|
18
22
|
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Parameters
|
|
25
|
-
----------
|
|
26
|
-
type : str
|
|
27
|
-
Store type.
|
|
28
|
-
|
|
29
|
-
Returns
|
|
30
|
-
-------
|
|
31
|
-
Store
|
|
32
|
-
The store class.
|
|
33
|
-
"""
|
|
34
|
-
if type == SchemeCategory.LOCAL.value:
|
|
35
|
-
return LocalStore
|
|
36
|
-
if type == SchemeCategory.S3.value:
|
|
37
|
-
return S3Store
|
|
38
|
-
if type == SchemeCategory.REMOTE.value:
|
|
39
|
-
return RemoteStore
|
|
40
|
-
if type == SchemeCategory.SQL.value:
|
|
41
|
-
return SqlStore
|
|
42
|
-
raise ValueError(f"Unknown store type: {type}")
|
|
24
|
+
class StoreInfo:
|
|
25
|
+
def __init__(self, store: Store, configurator: Configurator | None = None) -> None:
|
|
26
|
+
self._store = store
|
|
27
|
+
self._configurator = configurator
|
|
43
28
|
|
|
44
29
|
|
|
45
30
|
class StoreBuilder:
|
|
@@ -48,50 +33,58 @@ class StoreBuilder:
|
|
|
48
33
|
"""
|
|
49
34
|
|
|
50
35
|
def __init__(self) -> None:
|
|
36
|
+
self._builders: dict[str, StoreInfo] = {}
|
|
51
37
|
self._instances: dict[str, dict[str, Store]] = {}
|
|
52
38
|
|
|
53
|
-
def
|
|
39
|
+
def register(
|
|
40
|
+
self,
|
|
41
|
+
store_type: str,
|
|
42
|
+
store: Store,
|
|
43
|
+
configurator: Configurator | None = None,
|
|
44
|
+
) -> None:
|
|
45
|
+
if store_type not in self._builders:
|
|
46
|
+
self._builders[store_type] = StoreInfo(store, configurator)
|
|
47
|
+
else:
|
|
48
|
+
raise StoreError(f"Store type {store_type} already registered")
|
|
49
|
+
|
|
50
|
+
def get(self, uri: str) -> Store:
|
|
54
51
|
"""
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
Parameters
|
|
58
|
-
----------
|
|
59
|
-
store_type : str
|
|
60
|
-
Store type.
|
|
61
|
-
config : dict
|
|
62
|
-
|
|
63
|
-
Returns
|
|
64
|
-
-------
|
|
65
|
-
None
|
|
66
|
-
"""
|
|
67
|
-
env = get_current_env()
|
|
68
|
-
if env not in self._instances:
|
|
69
|
-
self._instances[env] = {}
|
|
70
|
-
self._instances[env][store_type] = _get_class_from_type(store_type)()
|
|
71
|
-
|
|
72
|
-
def get(self, project: str, uri: str) -> Store:
|
|
73
|
-
"""
|
|
74
|
-
Get a store instance by URI.
|
|
52
|
+
Get a store instance by URI, building it if necessary.
|
|
75
53
|
|
|
76
54
|
Parameters
|
|
77
55
|
----------
|
|
78
56
|
uri : str
|
|
79
57
|
URI to parse.
|
|
80
|
-
config : dict
|
|
81
|
-
Store configuration.
|
|
82
58
|
|
|
83
59
|
Returns
|
|
84
60
|
-------
|
|
85
61
|
Store
|
|
86
62
|
The store instance.
|
|
87
63
|
"""
|
|
88
|
-
|
|
64
|
+
env_profile = get_current_env()
|
|
89
65
|
store_type = map_uri_scheme(uri)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
self.
|
|
94
|
-
|
|
66
|
+
|
|
67
|
+
# Ensure env exists in _instances
|
|
68
|
+
if env_profile not in self._instances:
|
|
69
|
+
self._instances[env_profile] = {}
|
|
70
|
+
|
|
71
|
+
# Build the store instance if not already present
|
|
72
|
+
if store_type not in self._instances[env_profile]:
|
|
73
|
+
store_info = self._builders[store_type]
|
|
74
|
+
store_cls = store_info._store
|
|
75
|
+
cfgrt_cls = store_info._configurator
|
|
76
|
+
|
|
77
|
+
if cfgrt_cls is None:
|
|
78
|
+
store = store_cls()
|
|
79
|
+
else:
|
|
80
|
+
store = store_cls(cfgrt_cls())
|
|
81
|
+
self._instances[env_profile][store_type] = store
|
|
82
|
+
|
|
83
|
+
return self._instances[env_profile][store_type]
|
|
95
84
|
|
|
96
85
|
|
|
97
86
|
store_builder = StoreBuilder()
|
|
87
|
+
store_builder.register(SchemeCategory.S3.value, S3Store, S3StoreConfigurator)
|
|
88
|
+
store_builder.register(SchemeCategory.SQL.value, SqlStore, SqlStoreConfigurator)
|
|
89
|
+
store_builder.register(SchemeCategory.LOCAL.value, LocalStore)
|
|
90
|
+
store_builder.register(SchemeCategory.REMOTE.value, RemoteStore)
|
|
@@ -29,7 +29,6 @@ class LocalStore(Store):
|
|
|
29
29
|
self,
|
|
30
30
|
root: str,
|
|
31
31
|
dst: Path,
|
|
32
|
-
src: list[str],
|
|
33
32
|
overwrite: bool = False,
|
|
34
33
|
) -> str:
|
|
35
34
|
"""
|
|
@@ -37,19 +36,17 @@ class LocalStore(Store):
|
|
|
37
36
|
|
|
38
37
|
Parameters
|
|
39
38
|
----------
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
src : str
|
|
40
|
+
Path of the material entity.
|
|
42
41
|
dst : str
|
|
43
|
-
The destination of the
|
|
44
|
-
src : list[str]
|
|
45
|
-
List of sources.
|
|
42
|
+
The destination of the material entity on local filesystem.
|
|
46
43
|
overwrite : bool
|
|
47
44
|
Specify if overwrite existing file(s).
|
|
48
45
|
|
|
49
46
|
Returns
|
|
50
47
|
-------
|
|
51
48
|
str
|
|
52
|
-
Destination path of the downloaded
|
|
49
|
+
Destination path of the downloaded files.
|
|
53
50
|
"""
|
|
54
51
|
raise StoreError("Local store does not support download.")
|
|
55
52
|
|
|
@@ -28,7 +28,6 @@ class RemoteStore(Store):
|
|
|
28
28
|
self,
|
|
29
29
|
root: str,
|
|
30
30
|
dst: Path,
|
|
31
|
-
src: list[str],
|
|
32
31
|
overwrite: bool = False,
|
|
33
32
|
) -> str:
|
|
34
33
|
"""
|
|
@@ -36,19 +35,17 @@ class RemoteStore(Store):
|
|
|
36
35
|
|
|
37
36
|
Parameters
|
|
38
37
|
----------
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
src : str
|
|
39
|
+
Path of the material entity.
|
|
41
40
|
dst : str
|
|
42
|
-
The destination of the
|
|
43
|
-
src : list[str]
|
|
44
|
-
List of sources.
|
|
41
|
+
The destination of the material entity on local filesystem.
|
|
45
42
|
overwrite : bool
|
|
46
43
|
Specify if overwrite existing file(s).
|
|
47
44
|
|
|
48
45
|
Returns
|
|
49
46
|
-------
|
|
50
47
|
str
|
|
51
|
-
Destination path of the downloaded
|
|
48
|
+
Destination path of the downloaded files.
|
|
52
49
|
"""
|
|
53
50
|
# Handle destination
|
|
54
51
|
if dst is None:
|