digitalhub-runtime-python 0.5.0b10__tar.gz → 0.6.0__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.
Files changed (37) hide show
  1. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/PKG-INFO +2 -2
  2. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/__init__.py +1 -1
  3. digitalhub_runtime_python-0.6.0/digitalhub_runtime_python/entities/functions/models.py +101 -0
  4. digitalhub_runtime_python-0.6.0/digitalhub_runtime_python/entities/functions/spec.py +108 -0
  5. digitalhub_runtime_python-0.6.0/digitalhub_runtime_python/entities/runs/spec.py +78 -0
  6. digitalhub_runtime_python-0.6.0/digitalhub_runtime_python/entities/tasks/models.py +12 -0
  7. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/entities/tasks/spec.py +20 -21
  8. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/entities/tasks/status.py +6 -0
  9. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/runtimes/kind_registry.py +1 -1
  10. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/runtimes/runtime.py +45 -32
  11. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/utils/configuration.py +29 -0
  12. digitalhub_runtime_python-0.6.0/digitalhub_runtime_python/utils/env.py +3 -0
  13. digitalhub_runtime_python-0.6.0/digitalhub_runtime_python/utils/inputs.py +146 -0
  14. digitalhub_runtime_python-0.6.0/digitalhub_runtime_python/utils/nuclio_configuration.py +98 -0
  15. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/utils/outputs.py +32 -7
  16. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python.egg-info/PKG-INFO +2 -2
  17. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python.egg-info/SOURCES.txt +3 -0
  18. digitalhub_runtime_python-0.6.0/digitalhub_runtime_python.egg-info/requires.txt +1 -0
  19. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/pyproject.toml +3 -3
  20. digitalhub_runtime_python-0.5.0b10/digitalhub_runtime_python/entities/functions/spec.py +0 -139
  21. digitalhub_runtime_python-0.5.0b10/digitalhub_runtime_python/entities/runs/spec.py +0 -53
  22. digitalhub_runtime_python-0.5.0b10/digitalhub_runtime_python/entities/tasks/models.py +0 -31
  23. digitalhub_runtime_python-0.5.0b10/digitalhub_runtime_python/utils/inputs.py +0 -149
  24. digitalhub_runtime_python-0.5.0b10/digitalhub_runtime_python.egg-info/requires.txt +0 -1
  25. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/LICENSE.txt +0 -0
  26. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/README.md +0 -0
  27. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/entities/__init__.py +0 -0
  28. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/entities/functions/__init__.py +0 -0
  29. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/entities/functions/status.py +0 -0
  30. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/entities/runs/__init__.py +0 -0
  31. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/entities/runs/status.py +0 -0
  32. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/entities/tasks/__init__.py +0 -0
  33. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/runtimes/__init__.py +0 -0
  34. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python/utils/utils.py +0 -0
  35. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python.egg-info/dependency_links.txt +0 -0
  36. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/digitalhub_runtime_python.egg-info/top_level.txt +0 -0
  37. {digitalhub_runtime_python-0.5.0b10 → digitalhub_runtime_python-0.6.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: digitalhub-runtime-python
3
- Version: 0.5.0b10
3
+ Version: 0.6.0
4
4
  Summary: Python runtime for DHCore
5
5
  Author-email: Fondazione Bruno Kessler <dslab@fbk.eu>, Matteo Martini <mmartini@fbk.eu>
6
6
  License: Apache License
@@ -228,6 +228,6 @@ Classifier: Programming Language :: Python :: 3.10
228
228
  Requires-Python: >=3.9
229
229
  Description-Content-Type: text/markdown
230
230
  License-File: LICENSE.txt
231
- Requires-Dist: digitalhub[ml]<0.6,~=0.5.0b
231
+ Requires-Dist: digitalhub[ml]>=0.6.0b
232
232
 
233
233
  # SDK for DHCore
@@ -27,7 +27,7 @@ registry.register(func_kind, func_info)
27
27
 
28
28
  # Tasks
29
29
  entity_type = EntityTypes.TASKS.value
30
- for i in ["job", "build"]:
30
+ for i in ["job", "build", "serve"]:
31
31
  task_kind = f"{func_kind}+{i}"
32
32
  prefix = entity_type.removesuffix("s").capitalize()
33
33
  suffix = i.capitalize()
@@ -0,0 +1,101 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ from digitalhub_core.entities.functions.models import SourceCodeParams, SourceCodeStruct
6
+ from digitalhub_core.utils.exceptions import EntityError
7
+ from digitalhub_core.utils.generic_utils import encode_source, encode_string
8
+ from digitalhub_core.utils.uri_utils import map_uri_scheme
9
+
10
+
11
+ class SourceCodeStructPython(SourceCodeStruct):
12
+ """
13
+ Source code struct for python.
14
+ """
15
+
16
+ def __init__(
17
+ self,
18
+ source: str | None = None,
19
+ handler: str | None = None,
20
+ code: str | None = None,
21
+ base64: str | None = None,
22
+ lang: str | None = None,
23
+ init_function: str | None = None,
24
+ ) -> None:
25
+ super().__init__(
26
+ source=source,
27
+ handler=handler,
28
+ code=code,
29
+ base64=base64,
30
+ lang=lang,
31
+ )
32
+ self.init_function = init_function
33
+
34
+ @staticmethod
35
+ def source_check(source: dict) -> dict:
36
+ """
37
+ Check source. Overrides SourceCodeStruct.source_check.
38
+
39
+ Parameters
40
+ ----------
41
+ source : dict
42
+ Source.
43
+
44
+ Returns
45
+ -------
46
+ dict
47
+ Checked source.
48
+ """
49
+ # Source check
50
+ source_path = source.get("source")
51
+ code = source.get("code")
52
+ base64 = source.get("base64")
53
+ handler = source.get("handler")
54
+ source["lang"] = "python"
55
+
56
+ if handler is None:
57
+ raise EntityError("Handler must be provided.")
58
+
59
+ if source_path is None and code is None and base64 is None:
60
+ raise EntityError("Source must be provided.")
61
+
62
+ if base64 is not None:
63
+ return source
64
+
65
+ if code is not None:
66
+ source["base64"] = encode_string(code)
67
+ return source
68
+
69
+ if source_path is not None:
70
+ if map_uri_scheme(source_path) == "local":
71
+ if not (Path(source_path).suffix == ".py" and Path(source_path).is_file()):
72
+ raise EntityError("Source is not a valid python file.")
73
+ source["base64"] = encode_source(source_path)
74
+ else:
75
+ if handler is None:
76
+ raise EntityError("Handler must be provided if source is not local.")
77
+
78
+ return source
79
+
80
+ def to_dict(self) -> dict:
81
+ """
82
+ Convert to dictionary.
83
+
84
+ Returns
85
+ -------
86
+ dict
87
+ Dictionary representation of the object.
88
+ """
89
+ dict_ = super().to_dict()
90
+ if self.init_function is not None:
91
+ dict_["init_function"] = self.init_function
92
+ return dict_
93
+
94
+
95
+ class SourceCodeParamsPython(SourceCodeParams):
96
+ """
97
+ Source code params for python.
98
+ """
99
+
100
+ init_function: str = None
101
+ """Handler for init function."""
@@ -0,0 +1,108 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal
4
+
5
+ from digitalhub_core.entities.functions.spec import FunctionParams, FunctionSpec
6
+ from digitalhub_runtime_python.entities.functions.models import SourceCodeParamsPython, SourceCodeStructPython
7
+
8
+
9
+ class FunctionSpecPython(FunctionSpec):
10
+ """
11
+ Specification for a Function job.
12
+ """
13
+
14
+ def __init__(
15
+ self,
16
+ source: dict | None = None,
17
+ code_src: str | None = None,
18
+ handler: str | None = None,
19
+ code: str | None = None,
20
+ base64: str | None = None,
21
+ init_function: str | None = None,
22
+ lang: str | None = None,
23
+ image: str | None = None,
24
+ base_image: str | None = None,
25
+ python_version: str | None = None,
26
+ requirements: list | None = None,
27
+ ) -> None:
28
+ super().__init__()
29
+
30
+ self.image = image
31
+ self.base_image = base_image
32
+ self.python_version = python_version
33
+ self.requirements = requirements
34
+
35
+ # Give source precedence
36
+ if source is not None:
37
+ source_dict = source
38
+ else:
39
+ source_dict = {
40
+ "source": code_src,
41
+ "handler": handler,
42
+ "code": code,
43
+ "base64": base64,
44
+ "lang": lang,
45
+ "init_function": init_function,
46
+ }
47
+
48
+ source_checked = self.source_check(source_dict)
49
+ self.source = SourceCodeStructPython(**source_checked)
50
+
51
+ @staticmethod
52
+ def source_check(source: dict) -> dict:
53
+ """
54
+ Check source.
55
+
56
+ Parameters
57
+ ----------
58
+ source : dict
59
+ Source.
60
+
61
+ Returns
62
+ -------
63
+ dict
64
+ Checked source.
65
+ """
66
+ return SourceCodeStructPython.source_check(source)
67
+
68
+ def show_source_code(self) -> str:
69
+ """
70
+ Show source code.
71
+
72
+ Returns
73
+ -------
74
+ str
75
+ Source code.
76
+ """
77
+ return self.source.show_source_code()
78
+
79
+ def to_dict(self) -> dict:
80
+ """
81
+ Override to_dict to exclude code from source.
82
+
83
+ Returns
84
+ -------
85
+ dict
86
+ Dictionary representation of the object.
87
+ """
88
+ dict_ = super().to_dict()
89
+ dict_["source"] = self.source.to_dict()
90
+ return dict_
91
+
92
+
93
+ class FunctionParamsPython(FunctionParams, SourceCodeParamsPython):
94
+ """
95
+ Function python parameters model.
96
+ """
97
+
98
+ python_version: Literal["PYTHON3_9", "PYTHON3_10", "PYTHON3_11"]
99
+ "Python version"
100
+
101
+ image: str = None
102
+ "Image where the function will be executed"
103
+
104
+ base_image: str = None
105
+ "Base image used to build the image where the function will be executed"
106
+
107
+ requirements: list = None
108
+ "Requirements list to be installed in the image where the function will be executed"
@@ -0,0 +1,78 @@
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
+ super().__init__(task, local_execution)
16
+
17
+ self.source = kwargs.get("source")
18
+ self.image = kwargs.get("image")
19
+ self.base_image = kwargs.get("base_image")
20
+ self.python_version = kwargs.get("python_version")
21
+ self.requirements = kwargs.get("requirements")
22
+
23
+ self.function = kwargs.get("function")
24
+ self.node_selector = kwargs.get("node_selector")
25
+ self.volumes = kwargs.get("volumes")
26
+ self.resources = kwargs.get("resources")
27
+ self.affinity = kwargs.get("affinity")
28
+ self.tolerations = kwargs.get("tolerations")
29
+ self.env = kwargs.get("env")
30
+ self.secrets = kwargs.get("secrets")
31
+ self.backoff_limit = kwargs.get("backoff_limit")
32
+ self.schedule = kwargs.get("schedule")
33
+ self.replicas = kwargs.get("replicas")
34
+
35
+ # Task job
36
+
37
+ # Task build
38
+ self.instructions = kwargs.get("instructions")
39
+
40
+ self.inputs = kwargs.get("inputs")
41
+ self.outputs = kwargs.get("outputs")
42
+ self.parameters = kwargs.get("parameters")
43
+
44
+
45
+ class RunParamsPython(RunParamsMl):
46
+ """Run Python parameters."""
47
+
48
+ # Function parameters
49
+ source: dict = None
50
+ image: str = None
51
+ base_image: str = None
52
+ python_version: str = None
53
+ requirements: list = None
54
+
55
+ # Task parameters
56
+ function: str = None
57
+ node_selector: list[dict] = None
58
+ volumes: list[dict] = None
59
+ resources: list[dict] = None
60
+ affinity: dict = None
61
+ tolerations: list[dict] = None
62
+ env: list[dict] = None
63
+ secrets: list[str] = None
64
+
65
+ # Task job
66
+ backoff_limit: int = None
67
+
68
+ # Task serve
69
+ service_type: str = None
70
+ replicas: int = None
71
+
72
+ # Task build
73
+ instructions: list[str] = None
74
+
75
+ # Run parameters
76
+ inputs: dict = None
77
+ outputs: dict = None
78
+ parameters: dict = None
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class CorePort(BaseModel):
7
+ """
8
+ Port mapper model.
9
+ """
10
+
11
+ port: int
12
+ target_port: int
@@ -1,10 +1,8 @@
1
- """
2
- Task Python specification module.
3
- """
4
1
  from __future__ import annotations
5
2
 
3
+ from typing import Literal
4
+
6
5
  from digitalhub_core.entities.tasks.spec import TaskParamsK8s, TaskSpecK8s
7
- from digitalhub_runtime_python.entities.tasks.models import ContextRef, ContextSource
8
6
 
9
7
 
10
8
  class TaskSpecJob(TaskSpecK8s):
@@ -15,13 +13,9 @@ class TaskSpecJob(TaskSpecK8s):
15
13
  function: str,
16
14
  **kwargs,
17
15
  ) -> None:
