digitalhub 0.8.1__py3-none-any.whl → 0.9.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 +19 -2
- digitalhub/client/_base/api_builder.py +16 -0
- digitalhub/client/_base/client.py +31 -0
- digitalhub/client/api.py +2 -38
- digitalhub/client/dhcore/api_builder.py +100 -0
- digitalhub/client/dhcore/client.py +77 -24
- digitalhub/client/dhcore/enums.py +26 -0
- digitalhub/client/dhcore/env.py +2 -2
- digitalhub/client/dhcore/utils.py +17 -17
- digitalhub/client/local/api_builder.py +100 -0
- digitalhub/client/local/client.py +20 -0
- digitalhub/context/api.py +3 -38
- digitalhub/context/builder.py +10 -23
- digitalhub/context/context.py +20 -92
- digitalhub/entities/_base/context/entity.py +30 -22
- digitalhub/entities/_base/entity/_constructors/metadata.py +12 -1
- digitalhub/entities/_base/entity/_constructors/name.py +1 -1
- digitalhub/entities/_base/entity/_constructors/spec.py +1 -1
- digitalhub/entities/_base/entity/_constructors/status.py +3 -2
- digitalhub/entities/_base/entity/builder.py +6 -1
- digitalhub/entities/_base/entity/entity.py +30 -10
- digitalhub/entities/_base/entity/metadata.py +22 -0
- digitalhub/entities/_base/entity/spec.py +7 -2
- digitalhub/entities/_base/executable/entity.py +8 -8
- digitalhub/entities/_base/material/entity.py +48 -16
- digitalhub/entities/_base/material/status.py +0 -31
- digitalhub/entities/_base/material/utils.py +106 -0
- digitalhub/entities/_base/project/entity.py +341 -0
- digitalhub/entities/_base/unversioned/entity.py +1 -23
- digitalhub/entities/_base/versioned/entity.py +0 -25
- digitalhub/entities/_commons/enums.py +103 -0
- digitalhub/entities/_commons/utils.py +83 -0
- digitalhub/entities/_operations/processor.py +1747 -0
- digitalhub/entities/artifact/_base/builder.py +1 -1
- digitalhub/entities/artifact/_base/entity.py +1 -1
- digitalhub/entities/artifact/artifact/builder.py +2 -1
- digitalhub/entities/artifact/crud.py +46 -29
- digitalhub/entities/artifact/utils.py +62 -0
- digitalhub/entities/dataitem/_base/builder.py +1 -1
- digitalhub/entities/dataitem/_base/entity.py +6 -6
- digitalhub/entities/dataitem/crud.py +50 -66
- digitalhub/entities/dataitem/dataitem/builder.py +2 -1
- digitalhub/entities/dataitem/iceberg/builder.py +2 -1
- digitalhub/entities/dataitem/table/builder.py +2 -1
- digitalhub/entities/dataitem/table/entity.py +5 -10
- digitalhub/entities/dataitem/table/models.py +4 -5
- digitalhub/entities/dataitem/utils.py +137 -0
- digitalhub/entities/function/_base/builder.py +1 -1
- digitalhub/entities/function/_base/entity.py +5 -1
- digitalhub/entities/function/crud.py +36 -17
- digitalhub/entities/model/_base/builder.py +1 -1
- digitalhub/entities/model/_base/entity.py +1 -1
- digitalhub/entities/model/crud.py +46 -29
- digitalhub/entities/model/huggingface/builder.py +2 -1
- digitalhub/entities/model/huggingface/spec.py +4 -2
- digitalhub/entities/model/mlflow/builder.py +2 -1
- digitalhub/entities/model/mlflow/models.py +17 -9
- digitalhub/entities/model/mlflow/spec.py +6 -1
- digitalhub/entities/model/mlflow/utils.py +4 -2
- digitalhub/entities/model/model/builder.py +2 -1
- digitalhub/entities/model/sklearn/builder.py +2 -1
- digitalhub/entities/model/utils.py +62 -0
- digitalhub/entities/project/_base/builder.py +2 -2
- digitalhub/entities/project/_base/entity.py +82 -272
- digitalhub/entities/project/crud.py +110 -91
- digitalhub/entities/project/utils.py +35 -0
- digitalhub/entities/run/_base/builder.py +3 -1
- digitalhub/entities/run/_base/entity.py +52 -54
- digitalhub/entities/run/_base/spec.py +11 -7
- digitalhub/entities/run/crud.py +35 -17
- digitalhub/entities/secret/_base/builder.py +2 -2
- digitalhub/entities/secret/_base/entity.py +4 -10
- digitalhub/entities/secret/crud.py +36 -21
- digitalhub/entities/task/_base/builder.py +14 -14
- digitalhub/entities/task/_base/entity.py +6 -6
- digitalhub/entities/task/_base/models.py +29 -6
- digitalhub/entities/task/_base/spec.py +44 -13
- digitalhub/entities/task/_base/utils.py +18 -0
- digitalhub/entities/task/crud.py +35 -15
- digitalhub/entities/workflow/_base/builder.py +1 -1
- digitalhub/entities/workflow/_base/entity.py +14 -6
- digitalhub/entities/workflow/crud.py +36 -17
- digitalhub/factory/utils.py +1 -1
- digitalhub/readers/_base/reader.py +2 -2
- digitalhub/readers/_commons/enums.py +13 -0
- digitalhub/readers/api.py +3 -2
- digitalhub/readers/factory.py +12 -6
- digitalhub/readers/pandas/reader.py +20 -8
- digitalhub/runtimes/_base.py +0 -7
- digitalhub/stores/_base/store.py +53 -9
- digitalhub/stores/builder.py +5 -5
- digitalhub/stores/local/store.py +37 -2
- digitalhub/stores/remote/store.py +25 -3
- digitalhub/stores/s3/store.py +34 -7
- digitalhub/stores/sql/store.py +112 -45
- digitalhub/utils/exceptions.py +6 -0
- digitalhub/utils/file_utils.py +60 -2
- digitalhub/utils/generic_utils.py +45 -4
- digitalhub/utils/io_utils.py +18 -0
- digitalhub/utils/uri_utils.py +153 -15
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/METADATA +2 -2
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/RECORD +110 -113
- test/testkfp.py +4 -1
- digitalhub/datastores/_base/datastore.py +0 -85
- digitalhub/datastores/api.py +0 -37
- digitalhub/datastores/builder.py +0 -110
- digitalhub/datastores/local/datastore.py +0 -50
- digitalhub/datastores/remote/__init__.py +0 -0
- digitalhub/datastores/remote/datastore.py +0 -31
- digitalhub/datastores/s3/__init__.py +0 -0
- digitalhub/datastores/s3/datastore.py +0 -46
- digitalhub/datastores/sql/__init__.py +0 -0
- digitalhub/datastores/sql/datastore.py +0 -68
- digitalhub/entities/_base/api_utils.py +0 -620
- digitalhub/entities/_base/crud.py +0 -468
- digitalhub/entities/function/_base/models.py +0 -118
- digitalhub/entities/utils/__init__.py +0 -0
- digitalhub/entities/utils/api.py +0 -346
- digitalhub/entities/utils/entity_types.py +0 -19
- digitalhub/entities/utils/state.py +0 -31
- digitalhub/entities/utils/utils.py +0 -202
- /digitalhub/{context → entities/_base/project}/__init__.py +0 -0
- /digitalhub/{datastores → entities/_commons}/__init__.py +0 -0
- /digitalhub/{datastores/_base → entities/_operations}/__init__.py +0 -0
- /digitalhub/{datastores/local → readers/_commons}/__init__.py +0 -0
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/LICENSE.txt +0 -0
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/WHEEL +0 -0
- {digitalhub-0.8.1.dist-info → digitalhub-0.9.0b0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from digitalhub.client._base.api_builder import ClientApiBuilder
|
|
4
|
+
from digitalhub.entities._commons.enums import ApiCategories, BackendOperations
|
|
5
|
+
from digitalhub.utils.exceptions import BackendError
|
|
6
|
+
|
|
7
|
+
API_BASE = "/api/v1"
|
|
8
|
+
API_CONTEXT = f"{API_BASE}/-"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ClientLocalApiBuilder(ClientApiBuilder):
|
|
12
|
+
"""
|
|
13
|
+
This class is used to build the API for the Local client.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def build_api(self, category: str, operation: str, **kwargs) -> str:
|
|
17
|
+
"""
|
|
18
|
+
Build the API for the client.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
category : str
|
|
23
|
+
API category.
|
|
24
|
+
operation : str
|
|
25
|
+
API operation.
|
|
26
|
+
**kwargs : dict
|
|
27
|
+
Additional parameters.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
str
|
|
32
|
+
API formatted.
|
|
33
|
+
"""
|
|
34
|
+
if category == ApiCategories.BASE.value:
|
|
35
|
+
return self.build_api_base(operation, **kwargs)
|
|
36
|
+
return self.build_api_context(operation, **kwargs)
|
|
37
|
+
|
|
38
|
+
def build_api_base(self, operation: str, **kwargs) -> str:
|
|
39
|
+
"""
|
|
40
|
+
Build the base API for the client.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
operation : str
|
|
45
|
+
API operation.
|
|
46
|
+
**kwargs : dict
|
|
47
|
+
Additional parameters.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
str
|
|
52
|
+
API formatted.
|
|
53
|
+
"""
|
|
54
|
+
entity_type = kwargs["entity_type"] + "s"
|
|
55
|
+
if operation in (
|
|
56
|
+
BackendOperations.CREATE.value,
|
|
57
|
+
BackendOperations.LIST.value,
|
|
58
|
+
):
|
|
59
|
+
return f"{API_BASE}/{entity_type}"
|
|
60
|
+
elif operation in (
|
|
61
|
+
BackendOperations.READ.value,
|
|
62
|
+
BackendOperations.UPDATE.value,
|
|
63
|
+
BackendOperations.DELETE.value,
|
|
64
|
+
):
|
|
65
|
+
return f"{API_BASE}/{entity_type}/{kwargs['entity_name']}"
|
|
66
|
+
elif operation == BackendOperations.SHARE.value:
|
|
67
|
+
raise BackendError("Share API not implemented for Local.")
|
|
68
|
+
raise BackendError(f"Invalid operation '{operation}' for entity type '{entity_type}' in Local.")
|
|
69
|
+
|
|
70
|
+
def build_api_context(self, operation: str, **kwargs) -> str:
|
|
71
|
+
"""
|
|
72
|
+
Build the context API for the client.
|
|
73
|
+
"""
|
|
74
|
+
entity_type = kwargs["entity_type"] + "s"
|
|
75
|
+
project = kwargs["project"]
|
|
76
|
+
if operation in (
|
|
77
|
+
BackendOperations.CREATE.value,
|
|
78
|
+
BackendOperations.LIST.value,
|
|
79
|
+
):
|
|
80
|
+
return f"{API_CONTEXT}/{project}/{entity_type}"
|
|
81
|
+
elif operation in (
|
|
82
|
+
BackendOperations.READ.value,
|
|
83
|
+
BackendOperations.UPDATE.value,
|
|
84
|
+
BackendOperations.DELETE.value,
|
|
85
|
+
):
|
|
86
|
+
return f"{API_CONTEXT}/{project}/{entity_type}/{kwargs['entity_id']}"
|
|
87
|
+
elif operation == BackendOperations.LOGS.value:
|
|
88
|
+
raise BackendError("Logs run API not implemented for Local.")
|
|
89
|
+
elif operation == BackendOperations.STOP.value:
|
|
90
|
+
raise BackendError("Stop run API not implemented for Local.")
|
|
91
|
+
elif operation == BackendOperations.RESUME.value:
|
|
92
|
+
raise BackendError("Resume run API not implemented for Local.")
|
|
93
|
+
elif operation == BackendOperations.DATA.value:
|
|
94
|
+
raise BackendError("Secret API (read/set value) not implemented for Local.")
|
|
95
|
+
elif operation == BackendOperations.FILES.value:
|
|
96
|
+
raise BackendError("Files API not implemented for Local.")
|
|
97
|
+
elif operation == BackendOperations.SEARCH.value:
|
|
98
|
+
raise BackendError("Search API not implemented for Local.")
|
|
99
|
+
|
|
100
|
+
raise BackendError(f"Invalid operation '{operation}' for entity type '{entity_type}' in Local.")
|
|
@@ -4,6 +4,7 @@ from copy import deepcopy
|
|
|
4
4
|
from datetime import datetime, timezone
|
|
5
5
|
|
|
6
6
|
from digitalhub.client._base.client import Client
|
|
7
|
+
from digitalhub.client.local.api_builder import ClientLocalApiBuilder
|
|
7
8
|
from digitalhub.utils.exceptions import BackendError
|
|
8
9
|
|
|
9
10
|
|
|
@@ -22,6 +23,7 @@ class ClientLocal(Client):
|
|
|
22
23
|
|
|
23
24
|
def __init__(self) -> None:
|
|
24
25
|
super().__init__()
|
|
26
|
+
self._api_builder = ClientLocalApiBuilder()
|
|
25
27
|
self._db: dict[str, dict[str, dict]] = {}
|
|
26
28
|
|
|
27
29
|
##############################
|
|
@@ -349,6 +351,24 @@ class ClientLocal(Client):
|
|
|
349
351
|
except IndexError:
|
|
350
352
|
raise IndexError("No objects found")
|
|
351
353
|
|
|
354
|
+
def search_objects(self, api: str, **kwargs) -> dict:
|
|
355
|
+
"""
|
|
356
|
+
Search objects from Local.
|
|
357
|
+
|
|
358
|
+
Parameters
|
|
359
|
+
----------
|
|
360
|
+
api : str
|
|
361
|
+
Search API.
|
|
362
|
+
**kwargs : dict
|
|
363
|
+
Keyword arguments to pass to the request.
|
|
364
|
+
|
|
365
|
+
Returns
|
|
366
|
+
-------
|
|
367
|
+
dict
|
|
368
|
+
Response objects.
|
|
369
|
+
"""
|
|
370
|
+
raise NotImplementedError("Local client does not support search_objects.")
|
|
371
|
+
|
|
352
372
|
##############################
|
|
353
373
|
# Helpers
|
|
354
374
|
##############################
|
digitalhub/context/api.py
CHANGED
|
@@ -3,45 +3,26 @@ from __future__ import annotations
|
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
5
|
from digitalhub.context.builder import context_builder
|
|
6
|
-
from digitalhub.utils.exceptions import ContextError
|
|
7
6
|
|
|
8
7
|
if typing.TYPE_CHECKING:
|
|
9
8
|
from digitalhub.context.context import Context
|
|
10
9
|
from digitalhub.entities.project._base.entity import Project
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
def
|
|
14
|
-
"""
|
|
15
|
-
Check if the given project is in the context.
|
|
16
|
-
|
|
17
|
-
Parameters
|
|
18
|
-
----------
|
|
19
|
-
project : str
|
|
20
|
-
Project name.
|
|
21
|
-
|
|
22
|
-
Returns
|
|
23
|
-
-------
|
|
24
|
-
bool
|
|
25
|
-
True if the project is in the context, False otherwise.
|
|
26
|
-
"""
|
|
27
|
-
if project not in context_builder._instances:
|
|
28
|
-
raise ContextError
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def set_context(project: Project) -> None:
|
|
12
|
+
def build_context(project: Project, overwrite: bool = False) -> None:
|
|
32
13
|
"""
|
|
33
14
|
Wrapper for ContextBuilder.build().
|
|
34
15
|
|
|
35
16
|
Parameters
|
|
36
17
|
----------
|
|
37
18
|
project : Project
|
|
38
|
-
The project object used to
|
|
19
|
+
The project object used to build the context.
|
|
39
20
|
|
|
40
21
|
Returns
|
|
41
22
|
-------
|
|
42
23
|
None
|
|
43
24
|
"""
|
|
44
|
-
context_builder.build(project)
|
|
25
|
+
context_builder.build(project, overwrite)
|
|
45
26
|
|
|
46
27
|
|
|
47
28
|
def get_context(project: str) -> Context:
|
|
@@ -61,22 +42,6 @@ def get_context(project: str) -> Context:
|
|
|
61
42
|
return context_builder.get(project)
|
|
62
43
|
|
|
63
44
|
|
|
64
|
-
def set_context_object(context: Context) -> None:
|
|
65
|
-
"""
|
|
66
|
-
Wrapper for ContextBuilder.set().
|
|
67
|
-
|
|
68
|
-
Parameters
|
|
69
|
-
----------
|
|
70
|
-
context : Context
|
|
71
|
-
The context to set.
|
|
72
|
-
|
|
73
|
-
Returns
|
|
74
|
-
-------
|
|
75
|
-
None
|
|
76
|
-
"""
|
|
77
|
-
context_builder.set(context)
|
|
78
|
-
|
|
79
|
-
|
|
80
45
|
def delete_context(project: str) -> None:
|
|
81
46
|
"""
|
|
82
47
|
Wrapper for ContextBuilder.remove().
|
digitalhub/context/builder.py
CHANGED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
5
|
from digitalhub.context.context import Context
|
|
6
|
+
from digitalhub.utils.exceptions import ContextError
|
|
6
7
|
|
|
7
8
|
if typing.TYPE_CHECKING:
|
|
8
9
|
from digitalhub.entities.project._base.entity import Project
|
|
@@ -19,7 +20,7 @@ class ContextBuilder:
|
|
|
19
20
|
def __init__(self) -> None:
|
|
20
21
|
self._instances: dict[str, Context] = {}
|
|
21
22
|
|
|
22
|
-
def build(self, project_object: Project) -> None:
|
|
23
|
+
def build(self, project_object: Project, overwrite: bool = False) -> None:
|
|
23
24
|
"""
|
|
24
25
|
Add a project as context.
|
|
25
26
|
|
|
@@ -27,12 +28,15 @@ class ContextBuilder:
|
|
|
27
28
|
----------
|
|
28
29
|
project_object : Project
|
|
29
30
|
The project to add.
|
|
31
|
+
overwrite : bool
|
|
32
|
+
If True, the project will be overwritten if it already exists.
|
|
30
33
|
|
|
31
34
|
Returns
|
|
32
35
|
-------
|
|
33
36
|
None
|
|
34
37
|
"""
|
|
35
|
-
|
|
38
|
+
if (project_object.name not in self._instances) or overwrite:
|
|
39
|
+
self._instances[project_object.name] = Context(project_object)
|
|
36
40
|
|
|
37
41
|
def get(self, project: str) -> Context:
|
|
38
42
|
"""
|
|
@@ -53,12 +57,10 @@ class ContextBuilder:
|
|
|
53
57
|
ValueError
|
|
54
58
|
If the project is not in the context.
|
|
55
59
|
"""
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
61
|
-
return ctx
|
|
60
|
+
try:
|
|
61
|
+
return self._instances[project]
|
|
62
|
+
except KeyError:
|
|
63
|
+
raise ContextError(f"Context '{project}' not found. Get or create a project named '{project}'.")
|
|
62
64
|
|
|
63
65
|
def remove(self, project: str) -> None:
|
|
64
66
|
"""
|
|
@@ -75,20 +77,5 @@ class ContextBuilder:
|
|
|
75
77
|
"""
|
|
76
78
|
self._instances.pop(project, None)
|
|
77
79
|
|
|
78
|
-
def set(self, context: Context) -> None:
|
|
79
|
-
"""
|
|
80
|
-
Set the context.
|
|
81
|
-
|
|
82
|
-
Parameters
|
|
83
|
-
----------
|
|
84
|
-
context : Context
|
|
85
|
-
The context to set.
|
|
86
|
-
|
|
87
|
-
Returns
|
|
88
|
-
-------
|
|
89
|
-
None
|
|
90
|
-
"""
|
|
91
|
-
self._instances[context.name] = context
|
|
92
|
-
|
|
93
80
|
|
|
94
81
|
context_builder = ContextBuilder()
|
digitalhub/context/context.py
CHANGED
|
@@ -13,8 +13,6 @@ class Context:
|
|
|
13
13
|
some information about the project, such as the project name,
|
|
14
14
|
a client instance (local or non-local), the local context
|
|
15
15
|
project path and information about client locality.
|
|
16
|
-
It exposes CRUD operations for the entities and act as a layer
|
|
17
|
-
between the project object and its client.
|
|
18
16
|
"""
|
|
19
17
|
|
|
20
18
|
def __init__(self, project: Project) -> None:
|
|
@@ -22,115 +20,45 @@ class Context:
|
|
|
22
20
|
self.client = project._client
|
|
23
21
|
self.local = project._client.is_local()
|
|
24
22
|
self.root = Path(project.spec.context)
|
|
23
|
+
self.root.mkdir(parents=True, exist_ok=True)
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Create an object.
|
|
29
|
-
|
|
30
|
-
Parameters
|
|
31
|
-
----------
|
|
32
|
-
api : str
|
|
33
|
-
Create API.
|
|
34
|
-
obj : dict
|
|
35
|
-
Object to create.
|
|
36
|
-
**kwargs : dict
|
|
37
|
-
Keyword arguments passed to the request.
|
|
38
|
-
|
|
39
|
-
Returns
|
|
40
|
-
-------
|
|
41
|
-
dict
|
|
42
|
-
Response object.
|
|
43
|
-
"""
|
|
44
|
-
return self.client.create_object(api, obj, **kwargs)
|
|
45
|
-
|
|
46
|
-
def read_object(self, api: str, **kwargs) -> dict:
|
|
47
|
-
"""
|
|
48
|
-
Read an object.
|
|
49
|
-
|
|
50
|
-
Parameters
|
|
51
|
-
----------
|
|
52
|
-
api : str
|
|
53
|
-
Read API.
|
|
54
|
-
**kwargs : dict
|
|
55
|
-
Keyword arguments passed to the request.
|
|
56
|
-
|
|
57
|
-
Returns
|
|
58
|
-
-------
|
|
59
|
-
dict
|
|
60
|
-
Response object.
|
|
61
|
-
"""
|
|
62
|
-
return self.client.read_object(api, **kwargs)
|
|
63
|
-
|
|
64
|
-
def update_object(self, api: str, obj: dict, **kwargs) -> dict:
|
|
65
|
-
"""
|
|
66
|
-
Update an object.
|
|
67
|
-
|
|
68
|
-
Parameters
|
|
69
|
-
----------
|
|
70
|
-
api : str
|
|
71
|
-
Update API.
|
|
72
|
-
obj : dict
|
|
73
|
-
Object to update.
|
|
74
|
-
**kwargs : dict
|
|
75
|
-
Keyword arguments passed to the request.
|
|
76
|
-
|
|
77
|
-
Returns
|
|
78
|
-
-------
|
|
79
|
-
dict
|
|
80
|
-
Response object.
|
|
81
|
-
"""
|
|
82
|
-
return self.client.update_object(api, obj, **kwargs)
|
|
25
|
+
self.is_running: bool = False
|
|
26
|
+
self._run_ctx: str = None
|
|
83
27
|
|
|
84
|
-
def
|
|
28
|
+
def set_run(self, run_ctx: str) -> None:
|
|
85
29
|
"""
|
|
86
|
-
|
|
30
|
+
Set run identifier.
|
|
87
31
|
|
|
88
32
|
Parameters
|
|
89
33
|
----------
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
**kwargs : dict
|
|
93
|
-
Keyword arguments passed to the request.
|
|
34
|
+
run_ctx : str
|
|
35
|
+
Run key.
|
|
94
36
|
|
|
95
37
|
Returns
|
|
96
38
|
-------
|
|
97
|
-
|
|
98
|
-
Response object.
|
|
39
|
+
None
|
|
99
40
|
"""
|
|
100
|
-
|
|
41
|
+
self.is_running = True
|
|
42
|
+
self._run_ctx = run_ctx
|
|
101
43
|
|
|
102
|
-
def
|
|
44
|
+
def unset_run(self) -> None:
|
|
103
45
|
"""
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
Parameters
|
|
107
|
-
----------
|
|
108
|
-
api : str
|
|
109
|
-
The api to list the objects with.
|
|
110
|
-
**kwargs : dict
|
|
111
|
-
Keyword arguments passed to the request.
|
|
46
|
+
Unset run identifier.
|
|
112
47
|
|
|
113
48
|
Returns
|
|
114
49
|
-------
|
|
115
|
-
|
|
116
|
-
The list of objects.
|
|
50
|
+
None
|
|
117
51
|
"""
|
|
118
|
-
|
|
52
|
+
self.is_running = False
|
|
53
|
+
self._run_ctx = None
|
|
119
54
|
|
|
120
|
-
def
|
|
55
|
+
def get_run_ctx(self) -> str:
|
|
121
56
|
"""
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Parameters
|
|
125
|
-
----------
|
|
126
|
-
api : str
|
|
127
|
-
The api to list the objects with.
|
|
128
|
-
**kwargs : dict
|
|
129
|
-
Keyword arguments passed to the request.
|
|
57
|
+
Get run identifier.
|
|
130
58
|
|
|
131
59
|
Returns
|
|
132
60
|
-------
|
|
133
|
-
|
|
134
|
-
|
|
61
|
+
str
|
|
62
|
+
Run key.
|
|
135
63
|
"""
|
|
136
|
-
return self.
|
|
64
|
+
return self._run_ctx
|
|
@@ -3,9 +3,10 @@ from __future__ import annotations
|
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
5
|
from digitalhub.context.api import get_context
|
|
6
|
-
from digitalhub.entities._base.api_utils import create_entity_api_ctx, read_entity_api_ctx, update_entity_api_ctx
|
|
7
6
|
from digitalhub.entities._base.entity.entity import Entity
|
|
7
|
+
from digitalhub.entities._operations.processor import processor
|
|
8
8
|
from digitalhub.utils.generic_utils import get_timestamp
|
|
9
|
+
from digitalhub.utils.io_utils import write_yaml
|
|
9
10
|
|
|
10
11
|
if typing.TYPE_CHECKING:
|
|
11
12
|
from digitalhub.context.context import Context
|
|
@@ -26,7 +27,11 @@ class ContextEntity(Entity):
|
|
|
26
27
|
) -> None:
|
|
27
28
|
super().__init__(kind, metadata, spec, status, user)
|
|
28
29
|
self.project = project
|
|
29
|
-
self.
|
|
30
|
+
self.name: str
|
|
31
|
+
self.id: str
|
|
32
|
+
|
|
33
|
+
# Different behaviour for versioned and unversioned
|
|
34
|
+
self._obj_attr.extend(["project", "id", "name"])
|
|
30
35
|
|
|
31
36
|
##############################
|
|
32
37
|
# Save / Refresh / Export
|
|
@@ -46,49 +51,52 @@ class ContextEntity(Entity):
|
|
|
46
51
|
ContextEntity
|
|
47
52
|
Entity saved.
|
|
48
53
|
"""
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return self._update(obj)
|
|
54
|
+
if update:
|
|
55
|
+
return self._update()
|
|
56
|
+
return self._save()
|
|
53
57
|
|
|
54
|
-
def _save(self
|
|
58
|
+
def _save(self) -> ContextEntity:
|
|
55
59
|
"""
|
|
56
60
|
Save entity into backend.
|
|
57
61
|
|
|
58
|
-
Parameters
|
|
59
|
-
----------
|
|
60
|
-
obj : dict
|
|
61
|
-
Object instance as dictionary.
|
|
62
|
-
|
|
63
62
|
Returns
|
|
64
63
|
-------
|
|
65
64
|
ContextEntity
|
|
66
65
|
Entity saved.
|
|
67
66
|
"""
|
|
68
|
-
new_obj =
|
|
67
|
+
new_obj = processor.create_context_entity(_entity=self)
|
|
69
68
|
self._update_attributes(new_obj)
|
|
70
69
|
return self
|
|
71
70
|
|
|
72
|
-
def _update(self
|
|
71
|
+
def _update(self) -> ContextEntity:
|
|
73
72
|
"""
|
|
74
73
|
Update entity in backend.
|
|
75
74
|
|
|
76
|
-
Parameters
|
|
77
|
-
----------
|
|
78
|
-
obj : dict
|
|
79
|
-
Object instance as dictionary.
|
|
80
|
-
|
|
81
75
|
Returns
|
|
82
76
|
-------
|
|
83
77
|
ContextEntity
|
|
84
78
|
Entity updated.
|
|
85
79
|
"""
|
|
86
80
|
if self._context().local:
|
|
87
|
-
self.metadata.updated =
|
|
88
|
-
new_obj =
|
|
81
|
+
self.metadata.updated = self.metadata.updated = get_timestamp()
|
|
82
|
+
new_obj = processor.update_context_entity(self.project, self.ENTITY_TYPE, self.id, self.to_dict())
|
|
89
83
|
self._update_attributes(new_obj)
|
|
90
84
|
return self
|
|
91
85
|
|
|
86
|
+
def export(self) -> str:
|
|
87
|
+
"""
|
|
88
|
+
Export object as a YAML file in the context folder.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
str
|
|
93
|
+
Exported filepath.
|
|
94
|
+
"""
|
|
95
|
+
obj = self.to_dict()
|
|
96
|
+
pth = self._context().root / f"{self.ENTITY_TYPE}s-{self.id}.yaml"
|
|
97
|
+
write_yaml(pth, obj)
|
|
98
|
+
return str(pth)
|
|
99
|
+
|
|
92
100
|
def refresh(self) -> ContextEntity:
|
|
93
101
|
"""
|
|
94
102
|
Refresh object from backend.
|
|
@@ -98,7 +106,7 @@ class ContextEntity(Entity):
|
|
|
98
106
|
ContextEntity
|
|
99
107
|
Entity refreshed.
|
|
100
108
|
"""
|
|
101
|
-
new_obj =
|
|
109
|
+
new_obj = processor.read_context_entity(self.key)
|
|
102
110
|
self._update_attributes(new_obj)
|
|
103
111
|
return self
|
|
104
112
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from pydantic import ValidationError
|
|
4
|
+
|
|
5
|
+
from digitalhub.entities._base.entity.metadata import Metadata, RelationshipValidator
|
|
6
|
+
from digitalhub.utils.exceptions import BuilderError
|
|
4
7
|
from digitalhub.utils.generic_utils import get_timestamp
|
|
5
8
|
|
|
6
9
|
|
|
@@ -41,4 +44,12 @@ def parse_arguments(**kwargs) -> dict:
|
|
|
41
44
|
kwargs["created"] = get_timestamp()
|
|
42
45
|
if "updated" not in kwargs or kwargs["updated"] is None:
|
|
43
46
|
kwargs["updated"] = kwargs["created"]
|
|
47
|
+
if "relationships" in kwargs:
|
|
48
|
+
if not isinstance(kwargs["relationships"], list):
|
|
49
|
+
raise BuilderError("Invalid relationships format. Must be a list of maps.")
|
|
50
|
+
for relationship in kwargs["relationships"]:
|
|
51
|
+
try:
|
|
52
|
+
RelationshipValidator(**relationship)
|
|
53
|
+
except ValidationError as e:
|
|
54
|
+
raise BuilderError(f"Malformed relationship: {e}") from e
|
|
44
55
|
return kwargs
|
|
@@ -29,5 +29,5 @@ def build_spec(spec_cls: Spec, spec_validator: SpecValidator, validate: bool = T
|
|
|
29
29
|
Spec object.
|
|
30
30
|
"""
|
|
31
31
|
if validate:
|
|
32
|
-
kwargs = spec_validator(**kwargs).
|
|
32
|
+
kwargs = spec_validator(**kwargs).to_dict()
|
|
33
33
|
return spec_cls(**kwargs)
|
|
@@ -2,7 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from digitalhub.entities.
|
|
5
|
+
from digitalhub.entities._commons.enums import State
|
|
6
|
+
from digitalhub.utils.exceptions import BuilderError
|
|
6
7
|
|
|
7
8
|
if typing.TYPE_CHECKING:
|
|
8
9
|
from digitalhub.entities._base.entity.status import Status
|
|
@@ -48,5 +49,5 @@ def parse_arguments(**kwargs) -> dict:
|
|
|
48
49
|
kwargs["state"] = State.CREATED.value
|
|
49
50
|
else:
|
|
50
51
|
if kwargs["state"] not in State.__members__:
|
|
51
|
-
raise
|
|
52
|
+
raise BuilderError(f"Invalid state: {state}")
|
|
52
53
|
return kwargs
|
|
@@ -106,7 +106,12 @@ class EntityBuilder:
|
|
|
106
106
|
Spec
|
|
107
107
|
Spec object.
|
|
108
108
|
"""
|
|
109
|
-
return build_spec(
|
|
109
|
+
return build_spec(
|
|
110
|
+
self.ENTITY_SPEC_CLASS,
|
|
111
|
+
self.ENTITY_SPEC_VALIDATOR,
|
|
112
|
+
validate=validate,
|
|
113
|
+
**kwargs,
|
|
114
|
+
)
|
|
110
115
|
|
|
111
116
|
def build_status(self, **kwargs) -> Status:
|
|
112
117
|
"""
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import typing
|
|
4
|
-
from abc import
|
|
4
|
+
from abc import abstractmethod
|
|
5
5
|
|
|
6
6
|
from digitalhub.entities._base._base.entity import Base
|
|
7
|
-
from digitalhub.factory.api import build_entity_from_dict
|
|
8
7
|
|
|
9
8
|
if typing.TYPE_CHECKING:
|
|
10
9
|
from digitalhub.entities._base.entity.metadata import Metadata
|
|
@@ -12,7 +11,7 @@ if typing.TYPE_CHECKING:
|
|
|
12
11
|
from digitalhub.entities._base.entity.status import Status
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
class Entity(Base
|
|
14
|
+
class Entity(Base):
|
|
16
15
|
"""
|
|
17
16
|
Abstract class for entities.
|
|
18
17
|
|
|
@@ -56,7 +55,7 @@ class Entity(Base, metaclass=ABCMeta):
|
|
|
56
55
|
Abstract refresh method.
|
|
57
56
|
"""
|
|
58
57
|
|
|
59
|
-
def _update_attributes(self, obj:
|
|
58
|
+
def _update_attributes(self, obj: Entity) -> None:
|
|
60
59
|
"""
|
|
61
60
|
Update attributes.
|
|
62
61
|
|
|
@@ -69,18 +68,39 @@ class Entity(Base, metaclass=ABCMeta):
|
|
|
69
68
|
-------
|
|
70
69
|
None
|
|
71
70
|
"""
|
|
72
|
-
|
|
73
|
-
self.
|
|
74
|
-
self.
|
|
75
|
-
self.
|
|
76
|
-
self.user = new_obj.user
|
|
71
|
+
self.metadata = obj.metadata
|
|
72
|
+
self.spec = obj.spec
|
|
73
|
+
self.status = obj.status
|
|
74
|
+
self.user = obj.user
|
|
77
75
|
|
|
78
76
|
@abstractmethod
|
|
79
|
-
def export(self
|
|
77
|
+
def export(self) -> str:
|
|
80
78
|
"""
|
|
81
79
|
Abstract export method.
|
|
82
80
|
"""
|
|
83
81
|
|
|
82
|
+
def add_relationship(self, relation: str, source: str, dest: str) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Add relationship to entity metadata.
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
relation : str
|
|
89
|
+
The type of relationship.
|
|
90
|
+
source : str
|
|
91
|
+
The source entity.
|
|
92
|
+
dest : str
|
|
93
|
+
The target entity..
|
|
94
|
+
|
|
95
|
+
Returns
|
|
96
|
+
-------
|
|
97
|
+
None
|
|
98
|
+
"""
|
|
99
|
+
if self.metadata.relationships is None:
|
|
100
|
+
self.metadata.relationships = []
|
|
101
|
+
obj = {"type": relation, "source": source, "dest": dest}
|
|
102
|
+
self.metadata.relationships.append(obj)
|
|
103
|
+
|
|
84
104
|
def to_dict(self) -> dict:
|
|
85
105
|
"""
|
|
86
106
|
Override default to_dict method to add the possibility to exclude
|