digitalhub-runtime-python 0.14.2__tar.gz → 0.15.0b1__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 (87) hide show
  1. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/.github/workflows/release.yml +1 -1
  2. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/.github/workflows/run_local_test.yml +1 -1
  3. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/PKG-INFO +7 -5
  4. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/__init__.py +1 -1
  5. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/function/python/builder.py +4 -6
  6. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/function/python/entity.py +10 -0
  7. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/function/python/models.py +1 -1
  8. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/function/python/spec.py +3 -3
  9. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/function/python/utils.py +58 -0
  10. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/_base/entity.py +0 -44
  11. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/_base/spec.py +12 -23
  12. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/job/entity.py +33 -0
  13. digitalhub_runtime_python-0.15.0b1/digitalhub_runtime_python/entities/run/serve/entity.py +86 -0
  14. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/build/spec.py +1 -11
  15. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/serve/spec.py +3 -13
  16. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/runtimes/runtime.py +3 -3
  17. digitalhub_runtime_python-0.15.0b1/digitalhub_runtime_python/utils/configuration.py +345 -0
  18. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/utils/inputs.py +6 -6
  19. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/utils/outputs.py +12 -21
  20. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/utils/utils.py +36 -0
  21. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/pyproject.toml +10 -8
  22. digitalhub_runtime_python-0.14.2/digitalhub_runtime_python/entities/run/serve/entity.py +0 -36
  23. digitalhub_runtime_python-0.14.2/digitalhub_runtime_python/utils/configuration.py +0 -212
  24. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/.github/scripts/bump.sh +0 -0
  25. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/.github/scripts/changelog.sh +0 -0
  26. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/.github/scripts/cliff.toml +0 -0
  27. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/.github/workflows/test_release.yml +0 -0
  28. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/.gitignore +0 -0
  29. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/AUTHORS +0 -0
  30. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/CONTRIBUTING +0 -0
  31. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/COPYRIGHT +0 -0
  32. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/LICENSE +0 -0
  33. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/README.md +0 -0
  34. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/__init__.py +0 -0
  35. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/_base/__init__.py +0 -0
  36. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/_base/runtime_entity/__init__.py +0 -0
  37. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/_base/runtime_entity/builder.py +0 -0
  38. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/_commons/__init__.py +0 -0
  39. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/_commons/enums.py +0 -0
  40. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/function/__init__.py +0 -0
  41. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/function/python/__init__.py +0 -0
  42. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/function/python/status.py +0 -0
  43. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/__init__.py +0 -0
  44. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/_base/__init__.py +0 -0
  45. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/_base/builder.py +0 -0
  46. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/_base/status.py +0 -0
  47. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/_base/utils.py +0 -0
  48. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/build/__init__.py +0 -0
  49. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/build/builder.py +0 -0
  50. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/build/entity.py +0 -0
  51. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/build/spec.py +0 -0
  52. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/build/status.py +0 -0
  53. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/job/__init__.py +0 -0
  54. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/job/builder.py +0 -0
  55. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/job/spec.py +0 -0
  56. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/job/status.py +0 -0
  57. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/serve/__init__.py +0 -0
  58. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/serve/builder.py +0 -0
  59. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/serve/spec.py +0 -0
  60. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/run/serve/status.py +0 -0
  61. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/__init__.py +0 -0
  62. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/build/__init__.py +0 -0
  63. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/build/builder.py +0 -0
  64. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/build/entity.py +0 -0
  65. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/build/status.py +0 -0
  66. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/job/__init__.py +0 -0
  67. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/job/builder.py +0 -0
  68. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/job/entity.py +0 -0
  69. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/job/models.py +0 -0
  70. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/job/spec.py +0 -0
  71. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/job/status.py +0 -0
  72. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/serve/__init__.py +0 -0
  73. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/serve/builder.py +0 -0
  74. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/serve/entity.py +0 -0
  75. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/entities/task/serve/status.py +0 -0
  76. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/runtimes/__init__.py +0 -0
  77. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/digitalhub_runtime_python/runtimes/builder.py +0 -0
  78. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/function/function-python-git.json +0 -0
  79. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/function/function-python-local.json +0 -0
  80. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/function/function-python-zip.json +0 -0
  81. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/run/run-python+build:run.json +0 -0
  82. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/run/run-python+job:run.json +0 -0
  83. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/run/run-python+serve:run.json +0 -0
  84. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/task/task-python+build.json +0 -0
  85. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/task/task-python+job.json +0 -0
  86. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/entities/task/task-python+serve.json +0 -0
  87. {digitalhub_runtime_python-0.14.2 → digitalhub_runtime_python-0.15.0b1}/test/instances/test_validate.py +0 -0