18
- """
19
- Constructor.
20
- """
21
16
  super().__init__(function, **kwargs)
22
17
 
23
18
  self.backoff_limit = kwargs.get("backoff_limit")
24
- self.schedule = kwargs.get("schedule")
25
19
 
26
20
 
27
21
  class TaskParamsJob(TaskParamsK8s):
@@ -29,6 +23,9 @@ class TaskParamsJob(TaskParamsK8s):
29
23
  TaskParamsJob model.
30
24
  """
31
25
 
26
+ backoff_limit: int = None
27
+ """Backoff limit."""
28
+
32
29
 
33
30
  class TaskSpecBuild(TaskSpecK8s):
34
31
  """Task Build specification."""
@@ -36,18 +33,11 @@ class TaskSpecBuild(TaskSpecK8s):
36
33
  def __init__(
37
34
  self,
38
35
  function: str,
39
- context_refs: list | None = None,
40
- context_sources: list | None = None,
41
36
  instructions: list | None = None,
42
37
  **kwargs,
43
38
  ) -> None:
44
- """
45
- Constructor.
46
- """
47
39
  super().__init__(function, **kwargs)
48
40
 
49
- self.context_refs = context_refs
50
- self.context_sources = context_sources
51
41
  self.instructions = instructions
52
42
 
53
43
 
@@ -56,12 +46,6 @@ class TaskParamsBuild(TaskParamsK8s):
56
46
  TaskParamsBuild model.
57
47
  """
