digitalhub-runtime-python 0.15.2__py3-none-any.whl → 0.16.0b1__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.
Files changed (48) hide show
  1. digitalhub_runtime_python/__init__.py +24 -0
  2. digitalhub_runtime_python/entities/_base/runtime_entity/builder.py +36 -0
  3. digitalhub_runtime_python/entities/_commons/enums.py +9 -0
  4. digitalhub_runtime_python/entities/function/hydra/__init__.py +3 -0
  5. digitalhub_runtime_python/entities/function/hydra/builder.py +92 -0
  6. digitalhub_runtime_python/entities/function/hydra/entity.py +81 -0
  7. digitalhub_runtime_python/entities/function/hydra/models.py +63 -0
  8. digitalhub_runtime_python/entities/function/hydra/spec.py +58 -0
  9. digitalhub_runtime_python/entities/function/hydra/status.py +13 -0
  10. digitalhub_runtime_python/entities/function/hydra/utils.py +221 -0
  11. digitalhub_runtime_python/entities/run/hydra_build/__init__.py +3 -0
  12. digitalhub_runtime_python/entities/run/hydra_build/builder.py +25 -0
  13. digitalhub_runtime_python/entities/run/hydra_build/entity.py +25 -0
  14. digitalhub_runtime_python/entities/run/hydra_build/spec.py +15 -0
  15. digitalhub_runtime_python/entities/run/hydra_build/status.py +13 -0
  16. digitalhub_runtime_python/entities/run/hydra_job/__init__.py +3 -0
  17. digitalhub_runtime_python/entities/run/hydra_job/builder.py +25 -0
  18. digitalhub_runtime_python/entities/run/hydra_job/entity.py +69 -0
  19. digitalhub_runtime_python/entities/run/hydra_job/spec.py +79 -0
  20. digitalhub_runtime_python/entities/run/hydra_job/status.py +13 -0
  21. digitalhub_runtime_python/entities/run/hydra_subtask/__init__.py +3 -0
  22. digitalhub_runtime_python/entities/run/hydra_subtask/builder.py +45 -0
  23. digitalhub_runtime_python/entities/run/hydra_subtask/entity.py +25 -0
  24. digitalhub_runtime_python/entities/run/hydra_subtask/spec.py +72 -0
  25. digitalhub_runtime_python/entities/run/hydra_subtask/status.py +13 -0
  26. digitalhub_runtime_python/entities/task/hydra_build/__init__.py +3 -0
  27. digitalhub_runtime_python/entities/task/hydra_build/builder.py +25 -0
  28. digitalhub_runtime_python/entities/task/hydra_build/entity.py +25 -0
  29. digitalhub_runtime_python/entities/task/hydra_build/spec.py +42 -0
  30. digitalhub_runtime_python/entities/task/hydra_build/status.py +13 -0
  31. digitalhub_runtime_python/entities/task/hydra_job/__init__.py +3 -0
  32. digitalhub_runtime_python/entities/task/hydra_job/builder.py +25 -0
  33. digitalhub_runtime_python/entities/task/hydra_job/entity.py +25 -0
  34. digitalhub_runtime_python/entities/task/hydra_job/spec.py +19 -0
  35. digitalhub_runtime_python/entities/task/hydra_job/status.py +13 -0
  36. digitalhub_runtime_python/entities/task/hydra_subtask/__init__.py +3 -0
  37. digitalhub_runtime_python/entities/task/hydra_subtask/builder.py +25 -0
  38. digitalhub_runtime_python/entities/task/hydra_subtask/entity.py +25 -0
  39. digitalhub_runtime_python/entities/task/hydra_subtask/spec.py +19 -0
  40. digitalhub_runtime_python/entities/task/hydra_subtask/status.py +13 -0
  41. digitalhub_runtime_python/runtimes/builder.py +23 -0
  42. digitalhub_runtime_python/runtimes/hydra_runtime.py +150 -0
  43. digitalhub_runtime_python/runtimes/runtime.py +3 -1
  44. {digitalhub_runtime_python-0.15.2.dist-info → digitalhub_runtime_python-0.16.0b1.dist-info}/METADATA +3 -3
  45. {digitalhub_runtime_python-0.15.2.dist-info → digitalhub_runtime_python-0.16.0b1.dist-info}/RECORD +48 -10
  46. {digitalhub_runtime_python-0.15.2.dist-info → digitalhub_runtime_python-0.16.0b1.dist-info}/WHEEL +1 -1
  47. {digitalhub_runtime_python-0.15.2.dist-info → digitalhub_runtime_python-0.16.0b1.dist-info}/licenses/AUTHORS +0 -0
  48. {digitalhub_runtime_python-0.15.2.dist-info → digitalhub_runtime_python-0.16.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -3,10 +3,14 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  from digitalhub_runtime_python.entities._commons.enums import EntityKinds
5
5
  from digitalhub_runtime_python.entities.function.guardrail.builder import FunctionGuardrailBuilder
6
+ from digitalhub_runtime_python.entities.function.hydra.builder import FunctionHydraBuilder
6
7
  from digitalhub_runtime_python.entities.function.openinference.builder import FunctionOpeninferenceBuilder
7
8
  from digitalhub_runtime_python.entities.function.python.builder import FunctionPythonBuilder
8
9
  from digitalhub_runtime_python.entities.run.guardrail_build.builder import RunGuardrailRunBuildBuilder
9
10
  from digitalhub_runtime_python.entities.run.guardrail_serve.builder import RunGuardrailRunServeBuilder
11
+ from digitalhub_runtime_python.entities.run.hydra_build.builder import RunHydraRunBuildBuilder
12
+ from digitalhub_runtime_python.entities.run.hydra_job.builder import RunHydraRunJobBuilder
13
+ from digitalhub_runtime_python.entities.run.hydra_subtask.builder import RunHydraRunSubtaskBuilder
10
14
  from digitalhub_runtime_python.entities.run.openinference_build.builder import RunOpeninferenceRunBuildBuilder
11
15
  from digitalhub_runtime_python.entities.run.openinference_serve.builder import RunOpeninferenceRunServeBuilder
12
16
  from digitalhub_runtime_python.entities.run.python_build.builder import RunPythonRunBuildBuilder
@@ -14,6 +18,9 @@ from digitalhub_runtime_python.entities.run.python_job.builder import RunPythonR
14
18
  from digitalhub_runtime_python.entities.run.python_serve.builder import RunPythonRunServeBuilder
15
19
  from digitalhub_runtime_python.entities.task.guardrail_build.builder import TaskGuardrailBuildBuilder
16
20
  from digitalhub_runtime_python.entities.task.guardrail_serve.builder import TaskGuardrailServeBuilder
21
+ from digitalhub_runtime_python.entities.task.hydra_build.builder import TaskHydraBuildBuilder
22
+ from digitalhub_runtime_python.entities.task.hydra_job.builder import TaskHydraJobBuilder
23
+ from digitalhub_runtime_python.entities.task.hydra_subtask.builder import TaskHydraSubtaskBuilder
17
24
  from digitalhub_runtime_python.entities.task.openinference_build.builder import TaskOpeninferenceBuildBuilder
18
25
  from digitalhub_runtime_python.entities.task.openinference_serve.builder import TaskOpeninferenceServeBuilder
19
26
  from digitalhub_runtime_python.entities.task.python_build.builder import TaskPythonBuildBuilder
@@ -25,6 +32,7 @@ entity_builders = (
25
32
  (EntityKinds.FUNCTION_GUARDRAIL.value, FunctionGuardrailBuilder),
26
33
  (EntityKinds.FUNCTION_OPENINFERENCE.value, FunctionOpeninferenceBuilder),
27
34
  (EntityKinds.FUNCTION_PYTHON.value, FunctionPythonBuilder),
35
+ (EntityKinds.FUNCTION_HYDRA.value, FunctionHydraBuilder),
28
36
  (EntityKinds.RUN_GUARDRAIL_BUILD.value, RunGuardrailRunBuildBuilder),
29
37
  (EntityKinds.RUN_GUARDRAIL_SERVE.value, RunGuardrailRunServeBuilder),
30
38
  (EntityKinds.RUN_OPENINFERENCE_BUILD.value, RunOpeninferenceRunBuildBuilder),
@@ -32,6 +40,9 @@ entity_builders = (
32
40
  (EntityKinds.RUN_PYTHON_BUILD.value, RunPythonRunBuildBuilder),
33
41
  (EntityKinds.RUN_PYTHON_JOB.value, RunPythonRunJobBuilder),
34
42
  (EntityKinds.RUN_PYTHON_SERVE.value, RunPythonRunServeBuilder),
43
+ (EntityKinds.RUN_HYDRA_BUILD.value, RunHydraRunBuildBuilder),
44
+ (EntityKinds.RUN_HYDRA_JOB.value, RunHydraRunJobBuilder),
45
+ (EntityKinds.RUN_HYDRA_SUBTASK.value, RunHydraRunSubtaskBuilder),
35
46
  (EntityKinds.TASK_GUARDRAIL_BUILD.value, TaskGuardrailBuildBuilder),
36
47
  (EntityKinds.TASK_GUARDRAIL_SERVE.value, TaskGuardrailServeBuilder),
37
48
  (EntityKinds.TASK_OPENINFERENCE_BUILD.value, TaskOpeninferenceBuildBuilder),
@@ -39,11 +50,17 @@ entity_builders = (
39
50
  (EntityKinds.TASK_PYTHON_BUILD.value, TaskPythonBuildBuilder),
40
51
  (EntityKinds.TASK_PYTHON_JOB.value, TaskPythonJobBuilder),
41
52
  (EntityKinds.TASK_PYTHON_SERVE.value, TaskPythonServeBuilder),
53
+ (EntityKinds.TASK_HYDRA_BUILD.value, TaskHydraBuildBuilder),
54
+ (EntityKinds.TASK_HYDRA_JOB.value, TaskHydraJobBuilder),
55
+ (EntityKinds.TASK_HYDRA_SUBTASK.value, TaskHydraSubtaskBuilder),
42
56
  )
43
57
 
44
58
  try:
45
59
  from digitalhub_runtime_python.runtimes.builder import (
46
60
  RuntimeGuardrailBuilder,
61
+ RuntimeHydraBuilder,
62
+ RuntimeHydraJobBuilder,
63
+ RuntimeHydraSubtaskBuilder,
47
64
  RuntimeOpeninferenceBuilder,
48
65
  RuntimePythonBuilder,
49
66
  RuntimePythonJobBuilder,
@@ -53,6 +70,7 @@ try:
53
70
  (EntityKinds.FUNCTION_GUARDRAIL.value, RuntimeGuardrailBuilder),
54
71
  (EntityKinds.FUNCTION_OPENINFERENCE.value, RuntimeOpeninferenceBuilder),
55
72
  (EntityKinds.FUNCTION_PYTHON.value, RuntimePythonBuilder),
73
+ (EntityKinds.FUNCTION_HYDRA.value, RuntimeHydraBuilder),
56
74
  (EntityKinds.RUN_GUARDRAIL_BUILD.value, RuntimeGuardrailBuilder),
57
75
  (EntityKinds.RUN_GUARDRAIL_SERVE.value, RuntimeGuardrailBuilder),
58
76
  (EntityKinds.RUN_OPENINFERENCE_BUILD.value, RuntimeOpeninferenceBuilder),
@@ -60,6 +78,9 @@ try:
60
78
  (EntityKinds.RUN_PYTHON_BUILD.value, RuntimePythonBuilder),
61
79
  (EntityKinds.RUN_PYTHON_JOB.value, RuntimePythonJobBuilder),
62
80
  (EntityKinds.RUN_PYTHON_SERVE.value, RuntimePythonBuilder),
81
+ (EntityKinds.RUN_HYDRA_BUILD.value, RuntimeHydraBuilder),
82
+ (EntityKinds.RUN_HYDRA_JOB.value, RuntimeHydraJobBuilder),
83
+ (EntityKinds.RUN_HYDRA_SUBTASK.value, RuntimeHydraSubtaskBuilder),
63
84
  (EntityKinds.TASK_GUARDRAIL_BUILD.value, RuntimeGuardrailBuilder),
64
85
  (EntityKinds.TASK_GUARDRAIL_SERVE.value, RuntimeGuardrailBuilder),
65
86
  (EntityKinds.TASK_OPENINFERENCE_BUILD.value, RuntimeOpeninferenceBuilder),
@@ -67,6 +88,9 @@ try:
67
88
  (EntityKinds.TASK_PYTHON_BUILD.value, RuntimePythonBuilder),
68
89
  (EntityKinds.TASK_PYTHON_JOB.value, RuntimePythonJobBuilder),
69
90
  (EntityKinds.TASK_PYTHON_SERVE.value, RuntimePythonBuilder),
91
+ (EntityKinds.TASK_HYDRA_BUILD.value, RuntimeHydraBuilder),
92
+ (EntityKinds.TASK_HYDRA_JOB.value, RuntimeHydraJobBuilder),
93
+ (EntityKinds.TASK_HYDRA_SUBTASK.value, RuntimeHydraSubtaskBuilder),
70
94
  )
71
95
  except ImportError as e:
72
96
  from digitalhub.utils.logger.logger import get_logger
@@ -100,3 +100,39 @@ class RuntimeEntityBuilderGuardrail(RuntimeEntityBuilder):
100
100
  ),
101
101
  ]
102
102
  )