@@ -132,7 +132,7 @@ jobs:
132
132
  branch=${{ github.ref }}
133
133
 
134
134
  # Define the repositories to trigger
135
- repos=("digitalhub-sdk-wrapper-kfp" "digitalhub-serverless" "digitalhub-sdk-wrapper-hera")
135
+ repos=( "digitalhub-tests" "digitalhub-serverless" "digitalhub-sdk-wrapper-hera")
136
136
 
137
137
  # Loop over the repositories and trigger the workflow
138
138
  for repo in "${repos[@]}"; do
@@ -7,7 +7,7 @@ jobs:
7
7
  runs-on: ubuntu-latest
8
8
  strategy:
9
9
  matrix:
10
- python-version: ["3.9", "3.10", "3.11", "3.12"]
10
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
11
11
 
12
12
  steps:
13
13
  - uses: actions/checkout@v4
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalhub-runtime-python
3
- Version: 0.14.2
3
+ Version: 0.15.0b1
4
4
  Summary: Python runtime for DHCore
5
5
  Project-URL: Homepage, https://github.com/scc-digitalhub/digitalhub-sdk-runtime-python
6
6
  Author-email: Fondazione Bruno Kessler <digitalhub@fbk.eu>, Matteo Martini <mmartini@fbk.eu>
@@ -209,15 +209,17 @@ License-File: AUTHORS
209
209
  License-File: LICENSE
210
210
  Keywords: data,dataops,kubernetes
211
211
  Classifier: License :: OSI Approved :: Apache Software License
212
- Classifier: Programming Language :: Python :: 3.9
213
212
  Classifier: Programming Language :: Python :: 3.10
214
213
  Classifier: Programming Language :: Python :: 3.11
215
214
  Classifier: Programming Language :: Python :: 3.12
216
- Requires-Python: <3.13,>=3.9
217
- Requires-Dist: digitalhub[full]<0.15,>=0.14.0
215
+ Classifier: Programming Language :: Python :: 3.13
216
+ Requires-Python: <3.14,>=3.10
217
+ Requires-Dist: digitalhub[full]<0.16,>=0.15.0b
218
+ Requires-Dist: msgpack
218
219
  Requires-Dist: nuclio-sdk
220
+ Requires-Dist: pip
219
221
  Provides-Extra: dev
220
- Requires-Dist: digitalhub[dev]<0.15,>=0.14.0; extra == 'dev'
222
+ Requires-Dist: digitalhub[dev]<0.16,>=0.15.0b; extra == 'dev'
221
223
  Description-Content-Type: text/markdown
222
224
 
223
225
  # DigitalHub SDK Runtime Python
@@ -9,7 +9,7 @@ from digitalhub_runtime_python.entities.run.serve.builder import RunPythonRunSer
9
9
  from digitalhub_runtime_python.entities.task.build.builder import TaskPythonBuildBuilder
10
10
  from digitalhub_runtime_python.entities.task.job.builder import TaskPythonJobBuilder
11
11
  from digitalhub_runtime_python.entities.task.serve.builder import TaskPythonServeBuilder
12
- from digitalhub_runtime_python.utils.utils import handler
12
+ from digitalhub_runtime_python.utils.utils import handler, parse_requirements
13
13
 