58
48
 
59
- context_refs: list[ContextRef] = None
60
- """Context references."""
61
-
62
- context_sources: list[ContextSource] = None
63
- """Context sources."""
64
-
65
49
  instructions: list[str] = None
66
50
  """Build instructions."""
67
51
 
@@ -69,8 +53,23 @@ class TaskParamsBuild(TaskParamsK8s):
69
53
  class TaskSpecServe(TaskSpecK8s):
70
54
  """Task Serve specification."""
71
55
 
56
+ def __init__(
57
+ self,
58
+ function: str,
59
+ replicas: int | None = None,
60
+ service_type: str | None = None,
61
+ **kwargs,
62
+ ) -> None:
63
+ super().__init__(function, **kwargs)
64
+
65
+ self.replicas = replicas
66
+ self.service_type = service_type
67
+
72
68
 
73
69
  class TaskParamsServe(TaskParamsK8s):
74
70
  """
75
71
  TaskParamsServe model.
76
72
  """
73
+
74
+ replicas: int = None
75
+ service_type: Literal["ClusterIP", "NodePort", "LoadBalancer"] = "NodePort"
@@ -13,3 +13,9 @@ class TaskStatusBuild(TaskStatus):
13
13
  """
14
14
  Task Build status.
15
15
  """
16
+
17
+
18
+ class TaskStatusServe(TaskStatus):
19
+ """
20
+ Task Serve status.
21
+ """
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from digitalhub_core.runtimes.registry import KindRegistry
3
+ from digitalhub_core.runtimes.kind_registry import KindRegistry
4
4
 
