digitalhub 0.10.0b3__py3-none-any.whl → 0.10.0b4__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/entities/_base/entity/builder.py +5 -5
- digitalhub/entities/_base/material/entity.py +4 -17
- digitalhub/entities/_base/material/status.py +1 -1
- digitalhub/entities/_commons/models.py +7 -3
- digitalhub/entities/_commons/utils.py +5 -4
- digitalhub/entities/_operations/processor.py +5 -4
- digitalhub/entities/artifact/artifact/spec.py +3 -1
- digitalhub/entities/artifact/crud.py +3 -2
- digitalhub/entities/builders.py +6 -18
- digitalhub/entities/dataitem/crud.py +3 -2
- digitalhub/entities/dataitem/table/models.py +4 -3
- digitalhub/entities/dataitem/table/utils.py +7 -7
- digitalhub/entities/dataitem/utils.py +12 -7
- digitalhub/entities/model/_base/spec.py +6 -7
- digitalhub/entities/model/crud.py +3 -2
- digitalhub/entities/model/huggingface/spec.py +4 -2
- digitalhub/entities/model/mlflow/spec.py +6 -4
- digitalhub/entities/project/_base/spec.py +8 -6
- digitalhub/entities/project/crud.py +2 -2
- digitalhub/entities/run/_base/spec.py +4 -2
- digitalhub/entities/secret/_base/spec.py +4 -2
- digitalhub/entities/secret/crud.py +2 -0
- digitalhub/entities/task/_base/models.py +41 -40
- digitalhub/entities/task/_base/utils.py +2 -2
- digitalhub/stores/_base/store.py +4 -3
- digitalhub/stores/local/store.py +4 -3
- digitalhub/stores/remote/store.py +4 -3
- digitalhub/stores/s3/store.py +5 -4
- digitalhub/stores/sql/configurator.py +4 -4
- digitalhub/stores/sql/enums.py +1 -1
- digitalhub/stores/sql/store.py +7 -3
- digitalhub/utils/file_utils.py +8 -7
- digitalhub/utils/generic_utils.py +20 -8
- digitalhub/utils/types.py +6 -0
- digitalhub/utils/uri_utils.py +1 -1
- {digitalhub-0.10.0b3.dist-info → digitalhub-0.10.0b4.dist-info}/METADATA +1 -1
- {digitalhub-0.10.0b3.dist-info → digitalhub-0.10.0b4.dist-info}/RECORD +39 -38
- {digitalhub-0.10.0b3.dist-info → digitalhub-0.10.0b4.dist-info}/WHEEL +0 -0
- {digitalhub-0.10.0b3.dist-info → digitalhub-0.10.0b4.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
3
5
|
from digitalhub.entities._base.entity.spec import Spec, SpecValidator
|
|
4
6
|
|
|
5
7
|
|
|
@@ -28,8 +30,8 @@ class SecretValidator(SpecValidator):
|
|
|
28
30
|
SecretValidator validator.
|
|
29
31
|
"""
|
|
30
32
|
|
|
31
|
-
path: str = None
|
|
33
|
+
path: Optional[str] = None
|
|
32
34
|
"""Path to the secret."""
|
|
33
35
|
|
|
34
|
-
provider: str = None
|
|
36
|
+
provider: Optional[str] = None
|
|
35
37
|
"""Provider of the secret."""
|
|
@@ -108,6 +108,8 @@ def get_secret(
|
|
|
108
108
|
>>> entity_id="my-secret-id")
|
|
109
109
|
"""
|
|
110
110
|
if not identifier.startswith("store://"):
|
|
111
|
+
if project is None:
|
|
112
|
+
raise ValueError("Project must be provided.")
|
|
111
113
|
secrets = list_secrets(project=project, **kwargs)
|
|
112
114
|
for secret in secrets:
|
|
113
115
|
if secret.name == identifier:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
+
from typing import Optional
|
|
4
5
|
|
|
5
6
|
from pydantic import BaseModel, ConfigDict, Field
|
|
6
7
|
|
|
@@ -30,7 +31,7 @@ class Volume(BaseModel):
|
|
|
30
31
|
mount_path: str
|
|
31
32
|
"""Volume mount path inside the container."""
|
|
32
33
|
|
|
33
|
-
spec: dict[str, str] = None
|
|
34
|
+
spec: Optional[dict[str, str]] = None
|
|
34
35
|
"""Volume spec."""
|
|
35
36
|
|
|
36
37
|
|
|
@@ -63,13 +64,13 @@ class Resource(BaseModel):
|
|
|
63
64
|
Resource model.
|
|
64
65
|
"""
|
|
65
66
|
|
|
66
|
-
cpu: ResourceItem = None
|
|
67
|
+
cpu: Optional[ResourceItem] = None
|
|
67
68
|
"""CPU resource model."""
|
|
68
69
|
|
|
69
|
-
mem: ResourceItem = None
|
|
70
|
+
mem: Optional[ResourceItem] = None
|
|
70
71
|
"""Memory resource model."""
|
|
71
72
|
|
|
72
|
-
gpu: ResourceItem = None
|
|
73
|
+
gpu: Optional[ResourceItem] = None
|
|
73
74
|
"""GPU resource model."""
|
|
74
75
|
|
|
75
76
|
|
|
@@ -90,31 +91,31 @@ class Toleration(BaseModel):
|
|
|
90
91
|
Toleration model.
|
|
91
92
|
"""
|
|
92
93
|
|
|
93
|
-
key: str = None
|
|
94
|
+
key: Optional[str] = None
|
|
94
95
|
"""Toleration key."""
|
|
95
96
|
|
|
96
|
-
operator: str = None
|
|
97
|
+
operator: Optional[str] = None
|
|
97
98
|
"""Toleration operator."""
|
|
98
99
|
|
|
99
|
-
value: str = None
|
|
100
|
+
value: Optional[str] = None
|
|
100
101
|
"""Toleration value."""
|
|
101
102
|
|
|
102
|
-
effect: str = None
|
|
103
|
+
effect: Optional[str] = None
|
|
103
104
|
"""Toleration effect."""
|
|
104
105
|
|
|
105
|
-
toleration_seconds: int = None
|
|
106
|
+
toleration_seconds: Optional[int] = None
|
|
106
107
|
"""Toleration seconds."""
|
|
107
108
|
|
|
108
109
|
|
|
109
110
|
class V1NodeSelectorRequirement(BaseModel):
|
|
110
111
|
key: str
|
|
111
112
|
operator: str
|
|
112
|
-
values: list[str] = None
|
|
113
|
+
values: Optional[list[str]] = None
|
|
113
114
|
|
|
114
115
|
|
|
115
116
|
class V1NodeSelectorTerm(BaseModel):
|
|
116
|
-
match_expressions: list[V1NodeSelectorRequirement] = None
|
|
117
|
-
match_fields: list[V1NodeSelectorRequirement] = None
|
|
117
|
+
match_expressions: Optional[list[V1NodeSelectorRequirement]] = None
|
|
118
|
+
match_fields: Optional[list[V1NodeSelectorRequirement]] = None
|
|
118
119
|
|
|
119
120
|
|
|
120
121
|
class V1NodeSelector(BaseModel):
|
|
@@ -129,21 +130,21 @@ class V1PreferredSchedulingTerm(BaseModel):
|
|
|
129
130
|
class V1LabelSelectorRequirement(BaseModel):
|
|
130
131
|
key: str
|
|
131
132
|
operator: str
|
|
132
|
-
values: list[str] = None
|
|
133
|
+
values: Optional[list[str]] = None
|
|
133
134
|
|
|
134
135
|
|
|
135
136
|
class V1LabelSelector(BaseModel):
|
|
136
|
-
match_expressions: list[V1LabelSelectorRequirement] = None
|
|
137
|
-
match_labels: dict[str, str] = None
|
|
137
|
+
match_expressions: Optional[list[V1LabelSelectorRequirement]] = None
|
|
138
|
+
match_labels: Optional[dict[str, str]] = None
|
|
138
139
|
|
|
139
140
|
|
|
140
141
|
class V1PodAffinityTerm(BaseModel):
|
|
141
|
-
label_selector: V1LabelSelector = None
|
|
142
|
-
match_label_keys: list[str] = None
|
|
143
|
-
mismatch_label_keys: list[str] = None
|
|
144
|
-
namespace_selector: V1LabelSelector = None
|
|
145
|
-
namespaces: list[str] = None
|
|
146
|
-
topology_key: str
|
|
142
|
+
label_selector: Optional[V1LabelSelector] = None
|
|
143
|
+
match_label_keys: Optional[list[str]] = None
|
|
144
|
+
mismatch_label_keys: Optional[list[str]] = None
|
|
145
|
+
namespace_selector: Optional[V1LabelSelector] = None
|
|
146
|
+
namespaces: Optional[list[str]] = None
|
|
147
|
+
topology_key: Optional[str] = None
|
|
147
148
|
|
|
148
149
|
|
|
149
150
|
class V1WeightedPodAffinityTerm(BaseModel):
|
|
@@ -152,18 +153,18 @@ class V1WeightedPodAffinityTerm(BaseModel):
|
|
|
152
153
|
|
|
153
154
|
|
|
154
155
|
class V1NodeAffinity(BaseModel):
|
|
155
|
-
preferred_during_scheduling_ignored_during_execution: list[V1PreferredSchedulingTerm] = None
|
|
156
|
-
required_during_scheduling_ignored_during_execution: V1NodeSelector = None
|
|
156
|
+
preferred_during_scheduling_ignored_during_execution: Optional[list[V1PreferredSchedulingTerm]] = None
|
|
157
|
+
required_during_scheduling_ignored_during_execution: Optional[V1NodeSelector] = None
|
|
157
158
|
|
|
158
159
|
|
|
159
160
|
class V1PodAffinity(BaseModel):
|
|
160
|
-
preferred_during_scheduling_ignored_during_execution: list[V1WeightedPodAffinityTerm] = None
|
|
161
|
-
required_during_scheduling_ignored_during_execution: list[V1PodAffinityTerm] = None
|
|
161
|
+
preferred_during_scheduling_ignored_during_execution: Optional[list[V1WeightedPodAffinityTerm]] = None
|
|
162
|
+
required_during_scheduling_ignored_during_execution: Optional[list[V1PodAffinityTerm]] = None
|
|
162
163
|
|
|
163
164
|
|
|
164
165
|
class V1PodAntiAffinity(BaseModel):
|
|
165
|
-
preferred_during_scheduling_ignored_during_execution: list[V1WeightedPodAffinityTerm] = None
|
|
166
|
-
required_during_scheduling_ignored_during_execution: list[V1PodAffinityTerm] = None
|
|
166
|
+
preferred_during_scheduling_ignored_during_execution: Optional[list[V1WeightedPodAffinityTerm]] = None
|
|
167
|
+
required_during_scheduling_ignored_during_execution: Optional[list[V1PodAffinityTerm]] = None
|
|
167
168
|
|
|
168
169
|
|
|
169
170
|
class Affinity(BaseModel):
|
|
@@ -171,13 +172,13 @@ class Affinity(BaseModel):
|
|
|
171
172
|
Affinity model.
|
|
172
173
|
"""
|
|
173
174
|
|
|
174
|
-
node_affinity: V1NodeAffinity = None
|
|
175
|
+
node_affinity: Optional[V1NodeAffinity] = None
|
|
175
176
|
"""Node affinity."""
|
|
176
177
|
|
|
177
|
-
pod_affinity: V1PodAffinity = None
|
|
178
|
+
pod_affinity: Optional[V1PodAffinity] = None
|
|
178
179
|
"""Pod affinity."""
|
|
179
180
|
|
|
180
|
-
pod_anti_affinity: V1PodAntiAffinity = None
|
|
181
|
+
pod_anti_affinity: Optional[V1PodAntiAffinity] = None
|
|
181
182
|
"""Pod anti affinity."""
|
|
182
183
|
|
|
183
184
|
|
|
@@ -186,34 +187,34 @@ class K8s(BaseModel):
|
|
|
186
187
|
Kubernetes resource model.
|
|
187
188
|
"""
|
|
188
189
|
|
|
189
|
-
node_selector: list[NodeSelector] = None
|
|
190
|
+
node_selector: Optional[list[NodeSelector]] = None
|
|
190
191
|
"""Node selector."""
|
|
191
192
|
|
|
192
|
-
volumes: list[Volume] = None
|
|
193
|
+
volumes: Optional[list[Volume]] = None
|
|
193
194
|
"""List of volumes."""
|
|
194
195
|
|
|
195
|
-
resources: Resource = None
|
|
196
|
+
resources: Optional[Resource] = None
|
|
196
197
|
"""Resources restrictions."""
|
|
197
198
|
|
|
198
|
-
affinity: Affinity = None
|
|
199
|
+
affinity: Optional[Affinity] = None
|
|
199
200
|
"""Affinity."""
|
|
200
201
|
|
|
201
|
-
tolerations: list[Toleration] = None
|
|
202
|
+
tolerations: Optional[list[Toleration]] = None
|
|
202
203
|
"""Tolerations."""
|
|
203
204
|
|
|
204
|
-
envs: list[Env] = None
|
|
205
|
+
envs: Optional[list[Env]] = None
|
|
205
206
|
"""Env variables."""
|
|
206
207
|
|
|
207
|
-
secrets: list[str] = None
|
|
208
|
+
secrets: Optional[list[str]] = None
|
|
208
209
|
"""List of secret names."""
|
|
209
210
|
|
|
210
|
-
profile: str = None
|
|
211
|
+
profile: Optional[str] = None
|
|
211
212
|
"""Profile template."""
|
|
212
213
|
|
|
213
|
-
runtime_class: str = None
|
|
214
|
+
runtime_class: Optional[str] = None
|
|
214
215
|
"""Runtime class name."""
|
|
215
216
|
|
|
216
|
-
priority_class: str = None
|
|
217
|
+
priority_class: Optional[str] = None
|
|
217
218
|
"""Priority class."""
|
|
218
219
|
|
|
219
220
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def build_task_actions(kind_action_list: list[tuple[str, str]]) -> dict[str, str]:
|
|
4
|
+
def build_task_actions(kind_action_list: list[tuple[str, str]]) -> list[dict[str, str]]:
|
|
5
5
|
"""
|
|
6
6
|
Build task actions.
|
|
7
7
|
|
|
@@ -12,7 +12,7 @@ def build_task_actions(kind_action_list: list[tuple[str, str]]) -> dict[str, str
|
|
|
12
12
|
|
|
13
13
|
Returns
|
|
14
14
|
-------
|
|
15
|
-
dict[str, str]
|
|
15
|
+
list[dict[str, str]]
|
|
16
16
|
Returns the task actions.
|
|
17
17
|
"""
|
|
18
18
|
return [{"kind": kind, "action": action} for (kind, action) in kind_action_list]
|
digitalhub/stores/_base/store.py
CHANGED
|
@@ -8,6 +8,7 @@ from typing import Any
|
|
|
8
8
|
|
|
9
9
|
from digitalhub.readers.data.api import get_reader_by_engine
|
|
10
10
|
from digitalhub.utils.exceptions import StoreError
|
|
11
|
+
from digitalhub.utils.types import SourcesOrListOfSources
|
|
11
12
|
from digitalhub.utils.uri_utils import has_local_scheme
|
|
12
13
|
|
|
13
14
|
if typing.TYPE_CHECKING:
|
|
@@ -36,7 +37,7 @@ class Store:
|
|
|
36
37
|
"""
|
|
37
38
|
|
|
38
39
|
@abstractmethod
|
|
39
|
-
def upload(self, src:
|
|
40
|
+
def upload(self, src: SourcesOrListOfSources, dst: str) -> list[tuple[str, str]]:
|
|
40
41
|
"""
|
|
41
42
|
Method to upload artifact to storage.
|
|
42
43
|
"""
|
|
@@ -58,7 +59,7 @@ class Store:
|
|
|
58
59
|
@abstractmethod
|
|
59
60
|
def read_df(
|
|
60
61
|
self,
|
|
61
|
-
path:
|
|
62
|
+
path: SourcesOrListOfSources,
|
|
62
63
|
file_format: str | None = None,
|
|
63
64
|
engine: str | None = None,
|
|
64
65
|
**kwargs,
|
|
@@ -159,7 +160,7 @@ class Store:
|
|
|
159
160
|
|
|
160
161
|
Parameters
|
|
161
162
|
----------
|
|
162
|
-
path : str
|
|
163
|
+
path : str | Path
|
|
163
164
|
The path to build.
|
|
164
165
|
|
|
165
166
|
Returns
|
digitalhub/stores/local/store.py
CHANGED
|
@@ -8,6 +8,7 @@ from digitalhub.readers.data.api import get_reader_by_object
|
|
|
8
8
|
from digitalhub.stores._base.store import Store
|
|
9
9
|
from digitalhub.utils.exceptions import StoreError
|
|
10
10
|
from digitalhub.utils.file_utils import get_file_info_from_local
|
|
11
|
+
from digitalhub.utils.types import SourcesOrListOfSources
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class LocalStore(Store):
|
|
@@ -51,7 +52,7 @@ class LocalStore(Store):
|
|
|
51
52
|
"""
|
|
52
53
|
raise StoreError("Local store does not support download.")
|
|
53
54
|
|
|
54
|
-
def upload(self, src:
|
|
55
|
+
def upload(self, src: SourcesOrListOfSources, dst: str) -> list[tuple[str, str]]:
|
|
55
56
|
"""
|
|
56
57
|
Upload an artifact to storage.
|
|
57
58
|
|
|
@@ -88,7 +89,7 @@ class LocalStore(Store):
|
|
|
88
89
|
|
|
89
90
|
def read_df(
|
|
90
91
|
self,
|
|
91
|
-
path:
|
|
92
|
+
path: SourcesOrListOfSources,
|
|
92
93
|
file_format: str | None = None,
|
|
93
94
|
engine: str | None = None,
|
|
94
95
|
**kwargs,
|
|
@@ -98,7 +99,7 @@ class LocalStore(Store):
|
|
|
98
99
|
|
|
99
100
|
Parameters
|
|
100
101
|
----------
|
|
101
|
-
path :
|
|
102
|
+
path : SourcesOrListOfSources
|
|
102
103
|
Path(s) to read DataFrame from.
|
|
103
104
|
file_format : str
|
|
104
105
|
Extension of the file.
|
|
@@ -7,6 +7,7 @@ import requests
|
|
|
7
7
|
|
|
8
8
|
from digitalhub.stores._base.store import Store
|
|
9
9
|
from digitalhub.utils.exceptions import StoreError
|
|
10
|
+
from digitalhub.utils.types import SourcesOrListOfSources
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class RemoteStore(Store):
|
|
@@ -62,7 +63,7 @@ class RemoteStore(Store):
|
|
|
62
63
|
|
|
63
64
|
return self._download_file(root, dst, overwrite)
|
|
64
65
|
|
|
65
|
-
def upload(self, src:
|
|
66
|
+
def upload(self, src: SourcesOrListOfSources, dst: str) -> list[tuple[str, str]]:
|
|
66
67
|
"""
|
|
67
68
|
Upload an artifact to storage.
|
|
68
69
|
|
|
@@ -99,7 +100,7 @@ class RemoteStore(Store):
|
|
|
99
100
|
|
|
100
101
|
def read_df(
|
|
101
102
|
self,
|
|
102
|
-
path:
|
|
103
|
+
path: SourcesOrListOfSources,
|
|
103
104
|
file_format: str | None = None,
|
|
104
105
|
engine: str | None = None,
|
|
105
106
|
**kwargs,
|
|
@@ -109,7 +110,7 @@ class RemoteStore(Store):
|
|
|
109
110
|
|
|
110
111
|
Parameters
|
|
111
112
|
----------
|
|
112
|
-
path :
|
|
113
|
+
path : SourcesOrListOfSources
|
|
113
114
|
Path(s) to read DataFrame from.
|
|
114
115
|
file_format : str
|
|
115
116
|
Extension of the file.
|
digitalhub/stores/s3/store.py
CHANGED
|
@@ -16,6 +16,7 @@ from digitalhub.stores.s3.configurator import S3StoreConfigurator
|
|
|
16
16
|
from digitalhub.stores.s3.utils import get_bucket_name
|
|
17
17
|
from digitalhub.utils.exceptions import StoreError
|
|
18
18
|
from digitalhub.utils.file_utils import get_file_info_from_s3, get_file_mime_type
|
|
19
|
+
from digitalhub.utils.types import SourcesOrListOfSources
|
|
19
20
|
|
|
20
21
|
if typing.TYPE_CHECKING:
|
|
21
22
|
pass
|
|
@@ -117,7 +118,7 @@ class S3Store(Store):
|
|
|
117
118
|
|
|
118
119
|
def upload(
|
|
119
120
|
self,
|
|
120
|
-
src:
|
|
121
|
+
src: SourcesOrListOfSources,
|
|
121
122
|
dst: str,
|
|
122
123
|
) -> list[tuple[str, str]]:
|
|
123
124
|
"""
|
|
@@ -125,7 +126,7 @@ class S3Store(Store):
|
|
|
125
126
|
|
|
126
127
|
Parameters
|
|
127
128
|
----------
|
|
128
|
-
src :
|
|
129
|
+
src : SourcesOrListOfSources
|
|
129
130
|
Source(s).
|
|
130
131
|
dst : str
|
|
131
132
|
The destination of the artifact on storage.
|
|
@@ -238,7 +239,7 @@ class S3Store(Store):
|
|
|
238
239
|
|
|
239
240
|
def read_df(
|
|
240
241
|
self,
|
|
241
|
-
path:
|
|
242
|
+
path: SourcesOrListOfSources,
|
|
242
243
|
file_format: str | None = None,
|
|
243
244
|
engine: str | None = None,
|
|
244
245
|
**kwargs,
|
|
@@ -248,7 +249,7 @@ class S3Store(Store):
|
|
|
248
249
|
|
|
249
250
|
Parameters
|
|
250
251
|
----------
|
|
251
|
-
path :
|
|
252
|
+
path : SourcesOrListOfSources
|
|
252
253
|
Path(s) to read DataFrame from.
|
|
253
254
|
file_format : str
|
|
254
255
|
Extension of the file.
|
|
@@ -38,7 +38,7 @@ class SqlStoreConfigurator:
|
|
|
38
38
|
else:
|
|
39
39
|
config: SqlStoreConfig = SqlStoreConfig(**config)
|
|
40
40
|
for pair in [
|
|
41
|
-
(SqlStoreEnv.
|
|
41
|
+
(SqlStoreEnv.USERNAME.value, config.user),
|
|
42
42
|
(SqlStoreEnv.PASSWORD.value, config.password),
|
|
43
43
|
(SqlStoreEnv.HOST.value, config.host),
|
|
44
44
|
(SqlStoreEnv.PORT.value, config.port),
|
|
@@ -57,7 +57,7 @@ class SqlStoreConfigurator:
|
|
|
57
57
|
"""
|
|
58
58
|
creds = configurator.get_all_cred()
|
|
59
59
|
try:
|
|
60
|
-
user = creds[SqlStoreEnv.
|
|
60
|
+
user = creds[SqlStoreEnv.USERNAME.value]
|
|
61
61
|
password = creds[SqlStoreEnv.PASSWORD.value]
|
|
62
62
|
host = creds[SqlStoreEnv.HOST.value]
|
|
63
63
|
port = creds[SqlStoreEnv.PORT.value]
|
|
@@ -74,14 +74,14 @@ class SqlStoreConfigurator:
|
|
|
74
74
|
-------
|
|
75
75
|
None
|
|
76
76
|
"""
|
|
77
|
-
user = configurator.load_var(SqlStoreEnv.
|
|
77
|
+
user = configurator.load_var(SqlStoreEnv.USERNAME.value)
|
|
78
78
|
password = configurator.load_var(SqlStoreEnv.PASSWORD.value)
|
|
79
79
|
host = configurator.load_var(SqlStoreEnv.HOST.value)
|
|
80
80
|
port = configurator.load_var(SqlStoreEnv.PORT.value)
|
|
81
81
|
database = configurator.load_var(SqlStoreEnv.DATABASE.value)
|
|
82
82
|
if user is None or password is None or host is None or port is None or database is None:
|
|
83
83
|
raise StoreError("Missing credentials for SQL store.")
|
|
84
|
-
configurator.set_credential(SqlStoreEnv.
|
|
84
|
+
configurator.set_credential(SqlStoreEnv.USERNAME.value, user)
|
|
85
85
|
configurator.set_credential(SqlStoreEnv.PASSWORD.value, password)
|
|
86
86
|
configurator.set_credential(SqlStoreEnv.HOST.value, host)
|
|
87
87
|
configurator.set_credential(SqlStoreEnv.PORT.value, port)
|
digitalhub/stores/sql/enums.py
CHANGED
digitalhub/stores/sql/store.py
CHANGED
|
@@ -14,6 +14,7 @@ from digitalhub.readers.data.api import get_reader_by_object
|
|
|
14
14
|
from digitalhub.stores._base.store import Store
|
|
15
15
|
from digitalhub.stores.sql.configurator import SqlStoreConfigurator
|
|
16
16
|
from digitalhub.utils.exceptions import StoreError
|
|
17
|
+
from digitalhub.utils.types import SourcesOrListOfSources
|
|
17
18
|
|
|
18
19
|
if typing.TYPE_CHECKING:
|
|
19
20
|
from sqlalchemy.engine.row import Row
|
|
@@ -85,7 +86,7 @@ class SqlStore(Store):
|
|
|
85
86
|
|
|
86
87
|
def upload(
|
|
87
88
|
self,
|
|
88
|
-
src:
|
|
89
|
+
src: SourcesOrListOfSources,
|
|
89
90
|
dst: str,
|
|
90
91
|
) -> list[tuple[str, str]]:
|
|
91
92
|
"""
|
|
@@ -124,7 +125,7 @@ class SqlStore(Store):
|
|
|
124
125
|
|
|
125
126
|
def read_df(
|
|
126
127
|
self,
|
|
127
|
-
path:
|
|
128
|
+
path: SourcesOrListOfSources,
|
|
128
129
|
file_format: str | None = None,
|
|
129
130
|
engine: str | None = None,
|
|
130
131
|
**kwargs,
|
|
@@ -134,7 +135,7 @@ class SqlStore(Store):
|
|
|
134
135
|
|
|
135
136
|
Parameters
|
|
136
137
|
----------
|
|
137
|
-
path :
|
|
138
|
+
path : SourcesOrListOfSources
|
|
138
139
|
Path(s) to read DataFrame from.
|
|
139
140
|
file_format : str
|
|
140
141
|
Extension of the file.
|
|
@@ -148,6 +149,9 @@ class SqlStore(Store):
|
|
|
148
149
|
Any
|
|
149
150
|
DataFrame.
|
|
150
151
|
"""
|
|
152
|
+
if isinstance(path, list):
|
|
153
|
+
raise StoreError("SQL store can only read a single DataFrame at a time.")
|
|
154
|
+
|
|
151
155
|
reader = self._get_reader(engine)
|
|
152
156
|
schema = self._get_schema(path)
|
|
153
157
|
table = self._get_table_name(path)
|
digitalhub/utils/file_utils.py
CHANGED
|
@@ -4,6 +4,7 @@ from datetime import datetime
|
|
|
4
4
|
from hashlib import sha256
|
|
5
5
|
from mimetypes import guess_type
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
from typing import Optional
|
|
7
8
|
|
|
8
9
|
from pydantic import BaseModel
|
|
9
10
|
|
|
@@ -13,12 +14,12 @@ class FileInfo(BaseModel):
|
|
|
13
14
|
File info class.
|
|
14
15
|
"""
|
|
15
16
|
|
|
16
|
-
path: str = None
|
|
17
|
-
name: str = None
|
|
18
|
-
content_type: str = None
|
|
19
|
-
size: int = None
|
|
20
|
-
hash: str = None
|
|
21
|
-
last_modified: str = None
|
|
17
|
+
path: Optional[str] = None
|
|
18
|
+
name: Optional[str] = None
|
|
19
|
+
content_type: Optional[str] = None
|
|
20
|
+
size: Optional[int] = None
|
|
21
|
+
hash: Optional[str] = None
|
|
22
|
+
last_modified: Optional[str] = None
|
|
22
23
|
|
|
23
24
|
def to_dict(self):
|
|
24
25
|
return self.model_dump()
|
|
@@ -60,7 +61,7 @@ def get_file_size(data_path: str) -> int:
|
|
|
60
61
|
return Path(data_path).stat().st_size
|
|
61
62
|
|
|
62
63
|
|
|
63
|
-
def get_file_mime_type(data_path: str) -> str:
|
|
64
|
+
def get_file_mime_type(data_path: str) -> str | None:
|
|
64
65
|
"""
|
|
65
66
|
Get the mime type of a file.
|
|
66
67
|
|
|
@@ -4,8 +4,9 @@ import base64
|
|
|
4
4
|
import importlib.util as imputil
|
|
5
5
|
import json
|
|
6
6
|
from datetime import date, datetime, time
|
|
7
|
-
from enum import Enum
|
|
7
|
+
from enum import Enum, EnumMeta
|
|
8
8
|
from pathlib import Path
|
|
9
|
+
from types import MappingProxyType
|
|
9
10
|
from typing import Any, Callable
|
|
10
11
|
from zipfile import ZipFile
|
|
11
12
|
|
|
@@ -166,7 +167,7 @@ def dump_json(struct: Any) -> str:
|
|
|
166
167
|
str
|
|
167
168
|
The json string.
|
|
168
169
|
"""
|
|
169
|
-
return json.dumps(struct, cls=CustomJsonEncoder)
|
|
170
|
+
return json.dumps(struct, cls=CustomJsonEncoder)
|
|
170
171
|
|
|
171
172
|
|
|
172
173
|
def slugify_string(filename: str) -> str:
|
|
@@ -203,23 +204,34 @@ def import_function(path: Path, handler: str) -> Callable:
|
|
|
203
204
|
Function.
|
|
204
205
|
"""
|
|
205
206
|
spec = imputil.spec_from_file_location(path.stem, path)
|
|
207
|
+
if spec is None:
|
|
208
|
+
raise RuntimeError(f"Error loading function source from {str(path)}.")
|
|
209
|
+
|
|
206
210
|
mod = imputil.module_from_spec(spec)
|
|
211
|
+
if spec.loader is None:
|
|
212
|
+
raise RuntimeError(f"Error getting module loader from {str(path)}.")
|
|
213
|
+
|
|
207
214
|
spec.loader.exec_module(mod)
|
|
208
|
-
|
|
215
|
+
func = getattr(mod, handler)
|
|
216
|
+
if not callable(func):
|
|
217
|
+
raise RuntimeError(f"Handler '{handler}' is not a callable.")
|
|
218
|
+
|
|
219
|
+
return func
|
|
209
220
|
|
|
210
221
|
|
|
211
|
-
def list_enum(enum:
|
|
222
|
+
def list_enum(enum: EnumMeta) -> list[Any]:
|
|
212
223
|
"""
|
|
213
224
|
Get all values of an enum.
|
|
214
225
|
|
|
215
226
|
Parameters
|
|
216
227
|
----------
|
|
217
|
-
enum :
|
|
218
|
-
Enum to get values from.
|
|
228
|
+
enum : EnumMeta
|
|
229
|
+
Enum class to get values from.
|
|
219
230
|
|
|
220
231
|
Returns
|
|
221
232
|
-------
|
|
222
|
-
list
|
|
233
|
+
list[Any]
|
|
223
234
|
List of enum values.
|
|
224
235
|
"""
|
|
225
|
-
|
|
236
|
+
vals: MappingProxyType[str, Enum] = enum.__members__
|
|
237
|
+
return [member.value for member in vals.values()]
|
digitalhub/utils/uri_utils.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: digitalhub
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.0b4
|
|
4
4
|
Summary: Python SDK for Digitalhub
|
|
5
5
|
Project-URL: Homepage, https://github.com/scc-digitalhub/digitalhub-sdk
|
|
6
6
|
Author-email: Fondazione Bruno Kessler <dslab@fbk.eu>, Matteo Martini <mmartini@fbk.eu>
|