14
14
  entity_builders = (
15
15
  (EntityKinds.FUNCTION_PYTHON.value, FunctionPythonBuilder),
@@ -49,7 +49,7 @@ class FunctionPythonBuilder(FunctionBuilder, RuntimeEntityBuilderPython):
49
49
  )
50
50
  return source_post_check(obj)
51
51
 
52
- def from_dict(self, obj: dict, validate: bool = True) -> FunctionPython:
52
+ def from_dict(self, obj: dict) -> FunctionPython:
53
53
  """
54
54
  Create a new object from dictionary.
55
55
 
@@ -57,18 +57,16 @@ class FunctionPythonBuilder(FunctionBuilder, RuntimeEntityBuilderPython):
57
57
  ----------
58
58
  obj : dict
59
59
  Dictionary to create object from.
60
- validate : bool
61
- Flag to indicate if arguments must be validated.
62
60
 
63
61
  Returns
64
62
  -------
65
63
  FunctionPython
66
64
  Object instance.
67
65
  """
68
- entity = super().from_dict(obj, validate=validate)
66
+ entity = super().from_dict(obj)
69
67
  return source_post_check(entity)
70
68
 
71
- def _parse_dict(self, obj: dict, validate: bool = True) -> dict:
69
+ def _parse_dict(self, obj: dict) -> dict:
72
70
  """
73
71
  Get dictionary and parse it to a valid entity dictionary.
74
72
 
@@ -91,4 +89,4 @@ class FunctionPythonBuilder(FunctionBuilder, RuntimeEntityBuilderPython):
91
89
  if source:
92
90
  spec_dict["source"] = source_check(source=source)["source"]
93
91
 
94
- return super()._parse_dict(obj, validate=validate)
92
+ return super()._parse_dict(obj)
@@ -11,6 +11,8 @@ from digitalhub.utils.generic_utils import decode_base64_string
11
11
  from digitalhub.utils.io_utils import write_text
12
12
  from digitalhub.utils.uri_utils import has_local_scheme
13
13
 
14
+ from digitalhub_runtime_python.entities.function.python.utils import read_installed_packages
15
+
14
16
  if typing.TYPE_CHECKING:
15
17
  from digitalhub.entities._base.entity.metadata import Metadata
16
18
 
@@ -69,3 +71,11 @@ class FunctionPython(Function):
69
71
  return pth
70
72
 
71
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 = read_installed_packages(self.spec.requirements)
@@ -14,10 +14,10 @@ class PythonVersion(Enum):
14
14
  Python version supported.
15
15
  """
16
16
 
17
- PYTHON3_9 = "PYTHON3_9"
18
17
  PYTHON3_10 = "PYTHON3_10"
19
18
  PYTHON3_11 = "PYTHON3_11"
20
19
  PYTHON3_12 = "PYTHON3_12"
20
+ PYTHON3_13 = "PYTHON3_13"
21
21
 
22
22
 
23
23
  class Lang(Enum):
@@ -42,11 +42,11 @@ class FunctionValidatorPython(FunctionValidator):
42
42
  python_version: PythonVersion
43
43
  "Python version"
44
44
 
45
- image: str = None
45
+ image: str | None = None
46
46
  "Image where the function will be executed"
47
47
 
48
- base_image: str = None
48
+ base_image: str | None = None
49
49
  "Base image used to build the image where the function will be executed"
50
50
 
51
- requirements: list[str] = None
51
+ requirements: list[str] | None = None
52
52
  "Requirements list to be installed in the image where the function will be executed"
@@ -12,6 +12,7 @@ from digitalhub.utils.exceptions import EntityError
12
12
  from digitalhub.utils.file_utils import eval_py_type, eval_zip_type
13
13
  from digitalhub.utils.generic_utils import encode_string, read_source
14
14
  from digitalhub.utils.uri_utils import has_local_scheme
15
+ from pip._internal.operations import freeze
15
16
 
16
17
  from digitalhub_runtime_python.entities.function.python.models import Lang