5
5
  kind_registry = KindRegistry(
6
6
  {
@@ -1,6 +1,3 @@
1
- """
2
- Runtime class for running Python functions.
3
- """
4
1
  from __future__ import annotations
5
2
 
6
3
  import typing
@@ -10,11 +7,11 @@ from digitalhub_core.context.builder import get_context
10
7
  from digitalhub_core.runtimes.base import Runtime
11
8
  from digitalhub_core.utils.logger import LOGGER
12
9
  from digitalhub_runtime_python.utils.configuration import get_function_from_source
13
- from digitalhub_runtime_python.utils.inputs import get_inputs_parameters
10
+ from digitalhub_runtime_python.utils.inputs import compose_inputs
14
11
  from digitalhub_runtime_python.utils.outputs import build_status, parse_outputs
15
12
 
16
13
  if typing.TYPE_CHECKING:
17
- from digitalhub_core.runtimes.registry import KindRegistry
14
+ from digitalhub_core.runtimes.kind_registry import KindRegistry
18
15
 
19
16
 
20
17
  class RuntimePython(Runtime):
@@ -23,16 +20,13 @@ class RuntimePython(Runtime):
23
20
  """
24
21
 
25
22
  def __init__(self, kind_registry: KindRegistry, project: str) -> None:
26
- """
27
- Constructor.
28
- """
29
23
  super().__init__(kind_registry, project)
30
24
  ctx = get_context(self.project)
31
25
  self.root = ctx.runtime_dir
32
- self.tmp_path = ctx.tmp_dir
26
+ self.tmp_dir = ctx.tmp_dir
33
27
 
34
28
  self.root.mkdir(parents=True, exist_ok=True)
35
- self.tmp_path.mkdir(parents=True, exist_ok=True)
29
+ self.tmp_dir.mkdir(parents=True, exist_ok=True)
36
30
 
37
31
  def build(self, function: dict, task: dict, run: dict) -> dict:
38
32
  """
@@ -70,16 +64,19 @@ class RuntimePython(Runtime):
70
64
  LOGGER.info("Validating task.")
71
65
  self._validate_task(run)
72
66
 
67
+ LOGGER.info("Validating run.")
68
+ self._validate_run(run)
69
+
73
70
  LOGGER.info("Starting task.")
74
71
  spec = run.get("spec")
75
72
  project = run.get("project")
76
73
 
77
- LOGGER.info("Collecting inputs.")
78
- fnc_args = self._collect_inputs(spec)
79
-
80
74
  LOGGER.info("Configuring execution.")
81
75
  fnc, wrapped = self._configure_execution(spec)
82
76
 
77
+ LOGGER.info("Composing function arguments.")
78
+ fnc_args = self._compose_args(fnc, spec, project)
79
+
83
80
  LOGGER.info("Executing run.")
84
81
  if wrapped:
85
82
  results: dict = self._execute(fnc, project, **fnc_args)
@@ -111,33 +108,26 @@ class RuntimePython(Runtime):
111
108
  """
112
109
  raise NotImplementedError
113
110
 
114
- ####################
115
- # Inputs
116
- ####################
117
-
118
- def _collect_inputs(self, spec: dict) -> dict:
111
+ @staticmethod
112
+ def _validate_run(run: dict) -> None:
119
113
  """
120
- Collect inputs.
114
+ Check if run is locally allowed.
121
115
 
122
116
  Parameters
123
117
  ----------
124
- spec : dict
125
- Run specs.
126
- project : str
127
- Project name.
118
+ run : dict
119
+ Run object dictionary.
128
120
 
129
121
  Returns
130
122
  -------
131
- dict
132
- Parameters.
123
+ None
133
124
  """
134
- LOGGER.info("Getting inputs.")
135
- self.tmp_path.mkdir(parents=True, exist_ok=True)
136
- return get_inputs_parameters(
137
- spec.get("inputs", {}),
138
- spec.get("parameters", {}),
139
- self.tmp_path,
140
- )
125
+ task_kind = run["spec"]["task"].split(":")[0]
126
+ local_execution = run["spec"]["local_execution"]
127
+ if task_kind != "python+job" and local_execution:
128
+ msg = f"Local execution not allowed for task kind {task_kind}."
129
+ LOGGER.exception(msg)
130
+ raise RuntimeError(msg)
141
131
 
142
132
  ####################
143
133
  # Configuration
@@ -162,3 +152,26 @@ class RuntimePython(Runtime):
162
152
  spec.get("source", {}),
163
153
  )
164
154
  return fnc, hasattr(fnc, "__wrapped__")
155
+
156
+ def _compose_args(self, func: Callable, spec: dict, project: str) -> dict:
157
+ """
158
+ Collect inputs.
159
+
160
+ Parameters
161
+ ----------
162
+ func : Callable
163
+ Function to execute.
164
+ spec : dict
165
+ Run specs.
166
+ project : str
167
+ Project name.
168
+
169
+ Returns
170
+ -------
171
+ dict
172
+ Parameters.
173
+ """
174
+ inputs = spec.get("inputs", {})
175
+ parameters = spec.get("parameters", {})
176
+ local_execution = spec.get("local_execution")
177
+ return compose_inputs(inputs, parameters, local_execution, func, project)
@@ -43,6 +43,35 @@ def get_function_from_source(path: Path, source_spec: dict) -> Callable:
43
43
  raise RuntimeError(msg) from e
44
44
 
45
45
 
46
+ def get_init_function(path: Path, source_spec: dict) -> Callable:
47
+ """
48
+ Get function from source.
49
+
50
+ Parameters
51
+ ----------
52
+ path : Path
53
+ Path where to save the function source.
54
+ source_spec : dict
55
+ Funcrion source spec.
56
+
57
+ Returns
58
+ -------
59
+ Callable
60
+ Function.
61
+ """
62
+ try:
63
+ if "init_function" not in source_spec:
64
+ return
65
+ function_code = save_function_source(path, source_spec)
66
+ handler_path, _ = parse_handler(source_spec["handler"])
67
+ function_path = (function_code / handler_path).with_suffix(".py")
68
+ return import_function(function_path, source_spec["init_function"])
69
+ except Exception as e:
70
+ msg = f"Some error occurred while getting init function. Exception: {e.__class__}. Error: {e.args}"
71
+ LOGGER.exception(msg)
72
+ raise RuntimeError(msg) from e
73
+
74
+
46
75
  def parse_handler(handler: str) -> tuple:
47
76
  """
48
77
  Parse handler.
@@ -0,0 +1,3 @@
1
+ import os
2
+
3
+ S3_BUCKET = os.getenv("S3_BUCKET_NAME")