digitalhub-runtime-python 0.5.0__tar.gz → 0.5.0b5__tar.gz
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.
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/PKG-INFO +1 -1
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/__init__.py +0 -2
- digitalhub_runtime_python-0.5.0b5/digitalhub_runtime_python/entities/functions/metadata.py +9 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/functions/spec.py +0 -5
- digitalhub_runtime_python-0.5.0b5/digitalhub_runtime_python/entities/runs/metadata.py +9 -0
- digitalhub_runtime_python-0.5.0b5/digitalhub_runtime_python/entities/runs/spec.py +53 -0
- digitalhub_runtime_python-0.5.0b5/digitalhub_runtime_python/entities/tasks/metadata.py +15 -0
- digitalhub_runtime_python-0.5.0b5/digitalhub_runtime_python/entities/tasks/spec.py +103 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/runtimes/runtime.py +52 -50
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/utils/configuration.py +18 -47
- digitalhub_runtime_python-0.5.0b5/digitalhub_runtime_python/utils/functions.py +24 -0
- digitalhub_runtime_python-0.5.0b5/digitalhub_runtime_python/utils/inputs.py +153 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/utils/outputs.py +19 -34
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python.egg-info/PKG-INFO +1 -1
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python.egg-info/SOURCES.txt +4 -1
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/pyproject.toml +2 -2
- digitalhub_runtime_python-0.5.0/digitalhub_runtime_python/entities/runs/spec.py +0 -81
- digitalhub_runtime_python-0.5.0/digitalhub_runtime_python/entities/tasks/spec.py +0 -87
- digitalhub_runtime_python-0.5.0/digitalhub_runtime_python/runtimes/kind_registry.py +0 -15
- digitalhub_runtime_python-0.5.0/digitalhub_runtime_python/utils/inputs.py +0 -149
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/LICENSE.txt +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/README.md +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/__init__.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/functions/__init__.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/functions/status.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/runs/__init__.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/runs/status.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/tasks/__init__.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/tasks/models.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/entities/tasks/status.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/runtimes/__init__.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python/utils/utils.py +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python.egg-info/dependency_links.txt +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python.egg-info/requires.txt +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/digitalhub_runtime_python.egg-info/top_level.txt +0 -0
- {digitalhub_runtime_python-0.5.0 → digitalhub_runtime_python-0.5.0b5}/setup.cfg +0 -0
|
@@ -9,8 +9,6 @@ root = "digitalhub_runtime_python"
|
|
|
9
9
|
runtime_info = {
|
|
10
10
|
"module": f"{root}.runtimes.runtime",
|
|
11
11
|
"class_name": "RuntimePython",
|
|
12
|
-
"kind_registry_module": f"{root}.runtimes.kind_registry",
|
|
13
|
-
"kind_registry_class_name": "kind_registry",
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
root_ent = f"{root}.entities"
|
|
@@ -21,7 +21,6 @@ class FunctionSpecPython(FunctionSpec):
|
|
|
21
21
|
source: dict,
|
|
22
22
|
image: str | None = None,
|
|
23
23
|
base_image: str | None = None,
|
|
24
|
-
python_version: str | None = None,
|
|
25
24
|
requirements: list | None = None,
|
|
26
25
|
) -> None:
|
|
27
26
|
"""
|
|
@@ -31,7 +30,6 @@ class FunctionSpecPython(FunctionSpec):
|
|
|
31
30
|
|
|
32
31
|
self.image = image
|
|
33
32
|
self.base_image = base_image
|
|
34
|
-
self.python_version = python_version
|
|
35
33
|
self.requirements = requirements
|
|
36
34
|
|
|
37
35
|
source = self._source_check(source)
|
|
@@ -137,8 +135,5 @@ class FunctionParamsPython(FunctionParams):
|
|
|
137
135
|
base_image: str = None
|
|
138
136
|
"Base image"
|
|
139
137
|
|
|
140
|
-
python_version: str = None
|
|
141
|
-
"Python version"
|
|
142
|
-
|
|
143
138
|
requirements: list = None
|
|
144
139
|
"Requirements list, as used by the runtime"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from digitalhub_ml.entities.runs.spec import RunParamsMl, RunSpecMl
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RunSpecPython(RunSpecMl):
|
|
7
|
+
"""Run Python specification."""
|
|
8
|
+
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
task: str,
|
|
12
|
+
inputs: dict | None = None,
|
|
13
|
+
outputs: dict | None = None,
|
|
14
|
+
parameters: dict | None = None,
|
|
15
|
+
values: list | None = None,
|
|
16
|
+
local_execution: bool = False,
|
|
17
|
+
**kwargs,
|
|
18
|
+
) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Constructor.
|
|
21
|
+
"""
|
|
22
|
+
super().__init__(task, inputs, outputs, parameters, values, local_execution)
|
|
23
|
+
|
|
24
|
+
# Set function and task parameters
|
|
25
|
+
self._any_setter(**kwargs)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RunParamsPython(RunParamsMl):
|
|
29
|
+
"""Run Python parameters."""
|
|
30
|
+
|
|
31
|
+
# Function parameters
|
|
32
|
+
source: dict = None
|
|
33
|
+
image: str = None
|
|
34
|
+
base_image: str = None
|
|
35
|
+
requirements: list = None
|
|
36
|
+
|
|
37
|
+
# Task parameters
|
|
38
|
+
function: str = None
|
|
39
|
+
node_selector: list[dict] = None
|
|
40
|
+
volumes: list[dict] = None
|
|
41
|
+
resources: list[dict] = None
|
|
42
|
+
affinity: dict = None
|
|
43
|
+
tolerations: list[dict] = None
|
|
44
|
+
env: list[dict] = None
|
|
45
|
+
secrets: list[str] = None
|
|
46
|
+
backoff_limit: int = None
|
|
47
|
+
schedule: str = None
|
|
48
|
+
replicas: int = None
|
|
49
|
+
|
|
50
|
+
# Task build
|
|
51
|
+
context_refs: list[dict] = None
|
|
52
|
+
context_sources: list[dict] = None
|
|
53
|
+
instructions: list[str] = None
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from digitalhub_core.entities.tasks.metadata import TaskMetadata
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TaskMetadataJob(TaskMetadata):
|
|
7
|
+
"""
|
|
8
|
+
Task Job metadata.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TaskMetadataBuild(TaskMetadata):
|
|
13
|
+
"""
|
|
14
|
+
Task Build metadata.
|
|
15
|
+
"""
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Task Python specification module.
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from digitalhub_core.entities.tasks.models import K8s
|
|
7
|
+
from digitalhub_core.entities.tasks.spec import TaskParams, TaskSpec
|
|
8
|
+
from digitalhub_runtime_python.entities.tasks.models import ContextRef, ContextSource
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TaskSpecPythonBase(TaskSpec):
|
|
12
|
+
"""Task Python specification for Kubernetes."""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
function: str,
|
|
17
|
+
k8s: dict | None = None,
|
|
18
|
+
) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Constructor.
|
|
21
|
+
"""
|
|
22
|
+
super().__init__(function)
|
|
23
|
+
if k8s is None:
|
|
24
|
+
k8s = {}
|
|
25
|
+
k8s = K8s(**k8s).dict(by_alias=True)
|
|
26
|
+
self.node_selector = k8s.get("node_selector")
|
|
27
|
+
self.volumes = k8s.get("volumes")
|
|
28
|
+
self.resources = k8s.get("resources")
|
|
29
|
+
self.affinity = k8s.get("affinity")
|
|
30
|
+
self.tolerations = k8s.get("tolerations")
|
|
31
|
+
self.envs = k8s.get("envs")
|
|
32
|
+
self.secrets = k8s.get("secrets")
|
|
33
|
+
self.backoff_limit = k8s.get("backoff_limit")
|
|
34
|
+
self.schedule = k8s.get("schedule")
|
|
35
|
+
self.replicas = k8s.get("replicas")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TaskSpecJob(TaskSpecPythonBase):
|
|
39
|
+
"""Task Job specification."""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
function: str,
|
|
44
|
+
k8s: dict | None = None,
|
|
45
|
+
) -> None:
|
|
46
|
+
"""
|
|
47
|
+
Constructor.
|
|
48
|
+
"""
|
|
49
|
+
super().__init__(function, k8s)
|
|
50
|
+
|
|
51
|
+
k8s = k8s if k8s is not None else {}
|
|
52
|
+
|
|
53
|
+
self.backoff_limit = k8s.get("backoff_limit")
|
|
54
|
+
self.schedule = k8s.get("schedule")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class TaskParamsJob(TaskParams):
|
|
58
|
+
"""
|
|
59
|
+
TaskParamsJob model.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
k8s: K8s = None
|
|
63
|
+
"""Kubernetes resources."""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class TaskSpecBuild(TaskSpecPythonBase):
|
|
67
|
+
"""Task Build specification."""
|
|
68
|
+
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
function: str,
|
|
72
|
+
k8s: dict | None = None,
|
|
73
|
+
context_refs: list | None = None,
|
|
74
|
+
context_sources: list | None = None,
|
|
75
|
+
instructions: list | None = None,
|
|
76
|
+
) -> None:
|
|
77
|
+
"""
|
|
78
|
+
Constructor.
|
|
79
|
+
"""
|
|
80
|
+
super().__init__(function, k8s)
|
|
81
|
+
|
|
82
|
+
k8s = k8s if k8s is not None else {}
|
|
83
|
+
self.context_refs = context_refs
|
|
84
|
+
self.context_sources = context_sources
|
|
85
|
+
self.instructions = instructions
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class TaskParamsBuild(TaskParams):
|
|
89
|
+
"""
|
|
90
|
+
TaskParamsBuild model.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
k8s: K8s = None
|
|
94
|
+
"""Kubernetes resources."""
|
|
95
|
+
|
|
96
|
+
context_refs: list[ContextRef] = None
|
|
97
|
+
"""Context references."""
|
|
98
|
+
|
|
99
|
+
context_sources: list[ContextSource] = None
|
|
100
|
+
"""Context sources."""
|
|
101
|
+
|
|
102
|
+
instructions: list[str] = None
|
|
103
|
+
"""Build instructions."""
|
|
@@ -3,18 +3,15 @@ Runtime class for running Python functions.
|
|
|
3
3
|
"""
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
from pathlib import Path
|
|
7
7
|
from typing import Callable
|
|
8
8
|
|
|
9
|
-
from digitalhub_core.context.builder import get_context
|
|
10
9
|
from digitalhub_core.runtimes.base import Runtime
|
|
11
10
|
from digitalhub_core.utils.logger import LOGGER
|
|
12
11
|
from digitalhub_runtime_python.utils.configuration import get_function_from_source
|
|
13
|
-
from digitalhub_runtime_python.utils.
|
|
14
|
-
from digitalhub_runtime_python.utils.
|
|
15
|
-
|
|
16
|
-
if typing.TYPE_CHECKING:
|
|
17
|
-
from digitalhub_core.runtimes.kind_registry import KindRegistry
|
|
12
|
+
from digitalhub_runtime_python.utils.functions import run_python
|
|
13
|
+
from digitalhub_runtime_python.utils.inputs import get_inputs_parameters
|
|
14
|
+
from digitalhub_runtime_python.utils.outputs import build_status
|
|
18
15
|
|
|
19
16
|
|
|
20
17
|
class RuntimePython(Runtime):
|
|
@@ -22,17 +19,15 @@ class RuntimePython(Runtime):
|
|
|
22
19
|
Runtime Python class.
|
|
23
20
|
"""
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
allowed_actions = ["job", "nuclio"]
|
|
23
|
+
|
|
24
|
+
def __init__(self) -> None:
|
|
26
25
|
"""
|
|
27
26
|
Constructor.
|
|
28
27
|
"""
|
|
29
|
-
super().__init__(
|
|
30
|
-
|
|
31
|
-
self.
|
|
32
|
-
self.tmp_dir = ctx.tmp_dir
|
|
33
|
-
|
|
34
|
-
self.root.mkdir(parents=True, exist_ok=True)
|
|
35
|
-
self.tmp_dir.mkdir(parents=True, exist_ok=True)
|
|
28
|
+
super().__init__()
|
|
29
|
+
self.root_path = Path("digitalhub_runtime_python")
|
|
30
|
+
self.tmp_path = self.root_path / "temp"
|
|
36
31
|
|
|
37
32
|
def build(self, function: dict, task: dict, run: dict) -> dict:
|
|
38
33
|
"""
|
|
@@ -68,27 +63,28 @@ class RuntimePython(Runtime):
|
|
|
68
63
|
Status of the executed run.
|
|
69
64
|
"""
|
|
70
65
|
LOGGER.info("Validating task.")
|
|
71
|
-
self._validate_task(run)
|
|
66
|
+
action = self._validate_task(run)
|
|
67
|
+
executable = self._get_executable(action)
|
|
72
68
|
|
|
73
69
|
LOGGER.info("Starting task.")
|
|
74
70
|
spec = run.get("spec")
|
|
75
71
|
project = run.get("project")
|
|
76
72
|
|
|
77
|
-
LOGGER.info("
|
|
78
|
-
|
|
73
|
+
LOGGER.info("Collecting inputs.")
|
|
74
|
+
fnc_args = self._collect_inputs(spec)
|
|
79
75
|
|
|
80
|
-
LOGGER.info("
|
|
81
|
-
|
|
76
|
+
LOGGER.info("Configuring execution.")
|
|
77
|
+
fnc = self._configure_execution(spec)
|
|
82
78
|
|
|
83
79
|
LOGGER.info("Executing run.")
|
|
84
|
-
|
|
85
|
-
results: dict = self._execute(fnc, project, **fnc_args)
|
|
86
|
-
else:
|
|
87
|
-
exec_result = self._execute(fnc, **fnc_args)
|
|
88
|
-
LOGGER.info("Collecting outputs.")
|
|
89
|
-
results = parse_outputs(exec_result, list(spec.get("outputs", {})), project)
|
|
80
|
+
results = self._execute(executable, fnc, project, **fnc_args)
|
|
90
81
|
|
|
91
|
-
|
|
82
|
+
LOGGER.info("Collecting outputs.")
|
|
83
|
+
status = build_status(
|
|
84
|
+
results,
|
|
85
|
+
spec.get("outputs", {}),
|
|
86
|
+
spec.get("values", {}),
|
|
87
|
+
)
|
|
92
88
|
|
|
93
89
|
# Return run status
|
|
94
90
|
LOGGER.info("Task completed, returning run status.")
|
|
@@ -109,51 +105,57 @@ class RuntimePython(Runtime):
|
|
|
109
105
|
Callable
|
|
110
106
|
Function to execute.
|
|
111
107
|
"""
|
|
108
|
+
if action == "job":
|
|
109
|
+
return run_python
|
|
112
110
|
raise NotImplementedError
|
|
113
111
|
|
|
114
112
|
####################
|
|
115
|
-
#
|
|
113
|
+
# Inputs
|
|
116
114
|
####################
|
|
117
115
|
|
|
118
|
-
def
|
|
116
|
+
def _collect_inputs(self, spec: dict) -> dict:
|
|
119
117
|
"""
|
|
120
|
-
|
|
118
|
+
Collect inputs.
|
|
121
119
|
|
|
122
120
|
Parameters
|
|
123
121
|
----------
|
|
124
122
|
spec : dict
|
|
125
|
-
Run
|
|
123
|
+
Run specs.
|
|
124
|
+
project : str
|
|
125
|
+
Project name.
|
|
126
126
|
|
|
127
127
|
Returns
|
|
128
128
|
-------
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
dict
|
|
130
|
+
Parameters.
|
|
131
131
|
"""
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
LOGGER.info("Getting inputs.")
|
|
133
|
+
self.tmp_path.mkdir(parents=True, exist_ok=True)
|
|
134
|
+
return get_inputs_parameters(
|
|
135
|
+
spec.get("inputs", {}),
|
|
136
|
+
spec.get("parameters", {}),
|
|
137
|
+
self.tmp_path,
|
|
135
138
|
)
|
|
136
|
-
return fnc, hasattr(fnc, "__wrapped__")
|
|
137
139
|
|
|
138
|
-
|
|
140
|
+
####################
|
|
141
|
+
# Configuration
|
|
142
|
+
####################
|
|
143
|
+
|
|
144
|
+
def _configure_execution(self, spec: dict) -> Callable:
|
|
139
145
|
"""
|
|
140
|
-
|
|
146
|
+
Configure execution.
|
|
141
147
|
|
|
142
148
|
Parameters
|
|
143
149
|
----------
|
|
144
|
-
func : Callable
|
|
145
|
-
Function to execute.
|
|
146
150
|
spec : dict
|
|
147
|
-
Run
|
|
148
|
-
project : str
|
|
149
|
-
Project name.
|
|
151
|
+
Run spec.
|
|
150
152
|
|
|
151
153
|
Returns
|
|
152
154
|
-------
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
Callable
|
|
156
|
+
Function to execute.
|
|
155
157
|
"""
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
return get_function_from_source(
|
|
159
|
+
self.root_path,
|
|
160
|
+
spec.get("source", {}),
|
|
161
|
+
)
|
|
@@ -13,7 +13,6 @@ from digitalhub_core.utils.generic_utils import (
|
|
|
13
13
|
)
|
|
14
14
|
from digitalhub_core.utils.git_utils import clone_repository
|
|
15
15
|
from digitalhub_core.utils.logger import LOGGER
|
|
16
|
-
from digitalhub_core.utils.uri_utils import map_uri_scheme
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
def get_function_from_source(path: Path, source_spec: dict) -> Callable:
|
|
@@ -34,35 +33,14 @@ def get_function_from_source(path: Path, source_spec: dict) -> Callable:
|
|
|
34
33
|
"""
|
|
35
34
|
try:
|
|
36
35
|
function_code = save_function_source(path, source_spec)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return import_function(function_path, function_name)
|
|
36
|
+
handler = source_spec["handler"]
|
|
37
|
+
return import_function(function_code, handler)
|
|
40
38
|
except Exception as e:
|
|
41
39
|
msg = f"Some error occurred while getting function. Exception: {e.__class__}. Error: {e.args}"
|
|
42
40
|
LOGGER.exception(msg)
|
|
43
41
|
raise RuntimeError(msg) from e
|
|
44
42
|
|
|
45
43
|
|
|
46
|
-
def parse_handler(handler: str) -> tuple:
|
|
47
|
-
"""
|
|
48
|
-
Parse handler.
|
|
49
|
-
|
|
50
|
-
Parameters
|
|
51
|
-
----------
|
|
52
|
-
handler : str
|
|
53
|
-
Function handler
|
|
54
|
-
|
|
55
|
-
Returns
|
|
56
|
-
-------
|
|
57
|
-
str
|
|
58
|
-
Function handler.
|
|
59
|
-
"""
|
|
60
|
-
parsed = handler.split(":")
|
|
61
|
-
if len(parsed) == 1:
|
|
62
|
-
return Path(""), parsed[0]
|
|
63
|
-
return Path(*parsed[0].split(".")), parsed[1]
|
|
64
|
-
|
|
65
|
-
|
|
66
44
|
def save_function_source(path: Path, source_spec: dict) -> Path:
|
|
67
45
|
"""
|
|
68
46
|
Save function source.
|
|
@@ -85,45 +63,38 @@ def save_function_source(path: Path, source_spec: dict) -> Path:
|
|
|
85
63
|
# Get relevant information
|
|
86
64
|
base64 = source_spec.get("base64")
|
|
87
65
|
source = source_spec.get("source")
|
|
66
|
+
handler = source_spec.get("handler")
|
|
88
67
|
|
|
89
|
-
scheme = None
|
|
90
|
-
if source is not None:
|
|
91
|
-
scheme = map_uri_scheme(source)
|
|
92
|
-
|
|
93
|
-
# Base64
|
|
94
68
|
if base64 is not None:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
base64_path = path / filename
|
|
100
|
-
base64_path.write_text(decode_base64(base64))
|
|
69
|
+
path = path / "main.py"
|
|
70
|
+
path.write_text(decode_base64(base64))
|
|
71
|
+
return path
|
|
101
72
|
|
|
102
|
-
|
|
103
|
-
return base64_path
|
|
104
|
-
|
|
105
|
-
# Git repo
|
|
106
|
-
if scheme == "git":
|
|
107
|
-
get_repository(path, source)
|
|
73
|
+
scheme = source.split("://")[0]
|
|
108
74
|
|
|
109
75
|
# Http(s) or s3 presigned urls
|
|
110
|
-
|
|
76
|
+
if scheme in ["http", "https"]:
|
|
111
77
|
filename = path / "archive.zip"
|
|
112
78
|
get_remote_source(source, filename)
|
|
113
79
|
unzip(path, filename)
|
|
80
|
+
return path / handler
|
|
81
|
+
|
|
82
|
+
# Git repo
|
|
83
|
+
if scheme == "git+https":
|
|
84
|
+
path = path / "repository"
|
|
85
|
+
get_repository(path, source)
|
|
86
|
+
return path / handler
|
|
114
87
|
|
|
115
88
|
# S3 path
|
|
116
|
-
|
|
89
|
+
if scheme == "zip+s3":
|
|
117
90
|
filename = path / "archive.zip"
|
|
118
91
|
bucket, key = get_bucket_and_key(source)
|
|
119
92
|
get_s3_source(bucket, key, filename)
|
|
120
93
|
unzip(path, filename)
|
|
94
|
+
return path / handler
|
|
121
95
|
|
|
122
96
|
# Unsupported scheme
|
|
123
|
-
|
|
124
|
-
raise RuntimeError(f"Unsupported scheme: {scheme}")
|
|
125
|
-
|
|
126
|
-
return path
|
|
97
|
+
raise RuntimeError(f"Unsupported scheme: {scheme}")
|
|
127
98
|
|
|
128
99
|
|
|
129
100
|
def get_remote_source(source: str, filename: Path) -> None:
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Callable
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def run_python(func: Callable, *args, **kwargs) -> dict:
|
|
7
|
+
"""
|
|
8
|
+
Execute function.
|
|
9
|
+
|
|
10
|
+
Parameters
|
|
11
|
+
----------
|
|
12
|
+
func : Callable
|
|
13
|
+
Function.
|
|
14
|
+
args : tuple
|
|
15
|
+
Function arguments.
|
|
16
|
+
kwargs : dict
|
|
17
|
+
Function keyword arguments.
|
|
18
|
+
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
21
|
+
dict
|
|
22
|
+
Outputs from the function.
|
|
23
|
+
"""
|
|
24
|
+
return func(*args, **kwargs)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from digitalhub_core.entities.artifacts.crud import artifact_from_dict
|
|
7
|
+
from digitalhub_core.utils.exceptions import EntityError
|
|
8
|
+
from digitalhub_core.utils.generic_utils import parse_entity_key
|
|
9
|
+
from digitalhub_core.utils.logger import LOGGER
|
|
10
|
+
from digitalhub_data.entities.dataitems.crud import dataitem_from_dict
|
|
11
|
+
from digitalhub_ml.entities.models.crud import model_from_dict
|
|
12
|
+
|
|
13
|
+
if typing.TYPE_CHECKING:
|
|
14
|
+
from digitalhub_core.entities._base.entity import Entity
|
|
15
|
+
from digitalhub_core.entities.artifacts.entity import Artifact
|
|
16
|
+
from digitalhub_data.entities.dataitems.entity._base import Dataitem
|
|
17
|
+
from digitalhub_ml.entities.models.entity import Model
|
|
18
|
+
from pandas import DataFrame
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def persist_dataitem(dataitem: Dataitem, tmp_dir: Path) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Persist dataitem locally.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
dataitem : Dataitem
|
|
28
|
+
The dataitem to persist.
|
|
29
|
+
tmp_dir : Path
|
|
30
|
+
Temporary download directory.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
str
|
|
35
|
+
Temporary dataitem path.
|
|
36
|
+
|
|
37
|
+
Raises
|
|
38
|
+
------
|
|
39
|
+
EntityError
|
|
40
|
+
If the dataitem cannot be persisted.
|
|
41
|
+
"""
|
|
42
|
+
name = dataitem.name
|
|
43
|
+
try:
|
|
44
|
+
LOGGER.info(f"Persisting dataitem '{name}' locally.")
|
|
45
|
+
tmp_path = tmp_dir / f"{name}.csv"
|
|
46
|
+
dataframe: DataFrame = dataitem.as_df()
|
|
47
|
+
dataframe.to_csv(tmp_path, sep=",", index=False)
|
|
48
|
+
return str(tmp_path)
|
|
49
|
+
except Exception as e:
|
|
50
|
+
msg = f"Error during dataitem '{name}' collection. Exception: {e.__class__}. Error: {e.args}"
|
|
51
|
+
LOGGER.exception(msg)
|
|
52
|
+
raise EntityError(msg) from e
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def persist_artifact(artifact: Artifact, tmp_dir: Path) -> str:
|
|
56
|
+
"""
|
|
57
|
+
Persist artifact locally.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
artifact : Artifact
|
|
62
|
+
The artifact object.
|
|
63
|
+
tmp_dir : Path
|
|
64
|
+
Temporary directory.
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
str
|
|
69
|
+
Temporary artifact path.
|
|
70
|
+
|
|
71
|
+
Raises
|
|
72
|
+
------
|
|
73
|
+
EntityError
|
|
74
|
+
If the artifact cannot be persisted.
|
|
75
|
+
"""
|
|
76
|
+
name = artifact.name
|
|
77
|
+
try:
|
|
78
|
+
LOGGER.info(f"Persisting artifact '{name}' locally.")
|
|
79
|
+
filename = Path(artifact.spec.path).name
|
|
80
|
+
dst = tmp_dir / filename
|
|
81
|
+
tmp_path = artifact.download(dst=dst)
|
|
82
|
+
return str(tmp_path)
|
|
83
|
+
except Exception as e:
|
|
84
|
+
msg = f"Error during artifact '{name}' collection. Exception: {e.__class__}. Error: {e.args}"
|
|
85
|
+
LOGGER.exception(msg)
|
|
86
|
+
raise EntityError(msg) from e
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def persist_model(model: Model, tmp_dir: Path) -> str:
|
|
90
|
+
"""
|
|
91
|
+
Persist model locally.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
model : Model
|
|
96
|
+
The model object.
|
|
97
|
+
tmp_dir : Path
|
|
98
|
+
Temporary directory.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
str
|
|
103
|
+
Temporary model path.
|
|
104
|
+
|
|
105
|
+
Raises
|
|
106
|
+
------
|
|
107
|
+
EntityError
|
|
108
|
+
If the model cannot be persisted.
|
|
109
|
+
"""
|
|
110
|
+
name = model.name
|
|
111
|
+
try:
|
|
112
|
+
LOGGER.info(f"Persisting model '{name}' locally.")
|
|
113
|
+
filename = Path(model.spec.path).name
|
|
114
|
+
dst = tmp_dir / filename
|
|
115
|
+
tmp_path = model.download(dst=dst)
|
|
116
|
+
return str(tmp_path)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
msg = f"Error during model '{name}' collection. Exception: {e.__class__}. Error: {e.args}"
|
|
119
|
+
LOGGER.exception(msg)
|
|
120
|
+
raise EntityError(msg) from e
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def get_inputs_parameters(inputs: dict[str, Entity], parameters: dict, tmp_dir: Path) -> dict:
|
|
124
|
+
"""
|
|
125
|
+
Set inputs.
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
----------
|
|
129
|
+
inputs : dict[str, Entity]
|
|
130
|
+
Run inputs.
|
|
131
|
+
parameters : dict
|
|
132
|
+
Run parameters.
|
|
133
|
+
tmp_dir : Path
|
|
134
|
+
Temporary directory for storing dataitms and artifacts.
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
dict
|
|
139
|
+
Mlrun inputs.
|
|
140
|
+
"""
|
|
141
|
+
inputs_objects = {}
|
|
142
|
+
for k, v in inputs.items():
|
|
143
|
+
_, entity_type, _, _, _ = parse_entity_key(v.get("key"))
|
|
144
|
+
if entity_type == "dataitems":
|
|
145
|
+
v = dataitem_from_dict(v)
|
|
146
|
+
inputs_objects[k] = persist_dataitem(v, tmp_dir)
|
|
147
|
+
elif entity_type == "artifacts":
|
|
148
|
+
v = artifact_from_dict(v)
|
|
149
|
+
inputs_objects[k] = persist_artifact(v, tmp_dir)
|
|
150
|
+
elif entity_type == "models":
|
|
151
|
+
v = model_from_dict(v)
|
|
152
|
+
inputs_objects[k] = persist_model(v, tmp_dir)
|
|
153
|
+
return {**inputs_objects, **parameters}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import pickle
|
|
4
|
+
import typing
|
|
4
5
|
from typing import Any
|
|
5
6
|
|
|
6
7
|
from digitalhub_core.entities._base.status import State
|
|
7
8
|
from digitalhub_core.entities.artifacts.crud import new_artifact
|
|
8
|
-
from digitalhub_core.entities.artifacts.entity import Artifact
|
|
9
9
|
from digitalhub_core.utils.logger import LOGGER
|
|
10
10
|
from digitalhub_data.entities.dataitems.crud import new_dataitem
|
|
11
|
-
from digitalhub_data.entities.dataitems.entity.table import DataitemTable
|
|
12
11
|
from digitalhub_data.readers.registry import DATAFRAME_TYPES
|
|
13
12
|
|
|
13
|
+
if typing.TYPE_CHECKING:
|
|
14
|
+
from digitalhub_core.entities.artifacts.entity import Artifact
|
|
15
|
+
from digitalhub_data.entities.dataitems.entity.table import DataitemTable
|
|
16
|
+
|
|
14
17
|
|
|
15
18
|
def collect_outputs(results: Any, outputs: list[str], project_name: str) -> dict:
|
|
16
19
|
"""
|
|
@@ -49,32 +52,6 @@ def collect_outputs(results: Any, outputs: list[str], project_name: str) -> dict
|
|
|
49
52
|
return objects
|
|
50
53
|
|
|
51
54
|
|
|
52
|
-
def parse_outputs(results: Any, run_outputs: list, project_name: str) -> dict:
|
|
53
|
-
"""
|
|
54
|
-
Parse outputs.
|
|
55
|
-
|
|
56
|
-
Parameters
|
|
57
|
-
----------
|
|
58
|
-
results : Any
|
|
59
|
-
Function outputs.
|
|
60
|
-
project : Project
|
|
61
|
-
Project object.
|
|
62
|
-
|
|
63
|
-
Returns
|
|
64
|
-
-------
|
|
65
|
-
dict
|
|
66
|
-
Function outputs.
|
|
67
|
-
"""
|
|
68
|
-
results_list = listify_results(results)
|
|
69
|
-
out_list = []
|
|
70
|
-
for idx, _ in enumerate(results_list):
|
|
71
|
-
try:
|
|
72
|
-
out_list.append(run_outputs.pop(0))
|
|
73
|
-
except IndexError:
|
|
74
|
-
out_list.append(f"output_{idx}")
|
|
75
|
-
return collect_outputs(results, out_list, project_name)
|
|
76
|
-
|
|
77
|
-
|
|
78
55
|
def listify_results(results: Any) -> list:
|
|
79
56
|
"""
|
|
80
57
|
Listify results.
|
|
@@ -165,6 +142,7 @@ def build_and_load_artifact(name: str, project_name: str, data: Any) -> Artifact
|
|
|
165
142
|
def build_status(
|
|
166
143
|
parsed_execution: dict,
|
|
167
144
|
mapped_outputs: dict | None = None,
|
|
145
|
+
values_list: list | None = None,
|
|
168
146
|
) -> dict:
|
|
169
147
|
"""
|
|
170
148
|
Collect outputs.
|
|
@@ -175,24 +153,31 @@ def build_status(
|
|
|
175
153
|
Parsed execution dict.
|
|
176
154
|
mapped_outputs : dict
|
|
177
155
|
Mapped outputs.
|
|
156
|
+
values_list : list
|
|
157
|
+
Values list.
|
|
178
158
|
|
|
179
159
|
Returns
|
|
180
160
|
-------
|
|
181
161
|
dict
|
|
182
162
|
Status dict.
|
|
183
163
|
"""
|
|
184
|
-
results = {}
|
|
185
164
|
outputs = {}
|
|
186
165
|
if mapped_outputs is None:
|
|
187
166
|
mapped_outputs = {}
|
|
188
167
|
|
|
168
|
+
results = {}
|
|
169
|
+
if values_list is None:
|
|
170
|
+
values_list = []
|
|
171
|
+
|
|
189
172
|
try:
|
|
190
|
-
for key,
|
|
173
|
+
for key, value in mapped_outputs.items():
|
|
191
174
|
if key in parsed_execution:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
175
|
+
outputs[key] = parsed_execution[key].key
|
|
176
|
+
|
|
177
|
+
for value in values_list:
|
|
178
|
+
if value in parsed_execution:
|
|
179
|
+
results[value] = parsed_execution[value]
|
|
180
|
+
|
|
196
181
|
return {
|
|
197
182
|
"state": State.COMPLETED.value,
|
|
198
183
|
"outputs": outputs,
|
|
@@ -9,19 +9,22 @@ digitalhub_runtime_python.egg-info/requires.txt
|
|
|
9
9
|
digitalhub_runtime_python.egg-info/top_level.txt
|
|
10
10
|
digitalhub_runtime_python/entities/__init__.py
|
|
11
11
|
digitalhub_runtime_python/entities/functions/__init__.py
|
|
12
|
+
digitalhub_runtime_python/entities/functions/metadata.py
|
|
12
13
|
digitalhub_runtime_python/entities/functions/spec.py
|
|
13
14
|
digitalhub_runtime_python/entities/functions/status.py
|
|
14
15
|
digitalhub_runtime_python/entities/runs/__init__.py
|
|
16
|
+
digitalhub_runtime_python/entities/runs/metadata.py
|
|
15
17
|
digitalhub_runtime_python/entities/runs/spec.py
|
|
16
18
|
digitalhub_runtime_python/entities/runs/status.py
|
|
17
19
|
digitalhub_runtime_python/entities/tasks/__init__.py
|
|
20
|
+
digitalhub_runtime_python/entities/tasks/metadata.py
|
|
18
21
|
digitalhub_runtime_python/entities/tasks/models.py
|
|
19
22
|
digitalhub_runtime_python/entities/tasks/spec.py
|
|
20
23
|
digitalhub_runtime_python/entities/tasks/status.py
|
|
21
24
|
digitalhub_runtime_python/runtimes/__init__.py
|
|
22
|
-
digitalhub_runtime_python/runtimes/kind_registry.py
|
|
23
25
|
digitalhub_runtime_python/runtimes/runtime.py
|
|
24
26
|
digitalhub_runtime_python/utils/configuration.py
|
|
27
|
+
digitalhub_runtime_python/utils/functions.py
|
|
25
28
|
digitalhub_runtime_python/utils/inputs.py
|
|
26
29
|
digitalhub_runtime_python/utils/outputs.py
|
|
27
30
|
digitalhub_runtime_python/utils/utils.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "digitalhub-runtime-python"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.0b5"
|
|
8
8
|
description = "Python runtime for DHCore"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -39,7 +39,7 @@ line-length = 120
|
|
|
39
39
|
convention = "numpy"
|
|
40
40
|
|
|
41
41
|
[tool.bumpver]
|
|
42
|
-
current_version = "0.5.
|
|
42
|
+
current_version = "0.5.0b5"
|
|
43
43
|
version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
|
|
44
44
|
commit_message = "Bump version {old_version} -> {new_version}"
|
|
45
45
|
commit = false
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from digitalhub_ml.entities.runs.spec import RunParamsMl, RunSpecMl
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class RunSpecPython(RunSpecMl):
|
|
7
|
-
"""Run Python specification."""
|
|
8
|
-
|
|
9
|
-
def __init__(
|
|
10
|
-
self,
|
|
11
|
-
task: str,
|
|
12
|
-
local_execution: bool = False,
|
|
13
|
-
**kwargs,
|
|
14
|
-
) -> None:
|
|
15
|
-
"""
|
|
16
|
-
Constructor.
|
|
17
|
-
"""
|
|
18
|
-
super().__init__(task, local_execution)
|
|
19
|
-
|
|
20
|
-
self.source = kwargs.get("source")
|
|
21
|
-
self.image = kwargs.get("image")
|
|
22
|
-
self.base_image = kwargs.get("base_image")
|
|
23
|
-
self.python_version = kwargs.get("python_version")
|
|
24
|
-
self.requirements = kwargs.get("requirements")
|
|
25
|
-
|
|
26
|
-
self.function = kwargs.get("function")
|
|
27
|
-
self.node_selector = kwargs.get("node_selector")
|
|
28
|
-
self.volumes = kwargs.get("volumes")
|
|
29
|
-
self.resources = kwargs.get("resources")
|
|
30
|
-
self.affinity = kwargs.get("affinity")
|
|
31
|
-
self.tolerations = kwargs.get("tolerations")
|
|
32
|
-
self.env = kwargs.get("env")
|
|
33
|
-
self.secrets = kwargs.get("secrets")
|
|
34
|
-
self.backoff_limit = kwargs.get("backoff_limit")
|
|
35
|
-
self.schedule = kwargs.get("schedule")
|
|
36
|
-
self.replicas = kwargs.get("replicas")
|
|
37
|
-
|
|
38
|
-
# Task job
|
|
39
|
-
|
|
40
|
-
# Task build
|
|
41
|
-
self.instructions = kwargs.get("instructions")
|
|
42
|
-
|
|
43
|
-
self.inputs = kwargs.get("inputs")
|
|
44
|
-
self.outputs = kwargs.get("outputs")
|
|
45
|
-
self.parameters = kwargs.get("parameters")
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class RunParamsPython(RunParamsMl):
|
|
49
|
-
"""Run Python parameters."""
|
|
50
|
-
|
|
51
|
-
# Function parameters
|
|
52
|
-
source: dict = None
|
|
53
|
-
image: str = None
|
|
54
|
-
base_image: str = None
|
|
55
|
-
python_version: str = None
|
|
56
|
-
requirements: list = None
|
|
57
|
-
|
|
58
|
-
# Task parameters
|
|
59
|
-
function: str = None
|
|
60
|
-
node_selector: list[dict] = None
|
|
61
|
-
volumes: list[dict] = None
|
|
62
|
-
resources: list[dict] = None
|
|
63
|
-
affinity: dict = None
|
|
64
|
-
tolerations: list[dict] = None
|
|
65
|
-
env: list[dict] = None
|
|
66
|
-
secrets: list[str] = None
|
|
67
|
-
|
|
68
|
-
# Task job
|
|
69
|
-
backoff_limit: int = None
|
|
70
|
-
|
|
71
|
-
# Task serve
|
|
72
|
-
service_type: str = None
|
|
73
|
-
replicas: int = None
|
|
74
|
-
|
|
75
|
-
# Task build
|
|
76
|
-
instructions: list[str] = None
|
|
77
|
-
|
|
78
|
-
# Run parameters
|
|
79
|
-
inputs: dict = None
|
|
80
|
-
outputs: dict = None
|
|
81
|
-
parameters: dict = None
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Task Python specification module.
|
|
3
|
-
"""
|
|
4
|
-
from __future__ import annotations
|
|
5
|
-
|
|
6
|
-
from typing import Literal
|
|
7
|
-
|
|
8
|
-
from digitalhub_core.entities.tasks.spec import TaskParamsK8s, TaskSpecK8s
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class TaskSpecJob(TaskSpecK8s):
|
|
12
|
-
"""Task Job specification."""
|
|
13
|
-
|
|
14
|
-
def __init__(
|
|
15
|
-
self,
|
|
16
|
-
function: str,
|
|
17
|
-
**kwargs,
|
|
18
|
-
) -> None:
|
|
19
|
-
"""
|
|
20
|
-
Constructor.
|
|
21
|
-
"""
|
|
22
|
-
super().__init__(function, **kwargs)
|
|
23
|
-
|
|
24
|
-
self.backoff_limit = kwargs.get("backoff_limit")
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class TaskParamsJob(TaskParamsK8s):
|
|
28
|
-
"""
|
|
29
|
-
TaskParamsJob model.
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
|
-
backoff_limit: int = None
|
|
33
|
-
"""Backoff limit."""
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class TaskSpecBuild(TaskSpecK8s):
|
|
37
|
-
"""Task Build specification."""
|
|
38
|
-
|
|
39
|
-
def __init__(
|
|
40
|
-
self,
|
|
41
|
-
function: str,
|
|
42
|
-
instructions: list | None = None,
|
|
43
|
-
**kwargs,
|
|
44
|
-
) -> None:
|
|
45
|
-
"""
|
|
46
|
-
Constructor.
|
|
47
|
-
"""
|
|
48
|
-
super().__init__(function, **kwargs)
|
|
49
|
-
|
|
50
|
-
self.instructions = instructions
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
class TaskParamsBuild(TaskParamsK8s):
|
|
54
|
-
"""
|
|
55
|
-
TaskParamsBuild model.
|
|
56
|
-
"""
|
|
57
|
-
|
|
58
|
-
instructions: list[str] = None
|
|
59
|
-
"""Build instructions."""
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class TaskSpecServe(TaskSpecK8s):
|
|
63
|
-
"""Task Serve specification."""
|
|
64
|
-
|
|
65
|
-
def __init__(
|
|
66
|
-
self,
|
|
67
|
-
function: str,
|
|
68
|
-
replicas: int | None = None,
|
|
69
|
-
service_type: str | None = None,
|
|
70
|
-
**kwargs,
|
|
71
|
-
) -> None:
|
|
72
|
-
"""
|
|
73
|
-
Constructor.
|
|
74
|
-
"""
|
|
75
|
-
super().__init__(function, **kwargs)
|
|
76
|
-
|
|
77
|
-
self.replicas = replicas
|
|
78
|
-
self.service_type = service_type
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class TaskParamsServe(TaskParamsK8s):
|
|
82
|
-
"""
|
|
83
|
-
TaskParamsServe model.
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
replicas: int = None
|
|
87
|
-
service_type: Literal["ClusterIP", "NodePort", "LoadBalancer"] = "NodePort"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from digitalhub_core.runtimes.kind_registry import KindRegistry
|
|
4
|
-
|
|
5
|
-
kind_registry = KindRegistry(
|
|
6
|
-
{
|
|
7
|
-
"executable": {"kind": "python"},
|
|
8
|
-
"task": [
|
|
9
|
-
{"kind": "python+job", "action": "job"},
|
|
10
|
-
{"kind": "python+serve", "action": "serve"},
|
|
11
|
-
{"kind": "python+build", "action": "build"},
|
|
12
|
-
],
|
|
13
|
-
"run": {"kind": "python+run"},
|
|
14
|
-
}
|
|
15
|
-
)
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import inspect
|
|
4
|
-
import typing
|
|
5
|
-
from typing import Any, Callable
|
|
6
|
-
|
|
7
|
-
from digitalhub_core.context.builder import get_context
|
|
8
|
-
from digitalhub_core.entities.artifacts.crud import artifact_from_dict
|
|
9
|
-
from digitalhub_core.utils.generic_utils import parse_entity_key
|
|
10
|
-
from digitalhub_core.utils.logger import LOGGER
|
|
11
|
-
from digitalhub_data.entities.dataitems.crud import dataitem_from_dict
|
|
12
|
-
from digitalhub_ml.entities.entity_types import EntityTypes
|
|
13
|
-
from digitalhub_ml.entities.models.crud import model_from_dict
|
|
14
|
-
from digitalhub_ml.entities.projects.crud import get_project
|
|
15
|
-
|
|
16
|
-
if typing.TYPE_CHECKING:
|
|
17
|
-
from digitalhub_core.entities._base.entity import Entity
|
|
18
|
-
from digitalhub_core.entities.projects.entity import Project
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def get_project_(project_name: str) -> Project:
|
|
22
|
-
"""
|
|
23
|
-
Get project.
|
|
24
|
-
|
|
25
|
-
Parameters
|
|
26
|
-
----------
|
|
27
|
-
project_name : str
|
|
28
|
-
Project name.
|
|
29
|
-
|
|
30
|
-
Returns
|
|
31
|
-
-------
|
|
32
|
-
Project
|
|
33
|
-
Project.
|
|
34
|
-
"""
|
|
35
|
-
try:
|
|
36
|
-
ctx = get_context(project_name)
|
|
37
|
-
return get_project(project_name, local=ctx.local)
|
|
38
|
-
except Exception as e:
|
|
39
|
-
msg = f"Error during project collection. Exception: {e.__class__}. Error: {e.args}"
|
|
40
|
-
LOGGER.exception(msg)
|
|
41
|
-
raise RuntimeError(msg)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def get_entity_inputs(inputs: dict) -> dict[str, Entity]:
|
|
45
|
-
"""
|
|
46
|
-
Set inputs.
|
|
47
|
-
|
|
48
|
-
Parameters
|
|
49
|
-
----------
|
|
50
|
-
inputs : dict
|
|
51
|
-
Run inputs.
|
|
52
|
-
parameters : dict
|
|
53
|
-
Run parameters.
|
|
54
|
-
tmp_dir : Path
|
|
55
|
-
Temporary directory for storing dataitms and artifacts.
|
|
56
|
-
|
|
57
|
-
Returns
|
|
58
|
-
-------
|
|
59
|
-
dict
|
|
60
|
-
Mlrun inputs.
|
|
61
|
-
"""
|
|
62
|
-
try:
|
|
63
|
-
inputs_objects = {}
|
|
64
|
-
for k, v in inputs.items():
|
|
65
|
-
_, entity_type, _, _, _ = parse_entity_key(v.get("key"))
|
|
66
|
-
if entity_type == EntityTypes.DATAITEMS.value:
|
|
67
|
-
inputs_objects[k] = dataitem_from_dict(v)
|
|
68
|
-
elif entity_type == EntityTypes.ARTIFACTS.value:
|
|
69
|
-
inputs_objects[k] = artifact_from_dict(v)
|
|
70
|
-
elif entity_type == EntityTypes.MODELS.value:
|
|
71
|
-
inputs_objects[k] = model_from_dict(v)
|
|
72
|
-
return inputs_objects
|
|
73
|
-
except Exception as e:
|
|
74
|
-
msg = f"Error during inputs collection. Exception: {e.__class__}. Error: {e.args}"
|
|
75
|
-
LOGGER.exception(msg)
|
|
76
|
-
raise RuntimeError(msg) from e
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def compose_inputs(
|
|
80
|
-
inputs: dict,
|
|
81
|
-
parameters: dict,
|
|
82
|
-
local_execution: bool,
|
|
83
|
-
func: Callable,
|
|
84
|
-
project: str | Project,
|
|
85
|
-
context: Any | None = None,
|
|
86
|
-
event: Any | None = None,
|
|
87
|
-
) -> dict:
|
|
88
|
-
"""
|
|
89
|
-
Compose inputs.
|
|
90
|
-
|
|
91
|
-
Parameters
|
|
92
|
-
----------
|
|
93
|
-
inputs : dict
|
|
94
|
-
Run inputs.
|
|
95
|
-
parameters : dict
|
|
96
|
-
Run parameters.
|
|
97
|
-
local_execution : bool
|
|
98
|
-
Local execution.
|
|
99
|
-
func : Callable
|
|
100
|
-
Function to execute.
|
|
101
|
-
project : str
|
|
102
|
-
Project name.
|
|
103
|
-
context : nuclio_sdk.Context
|
|
104
|
-
Nuclio context.
|
|
105
|
-
event : nuclio_sdk.Event
|
|
106
|
-
Nuclio event.
|
|
107
|
-
|
|
108
|
-
Returns
|
|
109
|
-
-------
|
|
110
|
-
dict
|
|
111
|
-
Function inputs.
|
|
112
|
-
"""
|
|
113
|
-
try:
|
|
114
|
-
entity_inputs = get_entity_inputs(inputs)
|
|
115
|
-
fnc_args = {**parameters, **entity_inputs}
|
|
116
|
-
|
|
117
|
-
fnc_parameters = inspect.signature(func).parameters
|
|
118
|
-
LOGGER.info(f"Function parameters: {'project' in fnc_parameters}")
|
|
119
|
-
|
|
120
|
-
_has_project = "project" in fnc_parameters
|
|
121
|
-
_has_context = "context" in fnc_parameters
|
|
122
|
-
_has_event = "event" in fnc_parameters
|
|
123
|
-
|
|
124
|
-
if _has_project:
|
|
125
|
-
if _has_context:
|
|
126
|
-
fnc_args["project"] = context.project
|
|
127
|
-
elif isinstance(project, str):
|
|
128
|
-
fnc_args["project"] = get_project_(project)
|
|
129
|
-
else:
|
|
130
|
-
fnc_args["project"] = project
|
|
131
|
-
|
|
132
|
-
if _has_context:
|
|
133
|
-
if context is not None and not local_execution:
|
|
134
|
-
fnc_args["context"] = context
|
|
135
|
-
else:
|
|
136
|
-
raise RuntimeError("Context is not available on local execution.")
|
|
137
|
-
|
|
138
|
-
if _has_event:
|
|
139
|
-
if event is not None and not local_execution:
|
|
140
|
-
fnc_args["event"] = event
|
|
141
|
-
else:
|
|
142
|
-
raise RuntimeError("Event is not available on local execution.")
|
|
143
|
-
|
|
144
|
-
return fnc_args
|
|
145
|
-
|
|
146
|
-
except Exception as e:
|
|
147
|
-
msg = f"Error during function arguments compostion. Exception: {e.__class__}. Error: {e.args}"
|
|
148
|
-
LOGGER.exception(msg)
|
|
149
|
-
raise RuntimeError(msg) from e
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|