103
+
104
+
105
+ class RuntimeEntityBuilderHydra(RuntimeEntityBuilder):
106
+ EXECUTABLE_KIND = EntityKinds.FUNCTION_HYDRA.value
107
+ TASKS_KINDS = map_actions(
108
+ [
109
+ (
110
+ EntityKinds.TASK_HYDRA_BUILD.value,
111
+ Actions.BUILD.value,
112
+ ),
113
+ (
114
+ EntityKinds.TASK_HYDRA_JOB.value,
115
+ Actions.JOB.value,
116
+ ),
117
+ (
118
+ EntityKinds.TASK_HYDRA_SUBTASK.value,
119
+ Actions.SUBTASK.value,
120
+ ),
121
+ ]
122
+ )
123
+ RUN_KINDS = map_actions(
124
+ [
125
+ (
126
+ EntityKinds.RUN_HYDRA_BUILD.value,
127
+ Actions.BUILD.value,
128
+ ),
129
+ (
130
+ EntityKinds.RUN_HYDRA_JOB.value,
131
+ Actions.JOB.value,
132
+ ),
133
+ (
134
+ EntityKinds.RUN_HYDRA_SUBTASK.value,
135
+ Actions.SUBTASK.value,
136
+ ),
137
+ ]
138
+ )
@@ -32,6 +32,14 @@ class EntityKinds(Enum):
32
32
  RUN_GUARDRAIL_BUILD = "guardrail+build:run"