17
18
 
@@ -19,6 +20,9 @@ if typing.TYPE_CHECKING:
19
20
  from digitalhub_runtime_python.entities.function.python.entity import FunctionPython
20
21
 
21
22
 
23
+ SEPARATORS = ["==", ">=", "<=", ">", "<", "~=", "!="]
24
+
25
+
22
26
  def source_check(**kwargs) -> dict:
23
27
  """
24
28
  Check source code.
@@ -156,3 +160,57 @@ def source_post_check(exec: FunctionPython) -> FunctionPython:
156
160
  exec.spec.source["handler"] = f"{Path(code_src).stem}:{exec.spec.source['handler']}"
157
161
 
158
162
  return exec
163
+
164
+
165
+ def read_installed_packages(requirements: list[str] | None = None) -> list[str] | None:
166
+ """
167
+ Read installed packages in execution context.
168
+
169
+ If requirements is provided, returns only those packages with their
170
+ versions filled in from the environment. Package names without versions
171
+ in the requirements list will have their versions added if found.
172
+
173
+ Parameters
174
+ ----------
175
+ requirements : list[str]
176
+ Optional list of package names (e.g., ['pandas', 'torch']) or
177
+ requirements with versions (e.g., ['pandas==2.0.0']).
178
+
179
+ Returns
180
+ -------
181
+ list[str]
182
+ List of installed packages in pip freeze format (e.g., ['numpy==1.24.0', 'pandas==2.0.0']).
183
+ """
184
+ if requirements is None:
185
+ return
186
+
187
+ # Build a mapping of normalized package names to their installed versions
188
+ installed_map: dict[str, str] = {}
189
+ for pkg in freeze.freeze():
190
+ # Handle different separators
191
+ for sep in SEPARATORS:
192
+ if sep in pkg:
193
+ name, version = pkg.split(sep, 1)
194
+ # Normalize package name (lowercase, replace _ with -)
195
+ installed_map[name.lower().replace("_", "-")] = f"{name}{sep}{version}"
196
+ break
197
+
198
+ result = []
199
+ for req in requirements:
200
+ # Check if requirement already has a version specifier
201
+ has_version = any(sep in req for sep in SEPARATORS)
202
+
203
+ if has_version:
204
+ # Keep as-is if version is already specified
205
+ result.append(req)
206
+ else:
207
+ # Normalize the requirement name for lookup
208
+ normalized_name = req.lower().replace("_", "-")
209
+ if normalized_name in installed_map:
210
+ # Use the installed version
211
+ result.append(installed_map[normalized_name])
212
+ else:
213
+ # Package not found in environment, keep without version
214
+ result.append(req)
215
+
216
+ return result
@@ -8,12 +8,10 @@ import time
8
8
  import typing
9
9
  from typing import Any
10
10
 
11
- import requests
12
11
  from digitalhub.entities._commons.enums import Relationship, State
13
12
  from digitalhub.entities._commons.utils import get_entity_type_from_key
14
13
  from digitalhub.entities.run._base.entity import Run
15
14
  from digitalhub.factory.entity import entity_factory
16
- from digitalhub.utils.exceptions import EntityError
17
15
  from digitalhub.utils.logger import LOGGER
18
16
 
19
17
  from digitalhub_runtime_python.entities._commons.enums import Actions
@@ -225,45 +223,3 @@ class RunPythonRun(Run):
225
223
  if self.status.results is None:
226
224
  return {}
227
225
  return self.status.results
228
-
229
- def invoke(
230
- self,
231
- method: str = "POST",
232
- url: str | None = None,
233
- **kwargs,
234
- ) -> requests.Response:
235
- """
236
- Invoke run.
237
-
238
- Parameters
239
- ----------
240
- method : str
241
- Method of the request.
242
- url : str
243
- URL of the request.
244
- **kwargs : dict
245
- Keyword arguments to pass to the request.
246
-
247
- Returns
248
- -------
249
- requests.Response
250
- Response from service.
251
- """
252
- try:
253
- base_url: str = self.status.service.get("url")
254
- except AttributeError:
255
- raise EntityError(
256
- "Url not specified and service not found on run status."
257
- " If a service is deploying, use run.wait() or try again later."
258
- )
259
-
260
- if url is not None and not url.removeprefix("http://").removeprefix("https://").startswith(base_url):
261
- raise EntityError(f"Invalid URL: {url}. It must start with the service URL: {base_url}")
262
-
263
- if url is None:
264
- url = f"http://{base_url}"
265
-
266
- if "data" not in kwargs and "json" not in kwargs:
267
- method = "GET"
268
-
269
- return requests.request(method=method, url=url, **kwargs)
@@ -16,16 +16,11 @@ class RunSpecPythonRun(RunSpec):
16
16
  local_execution: bool = False,
17
17
  function: str | None = None,
18
18
  workflow: str | None = None,
19
- node_selector: list[dict] | None = None,
20
19
  volumes: list[dict] | None = None,
21
20
  resources: dict | None = None,
22
- affinity: dict | None = None,
23
- tolerations: list[dict] | None = None,
24
21
  envs: list[dict] | None = None,
25
22
  secrets: list[str] | None = None,
26
23
  profile: str | None = None,
27
- runtime_class: str | None = None,
28
- priority_class: str | None = None,
29
24
  source: dict | None = None,
30
25
  image: str | None = None,
31
26
  base_image: str | None = None,
@@ -45,16 +40,11 @@ class RunSpecPythonRun(RunSpec):
45
40
  local_execution,
46
41
  function,
47
42
  workflow,
48
- node_selector,
49
43
  volumes,
50
44
  resources,
51
- affinity,
52
- tolerations,
53
45
  envs,
54
46
  secrets,
55
47
  profile,
56
- runtime_class,
57
- priority_class,
58
48
  **kwargs,
59
49
  )
60
50
  self.source = source
@@ -62,7 +52,6 @@ class RunSpecPythonRun(RunSpec):
62
52
  self.base_image = base_image
63
53
  self.python_version = python_version
64
54
  self.requirements = requirements
65
-
66
55
  self.service_type = service_type
67
56
  self.service_name = service_name
68
57
  self.replicas = replicas
@@ -76,26 +65,26 @@ class RunValidatorPythonRun(RunValidator):
76
65
  """RunValidatorPythonRun validator."""
77
66
 
78
67
  # Function parameters
79
- source: dict = None
80
- image: str = None
81
- base_image: str = None
82
- python_version: str = None
83
- requirements: list = None
68
+ source: dict | None = None
69
+ image: str | None = None
70
+ base_image: str | None = None
71
+ python_version: str | None = None
72
+ requirements: list | None = None
84
73
 
85
74
  # Task serve
86
- service_type: str = None
87
- service_name: str = None
88
- replicas: int = None
75
+ service_type: str | None = None
76
+ service_name: str | None = None
77
+ replicas: int | None = None
89
78
 
90
79
  # Task build
91
- instructions: list[str] = None
80
+ instructions: list[str] | None = None
92
81
 
93
82
  # Run parameters
94
- inputs: dict = None
83
+ inputs: dict | None = None
95
84
  """Run inputs."""
96
85
 
97
- parameters: dict = None
86
+ parameters: dict | None = None
98
87
  """Run parameters."""
99
88
 
100
- init_parameters: dict = None
89
+ init_parameters: dict | None = None
101
90
  """Init function parameters."""
@@ -34,3 +34,36 @@ class RunPythonRunJob(RunPythonRun):
34
34
 
35
35
  self.spec: RunSpecPythonRunJob
36
36
  self.status: RunStatusPythonRunJob
37
+
38
+ def add_output(self, name: str, value: str) -> None:
39
+ """
40
+ Add an output to the run job.
41
+
42
+ Parameters
43
+ ----------
44
+ name : str
45
+ The name of the output.
46
+ value : str
47
+ The value of the output.
48
+ """
49
+ if self.status.outputs is None:
50
+ self.status.outputs = {}
51
+ self.status.outputs[name] = value
52
+
53
+ def set_status(self, status: dict) -> None:
54
+ """
55
+ Patch to merge outputs when updating status.
56
+
57
+ Parameters
58
+ ----------
59
+ status : dict
60
+ The status dictionary to update.
61
+ """
62
+ if self.status.outputs is None:
63
+ self.status.outputs = {}
64
+ if "outputs" in status:
65
+ status["outputs"] = {
66
+ **self.status.outputs,
67
+ **status["outputs"],
68
+ }
69
+ return super().set_status(status)
@@ -0,0 +1,86 @@
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
+ import requests
10
+ from digitalhub.utils.exceptions import EntityError
11
+
12
+ from digitalhub_runtime_python.entities.run._base.entity import RunPythonRun
13
+
14
+ if typing.TYPE_CHECKING:
15
+ from digitalhub.entities._base.entity.metadata import Metadata
16
+
17
+ from digitalhub_runtime_python.entities.run.serve.spec import RunSpecPythonRunServe
18
+ from digitalhub_runtime_python.entities.run.serve.status import RunStatusPythonRunServe
19
+
20
+
21
+ class RunPythonRunServe(RunPythonRun):
22
+ """
23
+ RunPythonRunServe class.
24
+ """
25
+
26
+ def __init__(
27
+ self,
28
+ project: str,
29
+ uuid: str,
30
+ kind: str,
31
+ metadata: Metadata,
32
+ spec: RunSpecPythonRunServe,
33
+ status: RunStatusPythonRunServe,
34
+ user: str | None = None,
35
+ ) -> None:
36
+ super().__init__(project, uuid, kind, metadata, spec, status, user)
37
+
38
+ self.spec: RunSpecPythonRunServe
39
+ self.status: RunStatusPythonRunServe
40
+
41
+ def invoke(
42
+ self,
43
+ method: str = "POST",
44
+ url: str | None = None,
45
+ **kwargs,
46
+ ) -> requests.Response:
47
+ """
48
+ Invoke run service endpoint. It uses the service URL from the run
49
+ status if no URL is specified.
50
+ The method defaults to "POST" if data or json is provided in kwargs,
51
+ otherwise it defaults to "GET". The function returns a requests.Response
52
+ object.
53
+
54
+ Parameters
55
+ ----------
56
+ method : str
57
+ Method of the request (e.g., "GET", "POST").
58
+ url : str
59
+ URL to invoke. If specified, it must start with the service URL
60
+ (http:// or https:// prefixes are required and stripped before comparison).
61
+ **kwargs : dict
62
+ Keyword arguments to pass to the request.
63
+
64
+ Returns
65
+ -------
66
+ requests.Response
67
+ Response from service.
68
+ """
69
+ try:
70
+ base_url: str = self.status.service.get("url")
71
+ except AttributeError:
72
+ raise EntityError(
73
+ "Url not specified and service not found on run status."
74
+ " If a service is deploying, use run.wait() or try again later."
75
+ )
76
+
77
+ if url is not None and not url.removeprefix("http://").removeprefix("https://").startswith(base_url):
78
+ raise EntityError(f"Invalid URL: {url}. It must start with the service URL: {base_url}")
79
+
80
+ if url is None:
81
+ url = f"http://{base_url}"
82
+
83
+ if "data" not in kwargs and "json" not in kwargs:
84
+ method = "GET"
85
+
86
+ return requests.request(method=method, url=url, **kwargs)
@@ -13,31 +13,21 @@ class TaskSpecPythonBuild(TaskSpecFunction):
13
13
  def __init__(
14
14
  self,
15
15
  function: str,
16
- node_selector: list[dict] | None = None,
17
16
  volumes: list[dict] | None = None,
18
17
  resources: dict | None = None,
19
- affinity: dict | None = None,
20
- tolerations: list[dict] | None = None,
21
18
  envs: list[dict] | None = None,
22
19
  secrets: list[str] | None = None,
23
20
  profile: str | None = None,
24
- runtime_class: str | None = None,
25
- priority_class: str | None = None,
26
21
  instructions: list | None = None,
27
22
  **kwargs,
28
23
  ) -> None:
29
24
  super().__init__(
30
25
  function,
31
- node_selector,
32
26
  volumes,
33
27
  resources,
34
- affinity,
35
- tolerations,
36
28
  envs,
37
29
  secrets,
38
30
  profile,
39
- runtime_class,
40
- priority_class,
41
31
  **kwargs,
42
32
  )
43
33
  self.instructions = instructions
@@ -48,5 +38,5 @@ class TaskValidatorPythonBuild(TaskValidatorFunction):
48
38
  TaskValidatorPythonBuild validator.
49
39
  """
50
40
 
51
- instructions: list[str] = None
41
+ instructions: list[str] | None = None
52
42
  """Build instructions."""
@@ -15,16 +15,11 @@ class TaskSpecPythonServe(TaskSpecFunction):
15
15
  def __init__(
16
16
  self,
17
17
  function: str,
18
- node_selector: list[dict] | None = None,
19
18
  volumes: list[dict] | None = None,
20
19
  resources: dict | None = None,
21
- affinity: dict | None = None,
22
- tolerations: list[dict] | None = None,
23
20
  envs: list[dict] | None = None,
24
21
  secrets: list[str] | None = None,
25
22
  profile: str | None = None,
26
- runtime_class: str | None = None,
27
- priority_class: str | None = None,
28
23
  replicas: int | None = None,
29
24
  service_type: str | None = None,
30
25
  service_name: str | None = None,
@@ -32,16 +27,11 @@ class TaskSpecPythonServe(TaskSpecFunction):
32
27
  ) -> None:
33
28
  super().__init__(
34
29
  function,
35
- node_selector,
36
30
  volumes,
37
31
  resources,
38
- affinity,
39
- tolerations,
40
32
  envs,
41
33
  secrets,
42
34
  profile,
43
- runtime_class,
44
- priority_class,
45
35
  **kwargs,
46
36
  )
47
37
  self.replicas = replicas
@@ -54,11 +44,11 @@ class TaskValidatorPythonServe(TaskValidatorFunction):
54
44
  TaskValidatorPythonServe validator.
55
45
  """
56
46
 
57
- replicas: int = Field(default=None, ge=1)
47
+ replicas: int | None = Field(default=None, ge=1)
58
48
  """Number of replicas."""
59
49
 
60
- service_type: CoreServiceType = None
50
+ service_type: CoreServiceType | None = None
61
51
  """Service type."""
62
52
 
63
- service_name: str = None
53
+ service_name: str | None = None
64
54
  """Service name."""
@@ -13,7 +13,7 @@ from digitalhub.utils.logger import LOGGER
13
13
  from digitalhub_runtime_python.entities._commons.enums import EntityKinds
14
14
  from digitalhub_runtime_python.utils.configuration import import_function_from_source
15
15
  from digitalhub_runtime_python.utils.inputs import compose_inputs
16
- from digitalhub_runtime_python.utils.outputs import build_status, parse_outputs
16
+ from digitalhub_runtime_python.utils.outputs import build_new_status, parse_outputs
17
17
 
18
18
 
19
19
  class RuntimePython(Runtime):
@@ -83,9 +83,9 @@ class RuntimePython(Runtime):
83
83
  else:
84
84
  exec_result = self._execute(fnc, **fnc_args)
85
85
  LOGGER.info("Collecting outputs.")
86
- results = parse_outputs(exec_result, list(spec.get("outputs", {})), project, run_key)
86
+ results = parse_outputs(exec_result, project, run_key)
87
87
 
88
- status = build_status(results, spec.get("outputs"))
88
+ status = build_new_status(project, results)
89
89
 
90
90
  # Return run status
91
91
  LOGGER.info("Task completed, returning run status.")