digitalhub 0.8.0b0__py3-none-any.whl → 0.8.0b2__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 +62 -94
- digitalhub/client/__init__.py +0 -0
- digitalhub/client/builder.py +105 -0
- digitalhub/client/objects/__init__.py +0 -0
- digitalhub/client/objects/base.py +56 -0
- digitalhub/client/objects/dhcore.py +681 -0
- digitalhub/client/objects/local.py +533 -0
- digitalhub/context/__init__.py +0 -0
- digitalhub/context/builder.py +178 -0
- digitalhub/context/context.py +136 -0
- digitalhub/datastores/__init__.py +0 -0
- digitalhub/datastores/builder.py +134 -0
- digitalhub/datastores/objects/__init__.py +0 -0
- digitalhub/datastores/objects/base.py +85 -0
- digitalhub/datastores/objects/local.py +42 -0
- digitalhub/datastores/objects/remote.py +23 -0
- digitalhub/datastores/objects/s3.py +38 -0
- digitalhub/datastores/objects/sql.py +60 -0
- digitalhub/entities/__init__.py +0 -0
- digitalhub/entities/_base/__init__.py +0 -0
- digitalhub/entities/_base/api.py +346 -0
- digitalhub/entities/_base/base.py +82 -0
- digitalhub/entities/_base/crud.py +610 -0
- digitalhub/entities/_base/entity/__init__.py +0 -0
- digitalhub/entities/_base/entity/base.py +132 -0
- digitalhub/entities/_base/entity/context.py +118 -0
- digitalhub/entities/_base/entity/executable.py +380 -0
- digitalhub/entities/_base/entity/material.py +214 -0
- digitalhub/entities/_base/entity/unversioned.py +87 -0
- digitalhub/entities/_base/entity/versioned.py +94 -0
- digitalhub/entities/_base/metadata.py +59 -0
- digitalhub/entities/_base/spec/__init__.py +0 -0
- digitalhub/entities/_base/spec/base.py +58 -0
- digitalhub/entities/_base/spec/material.py +22 -0
- digitalhub/entities/_base/state.py +31 -0
- digitalhub/entities/_base/status/__init__.py +0 -0
- digitalhub/entities/_base/status/base.py +32 -0
- digitalhub/entities/_base/status/material.py +49 -0
- digitalhub/entities/_builders/__init__.py +0 -0
- digitalhub/entities/_builders/metadata.py +60 -0
- digitalhub/entities/_builders/name.py +31 -0
- digitalhub/entities/_builders/spec.py +43 -0
- digitalhub/entities/_builders/status.py +62 -0
- digitalhub/entities/_builders/uuid.py +33 -0
- digitalhub/entities/artifact/__init__.py +0 -0
- digitalhub/entities/artifact/builder.py +133 -0
- digitalhub/entities/artifact/crud.py +358 -0
- digitalhub/entities/artifact/entity/__init__.py +0 -0
- digitalhub/entities/artifact/entity/_base.py +39 -0
- digitalhub/entities/artifact/entity/artifact.py +9 -0
- digitalhub/entities/artifact/spec.py +39 -0
- digitalhub/entities/artifact/status.py +15 -0
- digitalhub/entities/dataitem/__init__.py +0 -0
- digitalhub/entities/dataitem/builder.py +144 -0
- digitalhub/entities/dataitem/crud.py +395 -0
- digitalhub/entities/dataitem/entity/__init__.py +0 -0
- digitalhub/entities/dataitem/entity/_base.py +75 -0
- digitalhub/entities/dataitem/entity/dataitem.py +9 -0
- digitalhub/entities/dataitem/entity/iceberg.py +7 -0
- digitalhub/entities/dataitem/entity/table.py +125 -0
- digitalhub/entities/dataitem/models.py +62 -0
- digitalhub/entities/dataitem/spec.py +61 -0
- digitalhub/entities/dataitem/status.py +38 -0
- digitalhub/entities/entity_types.py +19 -0
- digitalhub/entities/function/__init__.py +0 -0
- digitalhub/entities/function/builder.py +86 -0
- digitalhub/entities/function/crud.py +305 -0
- digitalhub/entities/function/entity.py +101 -0
- digitalhub/entities/function/models.py +118 -0
- digitalhub/entities/function/spec.py +81 -0
- digitalhub/entities/function/status.py +9 -0
- digitalhub/entities/model/__init__.py +0 -0
- digitalhub/entities/model/builder.py +152 -0
- digitalhub/entities/model/crud.py +358 -0
- digitalhub/entities/model/entity/__init__.py +0 -0
- digitalhub/entities/model/entity/_base.py +34 -0
- digitalhub/entities/model/entity/huggingface.py +9 -0
- digitalhub/entities/model/entity/mlflow.py +90 -0
- digitalhub/entities/model/entity/model.py +9 -0
- digitalhub/entities/model/entity/sklearn.py +9 -0
- digitalhub/entities/model/models.py +26 -0
- digitalhub/entities/model/spec.py +146 -0
- digitalhub/entities/model/status.py +33 -0
- digitalhub/entities/project/__init__.py +0 -0
- digitalhub/entities/project/builder.py +82 -0
- digitalhub/entities/project/crud.py +350 -0
- digitalhub/entities/project/entity.py +2060 -0
- digitalhub/entities/project/spec.py +50 -0
- digitalhub/entities/project/status.py +9 -0
- digitalhub/entities/registries.py +48 -0
- digitalhub/entities/run/__init__.py +0 -0
- digitalhub/entities/run/builder.py +77 -0
- digitalhub/entities/run/crud.py +232 -0
- digitalhub/entities/run/entity.py +461 -0
- digitalhub/entities/run/spec.py +153 -0
- digitalhub/entities/run/status.py +114 -0
- digitalhub/entities/secret/__init__.py +0 -0
- digitalhub/entities/secret/builder.py +93 -0
- digitalhub/entities/secret/crud.py +294 -0
- digitalhub/entities/secret/entity.py +73 -0
- digitalhub/entities/secret/spec.py +35 -0
- digitalhub/entities/secret/status.py +9 -0
- digitalhub/entities/task/__init__.py +0 -0
- digitalhub/entities/task/builder.py +74 -0
- digitalhub/entities/task/crud.py +241 -0
- digitalhub/entities/task/entity.py +135 -0
- digitalhub/entities/task/models.py +199 -0
- digitalhub/entities/task/spec.py +51 -0
- digitalhub/entities/task/status.py +9 -0
- digitalhub/entities/utils.py +184 -0
- digitalhub/entities/workflow/__init__.py +0 -0
- digitalhub/entities/workflow/builder.py +91 -0
- digitalhub/entities/workflow/crud.py +304 -0
- digitalhub/entities/workflow/entity.py +77 -0
- digitalhub/entities/workflow/spec.py +15 -0
- digitalhub/entities/workflow/status.py +9 -0
- digitalhub/readers/__init__.py +0 -0
- digitalhub/readers/builder.py +54 -0
- digitalhub/readers/objects/__init__.py +0 -0
- digitalhub/readers/objects/base.py +70 -0
- digitalhub/readers/objects/pandas.py +207 -0
- digitalhub/readers/registry.py +15 -0
- digitalhub/registry/__init__.py +0 -0
- digitalhub/registry/models.py +87 -0
- digitalhub/registry/registry.py +74 -0
- digitalhub/registry/utils.py +150 -0
- digitalhub/runtimes/__init__.py +0 -0
- digitalhub/runtimes/base.py +164 -0
- digitalhub/runtimes/builder.py +53 -0
- digitalhub/runtimes/kind_registry.py +170 -0
- digitalhub/stores/__init__.py +0 -0
- digitalhub/stores/builder.py +257 -0
- digitalhub/stores/objects/__init__.py +0 -0
- digitalhub/stores/objects/base.py +189 -0
- digitalhub/stores/objects/local.py +230 -0
- digitalhub/stores/objects/remote.py +143 -0
- digitalhub/stores/objects/s3.py +563 -0
- digitalhub/stores/objects/sql.py +328 -0
- digitalhub/utils/__init__.py +0 -0
- digitalhub/utils/data_utils.py +127 -0
- digitalhub/utils/env_utils.py +123 -0
- digitalhub/utils/exceptions.py +55 -0
- digitalhub/utils/file_utils.py +204 -0
- digitalhub/utils/generic_utils.py +207 -0
- digitalhub/utils/git_utils.py +148 -0
- digitalhub/utils/io_utils.py +79 -0
- digitalhub/utils/logger.py +17 -0
- digitalhub/utils/uri_utils.py +56 -0
- {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b2.dist-info}/METADATA +27 -12
- digitalhub-0.8.0b2.dist-info/RECORD +161 -0
- test/test_crud_artifacts.py +1 -1
- test/test_crud_dataitems.py +1 -1
- test/test_crud_functions.py +1 -1
- test/test_crud_runs.py +1 -1
- test/test_crud_tasks.py +1 -1
- digitalhub-0.8.0b0.dist-info/RECORD +0 -14
- {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b2.dist-info}/LICENSE.txt +0 -0
- {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b2.dist-info}/WHEEL +0 -0
- {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
from abc import ABCMeta, abstractmethod
|
|
5
|
+
|
|
6
|
+
from digitalhub.entities._base.base import ModelObj
|
|
7
|
+
|
|
8
|
+
if typing.TYPE_CHECKING:
|
|
9
|
+
from digitalhub.entities._base.metadata import Metadata
|
|
10
|
+
from digitalhub.entities._base.spec.base import Spec
|
|
11
|
+
from digitalhub.entities._base.status.base import Status
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Entity(ModelObj, metaclass=ABCMeta):
|
|
15
|
+
"""
|
|
16
|
+
Abstract class for entities.
|
|
17
|
+
|
|
18
|
+
An entity is a collection of metadata, specification and status
|
|
19
|
+
representing a variety of objects handled by Digitalhub.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
# Entity type
|
|
23
|
+
# Need to be set in subclasses
|
|
24
|
+
ENTITY_TYPE: str
|
|
25
|
+
|
|
26
|
+
# Attributes to render as dict. Need to be expanded in subclasses.
|
|
27
|
+
_obj_attr = ["kind", "metadata", "spec", "status", "user", "key"]
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
kind: str,
|
|
32
|
+
metadata: Metadata,
|
|
33
|
+
spec: Spec,
|
|
34
|
+
status: Status,
|
|
35
|
+
user: str | None = None,
|
|
36
|
+
) -> None:
|
|
37
|
+
self.kind = kind
|
|
38
|
+
self.metadata = metadata
|
|
39
|
+
self.spec = spec
|
|
40
|
+
self.status = status
|
|
41
|
+
self.user = user
|
|
42
|
+
|
|
43
|
+
# Need to be set in subclasses
|
|
44
|
+
self.key: str
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def save(self, update: bool = False) -> Entity:
|
|
48
|
+
"""
|
|
49
|
+
Abstract save method.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def refresh(self) -> Entity:
|
|
54
|
+
"""
|
|
55
|
+
Abstract refresh method.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def _update_attributes(self, obj: dict) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Update attributes.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
obj : dict
|
|
65
|
+
Mapping representation of object.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
None
|
|
70
|
+
"""
|
|
71
|
+
new_obj = self.from_dict(obj)
|
|
72
|
+
self.metadata = new_obj.metadata
|
|
73
|
+
self.spec = new_obj.spec
|
|
74
|
+
self.status = new_obj.status
|
|
75
|
+
self.user = new_obj.user
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def export(self, filename: str | None = None) -> str:
|
|
79
|
+
"""
|
|
80
|
+
Abstract export method.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
def to_dict(self) -> dict:
|
|
84
|
+
"""
|
|
85
|
+
Override default to_dict method to add the possibility to exclude
|
|
86
|
+
some attributes. This requires to set a list of _obj_attr
|
|
87
|
+
attributes in the subclass.
|
|
88
|
+
|
|
89
|
+
Returns
|
|
90
|
+
-------
|
|
91
|
+
dict
|
|
92
|
+
A dictionary containing the attributes of the entity instance.
|
|
93
|
+
"""
|
|
94
|
+
return {k: v for k, v in super().to_dict().items() if k in self._obj_attr}
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def from_dict(cls, obj: dict, validate: bool = True) -> Entity:
|
|
98
|
+
"""
|
|
99
|
+
Create a new object from dictionary.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
obj : dict
|
|
104
|
+
Dictionary to create object from.
|
|
105
|
+
validate : bool
|
|
106
|
+
Flag to indicate if arguments validation against a pydantic schema must be ignored.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
Self
|
|
111
|
+
Self instance.
|
|
112
|
+
"""
|
|
113
|
+
parsed_dict = cls._parse_dict(obj, validate=validate)
|
|
114
|
+
return cls(**parsed_dict)
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
@abstractmethod
|
|
118
|
+
def _parse_dict(obj: dict, validate: bool = True) -> dict:
|
|
119
|
+
"""
|
|
120
|
+
Abstract method to parse dictionary.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
def __repr__(self) -> str:
|
|
124
|
+
"""
|
|
125
|
+
Return string representation of the entity object.
|
|
126
|
+
|
|
127
|
+
Returns
|
|
128
|
+
-------
|
|
129
|
+
str
|
|
130
|
+
A string representing the entity instance.
|
|
131
|
+
"""
|
|
132
|
+
return str(self.to_dict())
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from digitalhub.context.builder import get_context
|
|
6
|
+
from digitalhub.entities._base.crud import create_entity_api_ctx, read_entity_api_ctx, update_entity_api_ctx
|
|
7
|
+
from digitalhub.entities._base.entity.base import Entity
|
|
8
|
+
from digitalhub.utils.generic_utils import get_timestamp
|
|
9
|
+
|
|
10
|
+
if typing.TYPE_CHECKING:
|
|
11
|
+
from digitalhub.context.context import Context
|
|
12
|
+
from digitalhub.entities._base.metadata import Metadata
|
|
13
|
+
from digitalhub.entities._base.spec.base import Spec
|
|
14
|
+
from digitalhub.entities._base.status.base import Status
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ContextEntity(Entity):
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
project: str,
|
|
21
|
+
kind: str,
|
|
22
|
+
metadata: Metadata,
|
|
23
|
+
spec: Spec,
|
|
24
|
+
status: Status,
|
|
25
|
+
user: str | None = None,
|
|
26
|
+
) -> None:
|
|
27
|
+
super().__init__(kind, metadata, spec, status, user)
|
|
28
|
+
self.project = project
|
|
29
|
+
self._obj_attr.extend(["project"])
|
|
30
|
+
|
|
31
|
+
##############################
|
|
32
|
+
# Save / Refresh / Export
|
|
33
|
+
##############################
|
|
34
|
+
|
|
35
|
+
def save(self, update: bool = False) -> ContextEntity:
|
|
36
|
+
"""
|
|
37
|
+
Save or update the entity into the backend.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
update : bool
|
|
42
|
+
Flag to indicate update.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
ContextEntity
|
|
47
|
+
Entity saved.
|
|
48
|
+
"""
|
|
49
|
+
obj = self.to_dict()
|
|
50
|
+
if not update:
|
|
51
|
+
return self._save(obj)
|
|
52
|
+
return self._update(obj)
|
|
53
|
+
|
|
54
|
+
def _save(self, obj: dict) -> ContextEntity:
|
|
55
|
+
"""
|
|
56
|
+
Save entity into backend.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
obj : dict
|
|
61
|
+
Object instance as dictionary.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
ContextEntity
|
|
66
|
+
Entity saved.
|
|
67
|
+
"""
|
|
68
|
+
new_obj = create_entity_api_ctx(self.project, self.ENTITY_TYPE, obj)
|
|
69
|
+
self._update_attributes(new_obj)
|
|
70
|
+
return self
|
|
71
|
+
|
|
72
|
+
def _update(self, obj: dict) -> ContextEntity:
|
|
73
|
+
"""
|
|
74
|
+
Update entity in backend.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
obj : dict
|
|
79
|
+
Object instance as dictionary.
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
ContextEntity
|
|
84
|
+
Entity updated.
|
|
85
|
+
"""
|
|
86
|
+
if self._context().local:
|
|
87
|
+
self.metadata.updated = obj["metadata"]["updated"] = get_timestamp()
|
|
88
|
+
new_obj = update_entity_api_ctx(self.project, self.ENTITY_TYPE, self.id, obj)
|
|
89
|
+
self._update_attributes(new_obj)
|
|
90
|
+
return self
|
|
91
|
+
|
|
92
|
+
def refresh(self) -> ContextEntity:
|
|
93
|
+
"""
|
|
94
|
+
Refresh object from backend.
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
ContextEntity
|
|
99
|
+
Entity refreshed.
|
|
100
|
+
"""
|
|
101
|
+
new_obj = read_entity_api_ctx(self.key)
|
|
102
|
+
self._update_attributes(new_obj)
|
|
103
|
+
return self
|
|
104
|
+
|
|
105
|
+
##############################
|
|
106
|
+
# Context
|
|
107
|
+
##############################
|
|
108
|
+
|
|
109
|
+
def _context(self) -> Context:
|
|
110
|
+
"""
|
|
111
|
+
Get context.
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
Context
|
|
116
|
+
Context object.
|
|
117
|
+
"""
|
|
118
|
+
return get_context(self.project)
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from digitalhub.entities._base.crud import list_entity_api_ctx
|
|
6
|
+
from digitalhub.entities._base.entity.versioned import VersionedEntity
|
|
7
|
+
from digitalhub.entities.entity_types import EntityTypes
|
|
8
|
+
from digitalhub.entities.run.crud import delete_run, get_run, list_runs
|
|
9
|
+
from digitalhub.entities.task.crud import delete_task, task_from_dict, task_from_parameters
|
|
10
|
+
from digitalhub.utils.exceptions import EntityAlreadyExistsError, EntityError
|
|
11
|
+
|
|
12
|
+
if typing.TYPE_CHECKING:
|
|
13
|
+
from digitalhub.entities._base.metadata import Metadata
|
|
14
|
+
from digitalhub.entities._base.spec.base import Spec
|
|
15
|
+
from digitalhub.entities._base.status.base import Status
|
|
16
|
+
from digitalhub.entities.run.entity import Run
|
|
17
|
+
from digitalhub.entities.task.entity import Task
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ExecutableEntity(VersionedEntity):
|
|
21
|
+
"""
|
|
22
|
+
A class representing an entity that can be executed.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
project: str,
|
|
28
|
+
name: str,
|
|
29
|
+
uuid: str,
|
|
30
|
+
kind: str,
|
|
31
|
+
metadata: Metadata,
|
|
32
|
+
spec: Spec,
|
|
33
|
+
status: Status,
|
|
34
|
+
user: str | None = None,
|
|
35
|
+
) -> None:
|
|
36
|
+
super().__init__(project, name, uuid, kind, metadata, spec, status, user)
|
|
37
|
+
|
|
38
|
+
# Initialize tasks
|
|
39
|
+
self._tasks: dict[str, Task] = {}
|
|
40
|
+
|
|
41
|
+
##############################
|
|
42
|
+
# Helpers
|
|
43
|
+
##############################
|
|
44
|
+
|
|
45
|
+
def _get_executable_string(self) -> str:
|
|
46
|
+
"""
|
|
47
|
+
Get executable string.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
str
|
|
52
|
+
Executable string.
|
|
53
|
+
"""
|
|
54
|
+
return f"{self.kind}://{self.project}/{self.name}:{self.id}"
|
|
55
|
+
|
|
56
|
+
##############################
|
|
57
|
+
# Tasks
|
|
58
|
+
##############################
|
|
59
|
+
|
|
60
|
+
def _get_or_create_task(self, kind: str, **kwargs) -> Task:
|
|
61
|
+
"""
|
|
62
|
+
Get or create task.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
kind : str
|
|
67
|
+
Kind the object.
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
Task
|
|
72
|
+
Task.
|
|
73
|
+
"""
|
|
74
|
+
if self._tasks.get(kind) is None:
|
|
75
|
+
return self.new_task(kind)
|
|
76
|
+
return self._tasks[kind]
|
|
77
|
+
|
|
78
|
+
def import_tasks(self, tasks: list[dict]) -> None:
|
|
79
|
+
"""
|
|
80
|
+
Import tasks from yaml.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
tasks : list[dict]
|
|
85
|
+
List of tasks to import.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
None
|
|
90
|
+
"""
|
|
91
|
+
# Loop over tasks list, in the case where the function
|
|
92
|
+
# is imported from local file.
|
|
93
|
+
for task in tasks:
|
|
94
|
+
# If task is not a dictionary, skip it
|
|
95
|
+
if not isinstance(task, dict):
|
|
96
|
+
continue
|
|
97
|
+
|
|
98
|
+
# Create a new object from dictionary.
|
|
99
|
+
# the form in which tasks are stored in function
|
|
100
|
+
# status
|
|
101
|
+
task_obj = task_from_dict(task)
|
|
102
|
+
|
|
103
|
+
# Try to save it in backend to been able to use
|
|
104
|
+
# it for launching runs. In fact, tasks must be
|
|
105
|
+
# persisted in backend to be able to launch runs.
|
|
106
|
+
# Ignore if task already exists
|
|
107
|
+
try:
|
|
108
|
+
task_obj.save()
|
|
109
|
+
except EntityAlreadyExistsError:
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
# Set task if function is the same. Overwrite
|
|
113
|
+
# status task dict with the new task object
|
|
114
|
+
if task_obj.spec.function == self._get_executable_string():
|
|
115
|
+
self._tasks[task_obj.kind] = task_obj
|
|
116
|
+
|
|
117
|
+
def new_task(self, task_kind: str, **kwargs) -> Task:
|
|
118
|
+
"""
|
|
119
|
+
Create new task. If the task already exists, update it.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
task_kind : str
|
|
124
|
+
Kind the object.
|
|
125
|
+
**kwargs : dict
|
|
126
|
+
Keyword arguments.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
Task
|
|
131
|
+
New task.
|
|
132
|
+
"""
|
|
133
|
+
self._raise_if_exists(task_kind)
|
|
134
|
+
|
|
135
|
+
if kwargs is None:
|
|
136
|
+
kwargs = {}
|
|
137
|
+
|
|
138
|
+
# Override kwargs
|
|
139
|
+
kwargs["project"] = self.project
|
|
140
|
+
kwargs["function"] = self._get_executable_string()
|
|
141
|
+
kwargs["kind"] = task_kind
|
|
142
|
+
|
|
143
|
+
# Create object instance
|
|
144
|
+
task = task_from_parameters(**kwargs)
|
|
145
|
+
task.save()
|
|
146
|
+
|
|
147
|
+
self._tasks[task_kind] = task
|
|
148
|
+
return task
|
|
149
|
+
|
|
150
|
+
def update_task(self, kind: str, **kwargs) -> Task:
|
|
151
|
+
"""
|
|
152
|
+
Update task.
|
|
153
|
+
|
|
154
|
+
Parameters
|
|
155
|
+
----------
|
|
156
|
+
kind : str
|
|
157
|
+
Kind the object.
|
|
158
|
+
**kwargs : dict
|
|
159
|
+
Keyword arguments.
|
|
160
|
+
|
|
161
|
+
Returns
|
|
162
|
+
-------
|
|
163
|
+
Task
|
|
164
|
+
Task.
|
|
165
|
+
"""
|
|
166
|
+
self._raise_if_not_exists(kind)
|
|
167
|
+
|
|
168
|
+
if kwargs is None:
|
|
169
|
+
kwargs = {}
|
|
170
|
+
|
|
171
|
+
# Update kwargs
|
|
172
|
+
kwargs["project"] = self.project
|
|
173
|
+
kwargs["kind"] = kind
|
|
174
|
+
kwargs["function"] = self._get_executable_string()
|
|
175
|
+
kwargs["uuid"] = self._tasks[kind].id
|
|
176
|
+
|
|
177
|
+
# Update task
|
|
178
|
+
task = task_from_parameters(**kwargs)
|
|
179
|
+
task.save(update=True)
|
|
180
|
+
self._tasks[kind] = task
|
|
181
|
+
return task
|
|
182
|
+
|
|
183
|
+
def get_task(self, kind: str) -> Task:
|
|
184
|
+
"""
|
|
185
|
+
Get task.
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
kind : str
|
|
190
|
+
Kind the object.
|
|
191
|
+
|
|
192
|
+
Returns
|
|
193
|
+
-------
|
|
194
|
+
Task
|
|
195
|
+
Task.
|
|
196
|
+
|
|
197
|
+
Raises
|
|
198
|
+
------
|
|
199
|
+
EntityError
|
|
200
|
+
If task is not created.
|
|
201
|
+
"""
|
|
202
|
+
self._raise_if_not_exists(kind)
|
|
203
|
+
return self._tasks[kind]
|
|
204
|
+
|
|
205
|
+
def delete_task(self, kind: str, cascade: bool = True) -> dict:
|
|
206
|
+
"""
|
|
207
|
+
Delete task.
|
|
208
|
+
|
|
209
|
+
Parameters
|
|
210
|
+
----------
|
|
211
|
+
kind : str
|
|
212
|
+
Kind the object.
|
|
213
|
+
cascade : bool
|
|
214
|
+
Flag to determine if cascade deletion must be performed.
|
|
215
|
+
|
|
216
|
+
Returns
|
|
217
|
+
-------
|
|
218
|
+
dict
|
|
219
|
+
Response from backend.
|
|
220
|
+
"""
|
|
221
|
+
resp = delete_task(self._tasks[kind].key, cascade=cascade)
|
|
222
|
+
self._tasks.pop(kind, None)
|
|
223
|
+
return resp
|
|
224
|
+
|
|
225
|
+
def _check_task_in_backend(self, kind: str) -> bool:
|
|
226
|
+
"""
|
|
227
|
+
Check if task exists in backend.
|
|
228
|
+
|
|
229
|
+
Parameters
|
|
230
|
+
----------
|
|
231
|
+
kind : str
|
|
232
|
+
Kind the object.
|
|
233
|
+
|
|
234
|
+
Returns
|
|
235
|
+
-------
|
|
236
|
+
bool
|
|
237
|
+
Flag to determine if task exists in backend.
|
|
238
|
+
"""
|
|
239
|
+
# List tasks from backend filtered by function and kind
|
|
240
|
+
params = {"function": self._get_executable_string(), "kind": kind}
|
|
241
|
+
resp = list_entity_api_ctx(self.project, EntityTypes.TASK.value, params=params)
|
|
242
|
+
if not resp:
|
|
243
|
+
return False
|
|
244
|
+
return True
|
|
245
|
+
|
|
246
|
+
def _raise_if_exists(self, kind: str) -> None:
|
|
247
|
+
"""
|
|
248
|
+
Raise error if task is created.
|
|
249
|
+
|
|
250
|
+
Parameters
|
|
251
|
+
----------
|
|
252
|
+
kind : str
|
|
253
|
+
Kind the object.
|
|
254
|
+
|
|
255
|
+
Returns
|
|
256
|
+
-------
|
|
257
|
+
None
|
|
258
|
+
|
|
259
|
+
Raises
|
|
260
|
+
------
|
|
261
|
+
EntityError
|
|
262
|
+
If task already exists.
|
|
263
|
+
"""
|
|
264
|
+
if self._check_task_in_backend(kind):
|
|
265
|
+
raise EntityError(f"Task '{kind}' already exists.")
|
|
266
|
+
|
|
267
|
+
def _raise_if_not_exists(self, kind: str) -> None:
|
|
268
|
+
"""
|
|
269
|
+
Raise error if task is not created.
|
|
270
|
+
|
|
271
|
+
Parameters
|
|
272
|
+
----------
|
|
273
|
+
kind : str
|
|
274
|
+
Kind the object.
|
|
275
|
+
|
|
276
|
+
Returns
|
|
277
|
+
-------
|
|
278
|
+
None
|
|
279
|
+
|
|
280
|
+
Raises
|
|
281
|
+
------
|
|
282
|
+
EntityError
|
|
283
|
+
If task does not exist.
|
|
284
|
+
"""
|
|
285
|
+
if self._tasks.get(kind) is None:
|
|
286
|
+
raise EntityError(f"Task '{kind}' does not exist.")
|
|
287
|
+
|
|
288
|
+
##############################
|
|
289
|
+
# Runs
|
|
290
|
+
##############################
|
|
291
|
+
|
|
292
|
+
def get_run(
|
|
293
|
+
self,
|
|
294
|
+
identifier: str,
|
|
295
|
+
**kwargs,
|
|
296
|
+
) -> Run:
|
|
297
|
+
"""
|
|
298
|
+
Get object from backend.
|
|
299
|
+
|
|
300
|
+
Parameters
|
|
301
|
+
----------
|
|
302
|
+
identifier : str
|
|
303
|
+
Entity key (store://...) or entity ID.
|
|
304
|
+
**kwargs : dict
|
|
305
|
+
Parameters to pass to the API call.
|
|
306
|
+
|
|
307
|
+
Returns
|
|
308
|
+
-------
|
|
309
|
+
Run
|
|
310
|
+
Object instance.
|
|
311
|
+
|
|
312
|
+
Examples
|
|
313
|
+
--------
|
|
314
|
+
Using entity key:
|
|
315
|
+
>>> obj = executable.get_run("store://my-secret-key")
|
|
316
|
+
|
|
317
|
+
Using entity ID:
|
|
318
|
+
>>> obj = executable.get_run("123")
|
|
319
|
+
"""
|
|
320
|
+
obj = get_run(
|
|
321
|
+
identifier=identifier,
|
|
322
|
+
project=self.project,
|
|
323
|
+
**kwargs,
|
|
324
|
+
)
|
|
325
|
+
self.refresh()
|
|
326
|
+
return obj
|
|
327
|
+
|
|
328
|
+
def list_runs(self, **kwargs) -> list[Run]:
|
|
329
|
+
"""
|
|
330
|
+
List all runs from backend.
|
|
331
|
+
|
|
332
|
+
Parameters
|
|
333
|
+
----------
|
|
334
|
+
**kwargs : dict
|
|
335
|
+
Parameters to pass to the API call.
|
|
336
|
+
|
|
337
|
+
Returns
|
|
338
|
+
-------
|
|
339
|
+
list[Run]
|
|
340
|
+
List of object instances.
|
|
341
|
+
|
|
342
|
+
Examples
|
|
343
|
+
--------
|
|
344
|
+
>>> objs = executable.list_runs()
|
|
345
|
+
"""
|
|
346
|
+
if kwargs is None:
|
|
347
|
+
kwargs = {}
|
|
348
|
+
kwargs["params"] = {"function": self._get_executable_string()}
|
|
349
|
+
return list_runs(self.project, **kwargs)
|
|
350
|
+
|
|
351
|
+
def delete_run(
|
|
352
|
+
self,
|
|
353
|
+
identifier: str,
|
|
354
|
+
**kwargs,
|
|
355
|
+
) -> None:
|
|
356
|
+
"""
|
|
357
|
+
Delete run from backend.
|
|
358
|
+
|
|
359
|
+
Parameters
|
|
360
|
+
----------
|
|
361
|
+
identifier : str
|
|
362
|
+
Entity key (store://...) or entity ID.
|
|
363
|
+
**kwargs : dict
|
|
364
|
+
Parameters to pass to the API call.
|
|
365
|
+
|
|
366
|
+
Returns
|
|
367
|
+
-------
|
|
368
|
+
dict
|
|
369
|
+
Response from backend.
|
|
370
|
+
|
|
371
|
+
Examples
|
|
372
|
+
--------
|
|
373
|
+
>>> executable.delete_run("store://my-run-key")
|
|
374
|
+
|
|
375
|
+
"""
|
|
376
|
+
delete_run(
|
|
377
|
+
identifier=identifier,
|
|
378
|
+
project=self.project,
|
|
379
|
+
**kwargs,
|
|
380
|
+
)
|