33
33
  RUN_GUARDRAIL_SERVE = "guardrail+serve:run"
34
34
 
35
+ FUNCTION_HYDRA = "hydra"
36
+ TASK_HYDRA_BUILD = "hydra+build"
37
+ TASK_HYDRA_JOB = "hydra+job"
38
+ TASK_HYDRA_SUBTASK = "hydra+subtask"
39
+ RUN_HYDRA_BUILD = "hydra+build:run"
40
+ RUN_HYDRA_JOB = "hydra+job:run"
41
+ RUN_HYDRA_SUBTASK = "hydra+subtask:run"
42
+
35
43
 
36
44
  class Actions(Enum):
37
45
  """
@@ -41,3 +49,4 @@ class Actions(Enum):
41
49
  BUILD = "build"
42
50
  JOB = "job"
43
51
  SERVE = "serve"
52
+ SUBTASK = "subtask"
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
@@ -0,0 +1,92 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ from digitalhub.entities.function._base.builder import FunctionBuilder
8
+
9
+ from digitalhub_runtime_python.entities._base.runtime_entity.builder import RuntimeEntityBuilderHydra
10
+ from digitalhub_runtime_python.entities._commons.enums import EntityKinds
11
+ from digitalhub_runtime_python.entities.function.hydra.entity import FunctionHydra
12
+ from digitalhub_runtime_python.entities.function.hydra.spec import FunctionSpecHydra, FunctionValidatorHydra
13
+ from digitalhub_runtime_python.entities.function.hydra.status import FunctionStatusHydra
14
+ from digitalhub_runtime_python.entities.function.hydra.utils import config_check, source_check
15
+ from digitalhub_runtime_python.entities.function.python.utils import source_post_check
16
+
17
+
18
+ class FunctionHydraBuilder(FunctionBuilder, RuntimeEntityBuilderHydra):
19
+ """
20
+ FunctionHydra builder.
21
+ """
22
+
23
+ ENTITY_CLASS = FunctionHydra
24
+ ENTITY_SPEC_CLASS = FunctionSpecHydra
25
+ ENTITY_SPEC_VALIDATOR = FunctionValidatorHydra
26
+ ENTITY_STATUS_CLASS = FunctionStatusHydra
27
+ ENTITY_KIND = EntityKinds.FUNCTION_HYDRA.value
28
+
29
+ def build(
30
+ self,
31
+ kind: str,
32
+ project: str,
33
+ name: str,
34
+ uuid: str | None = None,
35
+ description: str | None = None,
36
+ labels: list[str] | None = None,
37
+ embedded: bool = False,
38
+ **kwargs,
39
+ ) -> FunctionHydra:
40
+ kwargs = source_check(**kwargs)
41
+ kwargs = config_check(**kwargs)
42
+ obj = super().build(
43
+ kind,
44
+ project,
45
+ name,
46
+ uuid,
47
+ description,
48
+ labels,
49
+ embedded,
50
+ **kwargs,
51
+ )
52
+ return source_post_check(obj)
53
+
54
+ def from_dict(self, obj: dict) -> FunctionHydra:
55
+ """
56
+ Create a new object from dictionary.
57
+
58
+ Parameters
59
+ ----------
60
+ obj : dict
61
+ Dictionary to create object from.
62
+
63
+ Returns
64
+ -------
65
+ FunctionHydra
66
+ Object instance.
67
+ """
68
+ entity = super().from_dict(obj)
69
+ return source_post_check(entity)
70
+
71
+ def _parse_dict(self, obj: dict) -> dict:
72
+ """
73
+ Get dictionary and parse it to a valid entity dictionary.
74
+
75
+ Parameters
76
+ ----------
77
+ obj : dict
78
+ Dictionary to parse.
79
+
80
+ Returns
81
+ -------
82
+ dict
83
+ A dictionary containing the attributes of the entity instance.
84
+ """
85
+ # Look for source in spec
86
+ if spec_dict := obj.get("spec", {}):
87
+ # Check source
88
+ source = spec_dict.get("source", {})
89
+ if source:
90
+ spec_dict["source"] = source_check(source=source)["source"]
91
+
92
+ return super()._parse_dict(obj)
@@ -0,0 +1,81 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ import typing
8
+
9
+ from digitalhub.entities.function._base.entity import Function
10
+ from digitalhub.utils.generic_utils import decode_base64_string
11
+ from digitalhub.utils.io_utils import write_text
12
+ from digitalhub.utils.uri_utils import has_local_scheme
13
+
14
+ from digitalhub_runtime_python.entities._commons.requirement_parser.parser import RequirementParser
15
+
16
+ if typing.TYPE_CHECKING:
17
+ from digitalhub_runtime_python.entities.function.hydra.spec import FunctionSpecHydra
18
+ from digitalhub_runtime_python.entities.function.hydra.status import FunctionStatusHydra
19
+
20
+
21
+ class FunctionHydra(Function):
22
+ """
23
+ FunctionHydra class.
24
+ """
25
+
26
+ def __init__(self, *args, **kwargs) -> None:
27
+ super().__init__(*args, **kwargs)
28
+
29
+ self.spec: FunctionSpecHydra
30
+ self.status: FunctionStatusHydra
31
+
32
+ def export(self) -> str:
33
+ """
34
+ Export object as a YAML file in the context folder.
35
+
36
+ Returns
37
+ -------
38
+ str
39
+ Exported filepath.
40
+ """
41
+ # Strip base64 from source at following conditions:
42
+ # - source is local path
43
+ # - base64 is not None
44
+
45
+ # Check source
46
+ source = self.spec.source.get("source")
47
+ if source is not None and has_local_scheme(source):
48
+ # Check base64. If it is set, decode it in a local file
49
+ # save in variable to restore on object after export
50
+ base64 = self.spec.source.pop("base64", None)
51
+ if base64 is not None:
52
+ # Write local file
53
+ src_pth = self._context().root / source
54
+ write_text(src_pth, decode_base64_string(base64))
55
+
56
+ # Export and restore base64, then return
57
+ super().export()
58
+ self.spec.source["base64"] = base64
59
+
60
+ config = self.spec.config
61
+ # Check base64. If it is set, decode it in a local file
62
+ # save in variable to restore on object after export
63
+ if config is not None:
64
+ base64 = config.pop("base64", None)
65
+ if base64 is not None:
66
+ # Write local file
67
+ config_pth = self._context().root / "config.yaml"
68
+ write_text(config_pth, decode_base64_string(base64))
69
+
70
+ # Export and restore base64, then return
71
+ self.spec.config = base64
72
+
73
+ return super().export()
74
+
75
+ def _post_create_hook_before_save(self) -> None:
76
+ """
77
+ Hook method called after the creation of the entity but before saving
78
+ in Core.
79
+ Can be overridden in subclasses to implement custom behavior.
80
+ """
81
+ self.spec.requirements = RequirementParser().parse(self.spec.requirements)
@@ -0,0 +1,63 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ from enum import Enum
8
+
9
+ from pydantic import BaseModel, ConfigDict, Field
10
+
11
+
12
+ class Lang(Enum):
13
+ """
14
+ Source code language.
15
+ """
16
+
17
+ PYTHON = "python"
18
+
19
+
20
+ class SourceValidator(BaseModel):
21
+ """
22
+ Source code params.
23
+ """
24
+
25
+ model_config = ConfigDict(use_enum_values=True)
26
+
27
+ source: str = None
28
+ "Pointer to source code."
29
+
30
+ handler: str = None
31
+ "Function entrypoint."
32
+
33
+ init_function: str = None
34
+ """Handler for init function."""
35
+
36
+ complete_function: str = None
37
+ """Handler for complete function."""
38
+
39
+ code: str = None
40
+ "Source code (plain text)."
41
+
42
+ base64: str = None
43
+ "Source code (base64 encoded)."
44
+
45
+ lang: Lang = Field(default=Lang.PYTHON.value)
46
+ "Source code language (hint)."
47
+
48
+
49
+ class ConfigValidator(BaseModel):
50
+ """
51
+ Config params.
52
+ """
53
+
54
+ model_config = ConfigDict(use_enum_values=True)
55
+
56
+ source: str = None
57
+ "Pointer to source code."
58
+
59
+ path: str = None
60
+ "Config path."
61
+
62
+ base64: str = None
63
+ "Config (base64 encoded)."
@@ -0,0 +1,58 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ from digitalhub.entities.function._base.spec import FunctionSpec, FunctionValidator
8
+
9
+ from digitalhub_runtime_python.entities.function.hydra.models import ConfigValidator, SourceValidator
10
+ from digitalhub_runtime_python.entities.function.python.models import PythonVersion
11
+
12
+
13
+ class FunctionSpecHydra(FunctionSpec):
14
+ """
15
+ FunctionSpecHydra specifications.
16
+ """
17
+
18
+ def __init__(
19
+ self,
20
+ source: dict | None = None,
21
+ config: dict | None = None,
22
+ image: str | None = None,
23
+ base_image: str | None = None,
24
+ python_version: str | None = None,
25
+ requirements: list | None = None,
26
+ ) -> None:
27
+ super().__init__()
28
+
29
+ self.image = image
30
+ self.base_image = base_image
31
+ self.python_version = python_version
32
+ self.requirements = requirements
33
+ self.source = source
34
+ self.config = config
35
+
36
+
37
+ class FunctionValidatorHydra(FunctionValidator):
38
+ """
39
+ FunctionValidatorHydra validator.
40
+ """
41
+
42
+ source: SourceValidator
43
+ """Source code validator"""
44
+
45
+ config: ConfigValidator
46
+ """Config validator"""
47
+
48
+ python_version: PythonVersion
49
+ "Python version"
50
+
51
+ image: str | None = None
52
+ "Image where the function will be executed"
53
+
54
+ base_image: str | None = None
55
+ "Base image used to build the image where the function will be executed"
56
+
57
+ requirements: list[str] | str | None = None
58
+ "Requirements list to be installed in the image where the function will be executed"
@@ -0,0 +1,13 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ from digitalhub.entities.function._base.status import FunctionStatus
8
+
9
+
10
+ class FunctionStatusHydra(FunctionStatus):
11
+ """
12
+ FunctionStatusHydra status.
13
+ """
@@ -0,0 +1,221 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ from pathlib import Path
8
+
9
+ from digitalhub.utils.exceptions import EntityError
10
+ from digitalhub.utils.generic_utils import encode_string, read_source
11
+ from digitalhub.utils.uri_utils import has_local_scheme
12
+
13
+ from digitalhub_runtime_python.entities.function.python.models import Lang
14
+
15
+
16
+ def source_check(**kwargs) -> dict:
17
+ """
18
+ Check source code.
19
+
20
+ Parameters
21
+ ----------
22
+ **kwargs
23
+ Keyword arguments.
24
+
25
+ Returns
26
+ -------
27
+ dict
28
+ Checked source.
29
+ """
30
+ source: dict = kwargs.pop("source", None)
31
+ code_src = kwargs.pop("code_src", None)
32
+ code = kwargs.pop("code", None)
33
+ base64 = kwargs.pop("base64", None)
34
+ handler = kwargs.pop("handler", None)
35
+ init_function = kwargs.pop("init_function", None)
36
+ complete_function = kwargs.pop("complete_function", None)
37
+ lang = kwargs.pop("lang", None)
38
+
39
+ if source is not None:
40
+ code_src = source.pop("source", None)
41
+ code = source.pop("code", None)
42
+ base64 = source.pop("base64", None)
43
+ handler = source.pop("handler", None)
44
+ init_function = source.pop("init_function", None)
45
+ complete_function = source.pop("complete_function", None)
46
+ lang = source.pop("lang", None)
47
+
48
+ kwargs["source"] = _check_params(
49
+ code_src=code_src,
50
+ code=code,
51
+ base64=base64,
52
+ handler=handler,
53
+ init_function=init_function,
54
+ complete_function=complete_function,
55
+ lang=lang,
56
+ )
57
+ return kwargs
58
+
59
+
60
+ def _check_params(
61
+ code_src: str | None = None,
62
+ code: str | None = None,
63
+ base64: str | None = None,
64
+ handler: str | None = None,
65
+ init_function: str | None = None,
66
+ complete_function: str | None = None,
67
+ lang: str | None = None,
68
+ ) -> dict:
69
+ """
70
+ Check source.
71
+
72
+ Parameters
73
+ ----------
74
+ code_src : str
75
+ Source code source.
76
+ code : str
77
+ Source code.
78
+ base64 : str
79
+ Source code base64.
80
+ handler : str
81
+ Function handler.
82
+ init_function : str
83
+ Init function.
84
+ complete_function : str
85
+ Complete function.
86
+ lang : str
87
+ Source code language.
88
+
89
+ Returns
90
+ -------
91
+ dict
92
+ Checked source.
93
+ """
94
+ source = {}
95
+
96
+ if handler is None:
97
+ raise EntityError("Handler must be provided.")
98
+ source["handler"] = handler
99
+
100
+ if init_function is not None:
101
+ source["init_function"] = init_function
102
+
103
+ if complete_function is not None:
104
+ source["complete_function"] = complete_function
105
+
106
+ if lang is None:
107
+ source["lang"] = Lang.PYTHON.value
108
+
109
+ if code_src is None and code is None and base64 is None:
110
+ raise EntityError("Source must be provided.")
111
+
112
+ if code_src is not None:
113
+ source["source"] = code_src
114
+
115
+ if base64 is not None:
116
+ source["base64"] = base64
117
+
118
+ if code is not None:
119
+ source["base64"] = encode_string(code)
120
+
121
+ return source
122
+
123
+
124
+ def config_check(**kwargs) -> dict:
125
+ """
126
+ Check config.
127
+
128
+ Parameters
129
+ ----------
130
+ **kwargs
131
+ Keyword arguments.
132
+
133
+ Returns
134
+ -------
135
+ dict
136
+ Checked config.
137
+ """
138
+ # either config_src or config or config_base64 may be provided
139
+ config_src = kwargs.pop("config_src", None)
140
+ config_base64 = kwargs.pop("config_base64", None)
141
+ config_content = kwargs.pop("config_content", None)
142
+ config = kwargs.pop("config", None)
143
+ config_path = kwargs.pop("config_path", None)
144
+
145
+ if config is not None:
146
+ config_src = config.pop("source", None)
147
+ config_base64 = config.pop("base64", None)
148
+ config_content = None
149
+ config_path = config.pop("path", None)
150
+
151
+ config = _check_config_params(
152
+ config_src=config_src,
153
+ config_content=config_content,
154
+ config_base64=config_base64,
155
+ path=config_path,
156
+ )
157
+
158
+ if config is not None:
159
+ kwargs["config"] = config
160
+ return kwargs
161
+
162
+ return kwargs
163
+
164
+
165
+ def _check_config_params(
166
+ config_src: str | None = None,
167
+ config_content: str | None = None,
168
+ config_base64: str | None = None,
169
+ path: str | None = None,
170
+ ) -> dict:
171
+ """
172
+ Check config.
173
+
174
+ Parameters
175
+ ----------
176
+ config_src : str
177
+ Config source.
178
+ config_content : str
179
+ Config.
180
+ config_base64 : str
181
+ Config base64.
182
+ path : str
183
+ Config path.
184
+
185
+ Returns
186
+ -------
187
+ dict
188
+ Checked config.
189
+ """
190
+ config = {}
191
+
192
+ if path is not None:
193
+ config["path"] = path
194
+
195
+ if config_src is None and config_content is None and config_base64 is None:
196
+ raise EntityError("Config must be provided.")
197
+
198
+ if config_src is not None:
199
+ # Check local source
200
+ if has_local_scheme(config_src):
201
+ path_src = Path(config_src)
202
+
203
+ if not path_src.exists():
204
+ raise EntityError(f"Source {config_src} does not exist.")
205
+
206
+ # If source is a folder, zip it and upload it
207
+ if not path_src.is_file():
208
+ raise EntityError(f"Source {config_src} should be a file.")
209
+
210
+ # If source is a file, read it and encode it in base64
211
+ config["base64"] = read_source(config_src)
212
+ else:
213
+ config["source"] = config_src
214
+
215
+ if config_base64 is not None:
216
+ config["base64"] = config_base64
217
+
218
+ if config_content is not None:
219
+ config["base64"] = encode_string(config_content)
220
+
221
+ return config
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0