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
|
@@ -12,18 +12,12 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
|
|
|
12
12
|
"""
|
|
13
13
|
Parameter builder for DHCore client API calls.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
The builder handles various parameter transformations including:
|
|
22
|
-
- Query parameter formatting for different operations
|
|
23
|
-
- Search filter construction for Solr-based searches
|
|
24
|
-
- Cascade deletion options
|
|
25
|
-
- Versioning parameters
|
|
26
|
-
- Entity sharing parameters
|
|
15
|
+
Constructs HTTP request parameters for DHCore API operations, handling
|
|
16
|
+
parameter formats and query structures for both base-level operations
|
|
17
|
+
(project management) and context-level operations (entity operations
|
|
18
|
+
within projects). Supports query parameter formatting, search filter
|
|
19
|
+
construction for Solr-based searches, cascade deletion options,
|
|
20
|
+
versioning parameters, and entity sharing parameters.
|
|
27
21
|
|
|
28
22
|
Methods
|
|
29
23
|
-------
|
|
@@ -39,36 +33,27 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
|
|
|
39
33
|
"""
|
|
40
34
|
Build HTTP request parameters for DHCore API calls.
|
|
41
35
|
|
|
42
|
-
Routes parameter building to
|
|
43
|
-
|
|
44
|
-
parameter
|
|
36
|
+
Routes parameter building to appropriate method based on API category
|
|
37
|
+
(base or context operations) and applies operation-specific transformations.
|
|
38
|
+
Acts as dispatcher, initializing parameter dictionaries with 'params' key
|
|
39
|
+
for query parameters.
|
|
45
40
|
|
|
46
41
|
Parameters
|
|
47
42
|
----------
|
|
48
43
|
category : str
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
API category: 'base' for project-level operations or 'context'
|
|
45
|
+
for entity operations within projects.
|
|
51
46
|
operation : str
|
|
52
|
-
|
|
53
|
-
delete, list, search, etc.).
|
|
47
|
+
Specific API operation (create, read, update, delete, list, search, etc.).
|
|
54
48
|
**kwargs : dict
|
|
55
|
-
Raw parameters to
|
|
56
|
-
|
|
57
|
-
options, etc.
|
|
49
|
+
Raw parameters to transform including entity identifiers, filter
|
|
50
|
+
criteria, pagination options, etc.
|
|
58
51
|
|
|
59
52
|
Returns
|
|
60
53
|
-------
|
|
61
54
|
dict
|
|
62
|
-
Formatted parameters dictionary
|
|
63
|
-
|
|
64
|
-
request-specific parameters.
|
|
65
|
-
|
|
66
|
-
Notes
|
|
67
|
-
-----
|
|
68
|
-
This method acts as a dispatcher, routing to either base or context
|
|
69
|
-
parameter building based on the category. All parameter dictionaries
|
|
70
|
-
are initialized with a 'params' key for query parameters if not
|
|
71
|
-
already present.
|
|
55
|
+
Formatted parameters dictionary with 'params' key for query parameters
|
|
56
|
+
and other request-specific parameters.
|
|
72
57
|
"""
|
|
73
58
|
if category == ApiCategories.BASE.value:
|
|
74
59
|
return self.build_parameters_base(operation, **kwargs)
|
|
@@ -78,18 +63,18 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
|
|
|
78
63
|
"""
|
|
79
64
|
Build parameters for base-level API operations.
|
|
80
65
|
|
|
81
|
-
Constructs HTTP request parameters for operations
|
|
82
|
-
|
|
83
|
-
|
|
66
|
+
Constructs HTTP request parameters for project-level operations and
|
|
67
|
+
entity sharing functionality. Handles CASCADE (boolean to lowercase string),
|
|
68
|
+
SHARE (user parameter to query params), and UNSHARE (requires unshare=True
|
|
69
|
+
and entity id).
|
|
84
70
|
|
|
85
71
|
Parameters
|
|
86
72
|
----------
|
|
87
73
|
operation : str
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- SHARE: Entity sharing/unsharing with users
|
|
74
|
+
API operation: DELETE (project deletion with optional cascade)
|
|
75
|
+
or SHARE (entity sharing/unsharing with users).
|
|
91
76
|
**kwargs : dict
|
|
92
|
-
Operation-specific parameters
|
|
77
|
+
Operation-specific parameters:
|
|
93
78
|
- cascade (bool): For DELETE, whether to cascade delete
|
|
94
79
|
- user (str): For SHARE, target user for sharing
|
|
95
80
|
- unshare (bool): For SHARE, whether to unshare instead
|
|
@@ -98,15 +83,7 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
|
|
|
98
83
|
Returns
|
|
99
84
|
-------
|
|
100
85
|
dict
|
|
101
|
-
Formatted parameters with 'params' containing query parameters
|
|
102
|
-
and other request-specific parameters.
|
|
103
|
-
|
|
104
|
-
Notes
|
|
105
|
-
-----
|
|
106
|
-
Parameter transformations:
|
|
107
|
-
- CASCADE: Boolean values are converted to lowercase strings
|
|
108
|
-
- SHARE: User parameter is moved to query params
|
|
109
|
-
- UNSHARE: Requires both unshare=True and entity id
|
|
86
|
+
Formatted parameters with 'params' containing query parameters.
|
|
110
87
|
"""
|
|
111
88
|
kwargs = self._set_params(**kwargs)
|
|
112
89
|
if operation == BackendOperations.DELETE.value:
|
|
@@ -123,23 +100,22 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
|
|
|
123
100
|
"""
|
|
124
101
|
Build parameters for context-level API operations.
|
|
125
102
|
|
|
126
|
-
Constructs HTTP request parameters for
|
|
127
|
-
|
|
128
|
-
|
|
103
|
+
Constructs HTTP request parameters for entity management and search within
|
|
104
|
+
projects. Handles search filters via 'filter' parameter, pagination with
|
|
105
|
+
'page' and 'size', result ordering with 'sort' parameter. READ supports
|
|
106
|
+
embedded entity inclusion, DELETE requires entity 'id' parameter.
|
|
129
107
|
|
|
130
108
|
Parameters
|
|
131
109
|
----------
|
|
132
110
|
operation : str
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
- DELETE: Delete specific entity by ID
|
|
137
|
-
- READ: Read specific entity by ID (with optional embedded)
|
|
111
|
+
API operation: SEARCH (search entities with filtering), READ_MANY
|
|
112
|
+
(retrieve multiple with pagination), DELETE (delete by ID),
|
|
113
|
+
READ (read by ID with optional embedded).
|
|
138
114
|
**kwargs : dict
|
|
139
|
-
Operation-specific parameters
|
|
115
|
+
Operation-specific parameters:
|
|
140
116
|
- params (dict): Search filters and conditions
|
|
141
117
|
- page (int): Page number for pagination (default: 0)
|
|
142
|
-
- size (int):
|
|
118
|
+
- size (int): Items per page (default: 20)
|
|
143
119
|
- order_by (str): Field to order results by
|
|
144
120
|
- order (str): Order direction ('asc' or 'desc')
|
|
145
121
|
- embedded (bool): For READ, whether to include embedded entities
|
|
@@ -148,19 +124,8 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
|
|
|
148
124
|
Returns
|
|
149
125
|
-------
|
|
150
126
|
dict
|
|
151
|
-
Formatted parameters with 'params'
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
Notes
|
|
155
|
-
-----
|
|
156
|
-
Search and pagination:
|
|
157
|
-
- Filters are applied via 'filter' parameter in query string
|
|
158
|
-
- Pagination uses 'page' and 'size' parameters
|
|
159
|
-
- Results can be ordered using 'sort' parameter format
|
|
160
|
-
|
|
161
|
-
Entity operations:
|
|
162
|
-
- READ: Supports embedded entity inclusion via 'embedded' param
|
|
163
|
-
- DELETE: Requires entity 'id' parameter
|
|
127
|
+
Formatted parameters with 'params' for query parameters and
|
|
128
|
+
other request-specific parameters like 'id' for entity operations.
|
|
164
129
|
"""
|
|
165
130
|
kwargs = self._set_params(**kwargs)
|
|
166
131
|
|
|
@@ -249,27 +214,20 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
|
|
|
249
214
|
"""
|
|
250
215
|
Initialize parameter dictionary with query parameters structure.
|
|
251
216
|
|
|
252
|
-
Ensures
|
|
253
|
-
|
|
254
|
-
parameter building methods to guarantee consistent structure.
|
|
217
|
+
Ensures parameter dictionary has 'params' key for HTTP query parameters,
|
|
218
|
+
guaranteeing consistent structure for all parameter building methods.
|
|
255
219
|
|
|
256
220
|
Parameters
|
|
257
221
|
----------
|
|
258
222
|
**kwargs : dict
|
|
259
|
-
Keyword arguments to
|
|
260
|
-
|
|
223
|
+
Keyword arguments to format. May be empty or contain various
|
|
224
|
+
parameters for API operations.
|
|
261
225
|
|
|
262
226
|
Returns
|
|
263
227
|
-------
|
|
264
228
|
dict
|
|
265
229
|
Parameters dictionary with guaranteed 'params' key containing
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
Notes
|
|
269
|
-
-----
|
|
270
|
-
This method is called at the beginning of all parameter building
|
|
271
|
-
methods to ensure consistent dictionary structure for query
|
|
272
|
-
parameter handling.
|
|
230
|
+
empty dict if not already present.
|
|
273
231
|
"""
|
|
274
232
|
if not kwargs:
|
|
275
233
|
kwargs = {}
|
|
@@ -23,36 +23,30 @@ def set_dhcore_env(
|
|
|
23
23
|
client_id: str | None = None,
|
|
24
24
|
) -> None:
|
|
25
25
|
"""
|
|
26
|
-
|
|
26
|
+
Set DHCore environment variables and reload client configuration.
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
reloads the client configurator to
|
|
30
|
-
|
|
31
|
-
will be overwritten.
|
|
28
|
+
Updates environment variables for DHCore configuration and automatically
|
|
29
|
+
reloads the client configurator to apply new settings. Overwrites existing
|
|
30
|
+
environment variables if already set.
|
|
32
31
|
|
|
33
32
|
Parameters
|
|
34
33
|
----------
|
|
35
34
|
endpoint : str, optional
|
|
36
|
-
|
|
35
|
+
DHCore backend endpoint URL.
|
|
37
36
|
user : str, optional
|
|
38
|
-
|
|
37
|
+
Username for basic authentication.
|
|
39
38
|
password : str, optional
|
|
40
|
-
|
|
39
|
+
Password for basic authentication.
|
|
41
40
|
access_token : str, optional
|
|
42
|
-
|
|
41
|
+
OAuth2 access token.
|
|
43
42
|
refresh_token : str, optional
|
|
44
|
-
|
|
43
|
+
OAuth2 refresh token.
|
|
45
44
|
client_id : str, optional
|
|
46
|
-
|
|
45
|
+
OAuth2 client identifier.
|
|
47
46
|
|
|
48
47
|
Returns
|
|
49
48
|
-------
|
|
50
49
|
None
|
|
51
|
-
|
|
52
|
-
Notes
|
|
53
|
-
-----
|
|
54
|
-
After setting the environment variables, this function automatically
|
|
55
|
-
reloads the client configurator to apply the new configuration.
|
|
56
50
|
"""
|
|
57
51
|
if endpoint is not None:
|
|
58
52
|
os.environ[CredsEnvVar.DHCORE_ENDPOINT.value] = endpoint
|
|
@@ -73,11 +67,10 @@ def set_dhcore_env(
|
|
|
73
67
|
|
|
74
68
|
def refresh_token() -> None:
|
|
75
69
|
"""
|
|
76
|
-
|
|
70
|
+
Refresh the current OAuth2 access token.
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
requires that the client be configured with OAuth2 authentication.
|
|
72
|
+
Uses the refresh token stored in client configuration to obtain a new
|
|
73
|
+
access token. Requires OAuth2 authentication configuration.
|
|
81
74
|
|
|
82
75
|
Returns
|
|
83
76
|
-------
|
|
@@ -86,8 +79,7 @@ def refresh_token() -> None:
|
|
|
86
79
|
Raises
|
|
87
80
|
------
|
|
88
81
|
ClientError
|
|
89
|
-
If
|
|
90
|
-
refresh fails.
|
|
82
|
+
If client not properly configured or token refresh fails.
|
|
91
83
|
"""
|
|
92
84
|
client: ClientDHCore = get_client(local=False)
|
|
93
85
|
client._configurator.check_config()
|
|
@@ -207,7 +207,16 @@ class ClientLocal(Client):
|
|
|
207
207
|
|
|
208
208
|
else:
|
|
209
209
|
name = obj.get("name", entity_id)
|
|
210
|
-
self._db[entity_type][name]
|
|
210
|
+
container = self._db[entity_type][name]
|
|
211
|
+
container[entity_id] = obj
|
|
212
|
+
|
|
213
|
+
# Keep the "latest" pointer consistent when updating the latest entity
|
|
214
|
+
try:
|
|
215
|
+
if container.get("latest", {}).get("id") == entity_id:
|
|
216
|
+
container["latest"] = obj
|
|
217
|
+
except AttributeError:
|
|
218
|
+
# In case "latest" is malformed, ignore and continue
|
|
219
|
+
pass
|
|
211
220
|
|
|
212
221
|
except KeyError:
|
|
213
222
|
msg = self._format_msg(3, entity_type=entity_type, entity_id=entity_id)
|
|
@@ -253,55 +262,51 @@ class ClientLocal(Client):
|
|
|
253
262
|
|
|
254
263
|
# Name is optional and extracted from kwargs
|
|
255
264
|
# "params": {"name": <name>}
|
|
256
|
-
|
|
265
|
+
name_param = kwargs.get("params", {}).get("name")
|
|
257
266
|
|
|
258
|
-
# Delete by name
|
|
259
|
-
if entity_id is None and
|
|
260
|
-
self._db[entity_type].pop(
|
|
267
|
+
# Delete by name (remove the whole named container)
|
|
268
|
+
if entity_id is None and name_param is not None:
|
|
269
|
+
self._db[entity_type].pop(name_param, None)
|
|
261
270
|
return {"deleted": True}
|
|
262
271
|
|
|
263
272
|
# Delete by id
|
|
264
|
-
|
|
273
|
+
found_name: str | None = None
|
|
274
|
+
container: dict | None = None
|
|
275
|
+
for n, v in self._db[entity_type].items():
|
|
265
276
|
if entity_id in v:
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
# Handle latest
|
|
269
|
-
if v["latest"]["id"] == entity_id:
|
|
270
|
-
name = v["latest"].get("name", entity_id)
|
|
271
|
-
v.pop("latest")
|
|
272
|
-
reset_latest = True
|
|
277
|
+
found_name = n
|
|
278
|
+
container = v
|
|
273
279
|
break
|
|
274
280
|
else:
|
|
275
281
|
raise KeyError
|
|
276
282
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
self._db[entity_type][name]["latest"] = self._db[entity_type][name][latest_uuid]
|
|
283
|
+
# Remove the entity from the container
|
|
284
|
+
assert container is not None # for type checkers
|
|
285
|
+
container.pop(entity_id)
|
|
286
|
+
|
|
287
|
+
# Handle latest pointer if needed
|
|
288
|
+
if container.get("latest", {}).get("id") == entity_id:
|
|
289
|
+
# Remove stale latest
|
|
290
|
+
container.pop("latest", None)
|
|
291
|
+
reset_latest = True
|
|
292
|
+
|
|
293
|
+
# If container is now empty, drop it entirely
|
|
294
|
+
if not container:
|
|
295
|
+
assert found_name is not None
|
|
296
|
+
self._db[entity_type].pop(found_name, None)
|
|
297
|
+
# Otherwise, recompute latest if required
|
|
298
|
+
elif reset_latest:
|
|
299
|
+
latest_uuid = None
|
|
300
|
+
latest_date = None
|
|
301
|
+
for k, v in container.items():
|
|
302
|
+
# Parse creation time from metadata; tolerate various formats
|
|
303
|
+
current_created = self._safe_parse_created(v)
|
|
304
|
+
if latest_date is None or current_created > latest_date:
|
|
305
|
+
latest_uuid = k
|
|
306
|
+
latest_date = current_created
|
|
307
|
+
|
|
308
|
+
if latest_uuid is not None:
|
|
309
|
+
container["latest"] = container[latest_uuid]
|
|
305
310
|
|
|
306
311
|
except KeyError:
|
|
307
312
|
msg = self._format_msg(3, entity_type=entity_type, entity_id=entity_id)
|
|
@@ -330,7 +335,10 @@ class ClientLocal(Client):
|
|
|
330
335
|
# "params": {"name": <name>}
|
|
331
336
|
name = kwargs.get("params", {}).get("name")
|
|
332
337
|
if name is not None:
|
|
333
|
-
|
|
338
|
+
try:
|
|
339
|
+
return [self._db[entity_type][name]["latest"]]
|
|
340
|
+
except KeyError:
|
|
341
|
+
return []
|
|
334
342
|
|
|
335
343
|
try:
|
|
336
344
|
# If no name is provided, get latest objects
|
|
@@ -343,7 +351,7 @@ class ClientLocal(Client):
|
|
|
343
351
|
if kind is not None:
|
|
344
352
|
listed_objects = [obj for obj in listed_objects if obj["kind"] == kind]
|
|
345
353
|
|
|
346
|
-
# If function is provided, return objects by function
|
|
354
|
+
# If function/task is provided, return objects by function/task
|
|
347
355
|
spec_params = ["function", "task"]
|
|
348
356
|
for i in spec_params:
|
|
349
357
|
p = kwargs.get("params", {}).get(i)
|
|
@@ -489,14 +497,15 @@ class ClientLocal(Client):
|
|
|
489
497
|
"""
|
|
490
498
|
# Deepcopy to avoid modifying the original object
|
|
491
499
|
project = deepcopy(obj)
|
|
492
|
-
spec
|
|
500
|
+
# Ensure spec exists on the returned project
|
|
501
|
+
spec = project.setdefault("spec", {})
|
|
493
502
|
|
|
494
503
|
# Get all entities associated with the project specs
|
|
495
504
|
projects_entities = [k for k, _ in self._db.items() if k not in ["projects", "runs", "tasks"]]
|
|
496
505
|
|
|
497
506
|
for entity_type in projects_entities:
|
|
498
507
|
# Get all objects of the entity type for the project
|
|
499
|
-
objs = self._db
|
|
508
|
+
objs = self._db.get(entity_type, {})
|
|
500
509
|
|
|
501
510
|
# Set empty list
|
|
502
511
|
spec[entity_type] = []
|
|
@@ -521,6 +530,29 @@ class ClientLocal(Client):
|
|
|
521
530
|
|
|
522
531
|
return project
|
|
523
532
|
|
|
533
|
+
@staticmethod
|
|
534
|
+
def _safe_parse_created(obj: dict) -> datetime:
|
|
535
|
+
"""
|
|
536
|
+
Safely parse the creation datetime of an object.
|
|
537
|
+
|
|
538
|
+
- Accepts ISO format with optional 'Z'.
|
|
539
|
+
- If tzinfo is missing, assume UTC.
|
|
540
|
+
- Falls back to epoch if missing/invalid.
|
|
541
|
+
"""
|
|
542
|
+
created_raw = obj.get("metadata", {}).get("created")
|
|
543
|
+
fallback = datetime.fromtimestamp(0, timezone.utc)
|
|
544
|
+
if not created_raw or not isinstance(created_raw, str):
|
|
545
|
+
return fallback
|
|
546
|
+
try:
|
|
547
|
+
# Support trailing 'Z'
|
|
548
|
+
ts = created_raw.replace("Z", "+00:00")
|
|
549
|
+
dt = datetime.fromisoformat(ts)
|
|
550
|
+
if dt.tzinfo is None:
|
|
551
|
+
dt = dt.replace(tzinfo=timezone.utc)
|
|
552
|
+
return dt
|
|
553
|
+
except Exception:
|
|
554
|
+
return fallback
|
|
555
|
+
|
|
524
556
|
##############################
|
|
525
557
|
# Utils
|
|
526
558
|
##############################
|
|
@@ -146,19 +146,3 @@ def set_current_profile(environment: str) -> None:
|
|
|
146
146
|
|
|
147
147
|
except Exception as e:
|
|
148
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
|
digitalhub/stores/data/api.py
CHANGED
|
@@ -37,7 +37,7 @@ def get_default_store(project: str) -> str:
|
|
|
37
37
|
var = StoreEnv.DEFAULT_FILES_STORE.value
|
|
38
38
|
|
|
39
39
|
context = get_context(project)
|
|
40
|
-
store = context.config.get(var.lower())
|
|
40
|
+
store = context.config.get(var.lower().replace("dhcore_", ""))
|
|
41
41
|
if store is not None:
|
|
42
42
|
return store
|
|
43
43
|
|
|
@@ -21,6 +21,20 @@ if typing.TYPE_CHECKING:
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class StoreInfo:
|
|
24
|
+
"""
|
|
25
|
+
Container for store class and configurator information.
|
|
26
|
+
|
|
27
|
+
Holds store class references and their associated configurators
|
|
28
|
+
for registration and instantiation in the store builder system.
|
|
29
|
+
|
|
30
|
+
Attributes
|
|
31
|
+
----------
|
|
32
|
+
_store : Store
|
|
33
|
+
The store class to be instantiated.
|
|
34
|
+
_configurator : Configurator or None
|
|
35
|
+
The configurator class for store configuration, if required.
|
|
36
|
+
"""
|
|
37
|
+
|
|
24
38
|
def __init__(self, store: Store, configurator: Configurator | None = None) -> None:
|
|
25
39
|
self._store = store
|
|
26
40
|
self._configurator = configurator
|
|
@@ -28,7 +42,19 @@ class StoreInfo:
|
|
|
28
42
|
|
|
29
43
|
class StoreBuilder:
|
|
30
44
|
"""
|
|
31
|
-
Store
|
|
45
|
+
Store factory and registry for managing data store instances.
|
|
46
|
+
|
|
47
|
+
Provides registration, instantiation, and caching of data store
|
|
48
|
+
instances based on URI schemes. Supports various store types
|
|
49
|
+
including S3, SQL, local, and remote stores with their respective
|
|
50
|
+
configurators.
|
|
51
|
+
|
|
52
|
+
Attributes
|
|
53
|
+
----------
|
|
54
|
+
_builders : dict[str, StoreInfo]
|
|
55
|
+
Registry of store types mapped to their StoreInfo instances.
|
|
56
|
+
_instances : dict[str, Store]
|
|
57
|
+
Cache of instantiated store instances by store type.
|
|
32
58
|
"""
|
|
33
59
|
|
|
34
60
|
def __init__(self) -> None:
|
|
@@ -41,6 +67,31 @@ class StoreBuilder:
|
|
|
41
67
|
store: Store,
|
|
42
68
|
configurator: Configurator | None = None,
|
|
43
69
|
) -> None:
|
|
70
|
+
"""
|
|
71
|
+
Register a store type with its class and optional configurator.
|
|
72
|
+
|
|
73
|
+
Adds a new store type to the builder registry, associating it
|
|
74
|
+
with a store class and optional configurator for later instantiation.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
store_type : str
|
|
79
|
+
The unique identifier for the store type (e.g., 's3', 'sql').
|
|
80
|
+
store : Store
|
|
81
|
+
The store class to register for this type.
|
|
82
|
+
configurator : Configurator, optional
|
|
83
|
+
The configurator class for store configuration.
|
|
84
|
+
If None, the store will be instantiated without configuration.
|
|
85
|
+
|
|
86
|
+
Returns
|
|
87
|
+
-------
|
|
88
|
+
None
|
|
89
|
+
|
|
90
|
+
Raises
|
|
91
|
+
------
|
|
92
|
+
StoreError
|
|
93
|
+
If the store type is already registered in the builder.
|
|
94
|
+
"""
|
|
44
95
|
if store_type not in self._builders:
|
|
45
96
|
self._builders[store_type] = StoreInfo(store, configurator)
|
|
46
97
|
else:
|
|
@@ -48,17 +99,28 @@ class StoreBuilder:
|
|
|
48
99
|
|
|
49
100
|
def get(self, uri: str) -> Store:
|
|
50
101
|
"""
|
|
51
|
-
Get a store instance
|
|
102
|
+
Get or create a store instance based on URI scheme.
|
|
103
|
+
|
|
104
|
+
Determines the appropriate store type from the URI scheme,
|
|
105
|
+
instantiates the store if not already cached, and returns
|
|
106
|
+
the store instance. Store instances are cached for reuse.
|
|
52
107
|
|
|
53
108
|
Parameters
|
|
54
109
|
----------
|
|
55
110
|
uri : str
|
|
56
|
-
URI to parse.
|
|
111
|
+
The URI to parse for determining the store type.
|
|
112
|
+
The scheme (e.g., 's3://', 'sql://') determines which
|
|
113
|
+
store type to instantiate.
|
|
57
114
|
|
|
58
115
|
Returns
|
|
59
116
|
-------
|
|
60
117
|
Store
|
|
61
|
-
The store instance.
|
|
118
|
+
The store instance appropriate for handling the given URI.
|
|
119
|
+
|
|
120
|
+
Raises
|
|
121
|
+
------
|
|
122
|
+
KeyError
|
|
123
|
+
If no store is registered for the URI scheme.
|
|
62
124
|
"""
|
|
63
125
|
store_type = map_uri_scheme(uri)
|
|
64
126
|
|