ocean-runner 0.2.19__py3-none-any.whl → 0.2.23__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.
ocean_runner/config.py CHANGED
@@ -27,8 +27,8 @@ class Environment(BaseSettings):
27
27
  description="Base data directory, defaults to '/data'",
28
28
  )
29
29
 
30
- dids: str | list[Path] | None = Field(
31
- default=None,
30
+ dids: list[Path] | str | None = Field(
31
+ default_factory=list,
32
32
  validation_alias=Keys.DIDS.value,
33
33
  description='Datasets DID\'s, format: ["XXXX"]',
34
34
  )
ocean_runner/py.typed ADDED
File without changes
ocean_runner/runner.py CHANGED
@@ -1,26 +1,31 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dataclasses import InitVar, asdict, dataclass, field
3
+ import asyncio
4
+ import inspect
5
+ from dataclasses import InitVar, dataclass, field
4
6
  from logging import Logger
5
7
  from pathlib import Path
6
- from typing import Callable, Generic, TypeVar
8
+ from typing import Awaitable, Callable, Generic, TypeAlias, TypeVar
7
9
 
8
- from oceanprotocol_job_details import JobDetails # type: ignore
10
+ from oceanprotocol_job_details import load_job_details, JobDetails # type: ignore
9
11
 
10
12
  from ocean_runner.config import Config
11
13
 
12
14
  InputT = TypeVar("InputT")
13
15
  ResultT = TypeVar("ResultT")
16
+ T = TypeVar("T")
14
17
 
15
- ValidateFuncT = Callable[["Algorithm"], None]
16
- RunFuncT = Callable[["Algorithm"], ResultT] | None
17
- SaveFuncT = Callable[["Algorithm", ResultT, Path], None]
18
- ErrorFuncT = Callable[["Algorithm", Exception], None]
19
18
 
19
+ Algo: TypeAlias = "Algorithm[InputT, ResultT]"
20
+ ValidateFuncT: TypeAlias = Callable[[Algo], None | Awaitable[None] | None]
21
+ RunFuncT: TypeAlias = Callable[[Algo], ResultT | Awaitable[ResultT]]
22
+ SaveFuncT: TypeAlias = Callable[[Algo, ResultT, Path], Awaitable[None] | None]
23
+ ErrorFuncT: TypeAlias = Callable[[Algo, Exception], Awaitable[None] | None]
20
24
 
21
- def default_error_callback(algorithm: Algorithm, e: Exception) -> None:
25
+
26
+ def default_error_callback(algorithm: Algorithm, error: Exception) -> None:
22
27
  algorithm.logger.exception("Error during algorithm execution")
23
- raise e
28
+ raise error
24
29
 
25
30
 
26
31
  def default_validation(algorithm: Algorithm) -> None:
@@ -29,10 +34,29 @@ def default_validation(algorithm: Algorithm) -> None:
29
34
  assert algorithm.job_details.files, "Files missing"
30
35
 
31
36
 
32
- def default_save(algorithm: Algorithm, result: ResultT, base: Path) -> None:
37
+ async def default_save(algorithm: Algorithm, result: ResultT, base: Path) -> None:
38
+ import aiofiles
39
+
33
40
  algorithm.logger.info("Saving results using default save")
34
- with open(base / "result.txt", "w+") as f:
35
- f.write(str(result))
41
+ async with aiofiles.open(base / "result.txt", "w+") as f:
42
+ await f.write(str(result))
43
+
44
+
45
+ async def execute(function: Callable[..., T | Awaitable[T]], *args, **kwargs) -> T:
46
+ result = function(*args, **kwargs)
47
+
48
+ if inspect.isawaitable(result):
49
+ return await result
50
+
51
+ return result
52
+
53
+
54
+ @dataclass(slots=True)
55
+ class Functions(Generic[InputT, ResultT]):
56
+ validate: ValidateFuncT = field(default=default_validation, init=False)
57
+ run: RunFuncT | None = field(default=None, init=False)
58
+ save: SaveFuncT = field(default=default_save, init=False)
59
+ error: ErrorFuncT = field(default=default_error_callback, init=False)
36
60
 
37
61
 
38
62
  @dataclass
@@ -44,33 +68,13 @@ class Algorithm(Generic[InputT, ResultT]):
44
68
  """
45
69
 
46
70
  config: InitVar[Config[InputT] | None] = field(default=None)
47
- logger: Logger = field(init=False)
48
- _job_details: JobDetails[InputT] = field(init=False)
49
- _result: ResultT | None = field(default=None, init=False)
50
71
 
51
- # Decorator-registered callbacks
52
- _validate_fn: ValidateFuncT = field(
53
- default=default_validation,
54
- init=False,
55
- repr=False,
56
- )
72
+ logger: Logger = field(init=False, repr=False)
57
73
 
58
- _run_fn: RunFuncT = field(
59
- default=None,
60
- init=False,
61
- repr=False,
62
- )
63
-
64
- _save_fn: SaveFuncT = field(
65
- default=default_save,
66
- init=False,
67
- repr=False,
68
- )
69
-
70
- _error_callback: ErrorFuncT = field(
71
- default=default_error_callback,
72
- init=False,
73
- repr=False,
74
+ _job_details: JobDetails[InputT] = field(init=False)
75
+ _result: ResultT | None = field(default=None, init=False)
76
+ _functions: Functions[InputT, ResultT] = field(
77
+ default_factory=Functions, init=False, repr=False
74
78
  )
75
79
 
76
80
  def __post_init__(self, config: Config[InputT] | None) -> None:
@@ -127,55 +131,61 @@ class Algorithm(Generic[InputT, ResultT]):
127
131
  # ---------------------------
128
132
 
129
133
  def validate(self, fn: ValidateFuncT) -> ValidateFuncT:
130
- self._validate_fn = fn
134
+ self._functions.validate = fn
131
135
  return fn
132
136
 
133
137
  def run(self, fn: RunFuncT) -> RunFuncT:
134
- self._run_fn = fn
138
+ self._functions.run = fn
135
139
  return fn
136
140
 
137
141
  def save_results(self, fn: SaveFuncT) -> SaveFuncT:
138
- self._save_fn = fn
142
+ self._functions.save = fn
139
143
  return fn
140
144
 
141
145
  def on_error(self, fn: ErrorFuncT) -> ErrorFuncT:
142
- self._error_callback = fn
146
+ self._functions.error = fn
143
147
  return fn
144
148
 
145
149
  # ---------------------------
146
150
  # Execution Pipeline
147
151
  # ---------------------------
148
152
 
149
- def __call__(self) -> ResultT | None:
150
- """Executes the algorithm pipeline: validate → run → save_results."""
151
- # Load job details
152
- self._job_details = JobDetails.load(
153
- _type=self.configuration.custom_input,
154
- base_dir=self.configuration.environment.base_dir,
155
- dids=self.configuration.environment.dids,
156
- transformation_did=self.configuration.environment.transformation_did,
157
- secret=self.configuration.environment.secret,
153
+ async def execute(self) -> ResultT | None:
154
+ self._job_details = load_job_details(
155
+ {
156
+ "base_dir": self.configuration.environment.base_dir,
157
+ "dids": self.configuration.environment.dids or [],
158
+ "secret": self.configuration.environment.secret,
159
+ "transformation_did": self.configuration.environment.transformation_did,
160
+ },
161
+ self.configuration.custom_input,
158
162
  )
159
163
 
160
164
  self.logger.info("Loaded JobDetails")
161
- self.logger.debug(asdict(self.job_details))
165
+ self.logger.debug(self.job_details.model_dump())
162
166
 
163
167
  try:
164
- # Validation step
165
- self._validate_fn(self)
168
+ await execute(self._functions.validate, self)
166
169
 
167
- # Run step
168
- if self._run_fn:
170
+ if self._functions.run:
169
171
  self.logger.info("Running algorithm...")
170
- self._result = self._run_fn(self)
172
+ self._result = await execute(self._functions.run, self)
171
173
  else:
172
174
  self.logger.error("No run() function defined. Skipping execution.")
173
175
  self._result = None
174
176
 
175
- # Save step
176
- self._save_fn(self, self._result, self.job_details.paths.outputs)
177
+ await execute(
178
+ self._functions.save,
179
+ algorithm=self,
180
+ result=self._result,
181
+ base=self.job_details.paths.outputs,
182
+ )
177
183
 
178
184
  except Exception as e:
179
- self._error_callback(self, e)
185
+ await execute(self._functions.error, self, e)
180
186
 
181
187
  return self._result
188
+
189
+ def __call__(self) -> ResultT | None:
190
+ """Executes the algorithm pipeline: validate → run → save_results."""
191
+ return asyncio.run(self.execute())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ocean-runner
3
- Version: 0.2.19
3
+ Version: 0.2.23
4
4
  Summary: A fluent API for OceanProtocol algorithms
5
5
  Project-URL: Homepage, https://github.com/AgrospAI/ocean-runner
6
6
  Project-URL: Issues, https://github.com/AgrospAI/ocean-runner/issues
@@ -17,7 +17,8 @@ Classifier: License :: OSI Approved :: MIT License
17
17
  Classifier: Operating System :: OS Independent
18
18
  Classifier: Programming Language :: Python :: 3
19
19
  Requires-Python: >=3.10
20
- Requires-Dist: oceanprotocol-job-details>=0.2.8
20
+ Requires-Dist: aiofiles>=25.1.0
21
+ Requires-Dist: oceanprotocol-job-details>=0.3.4
21
22
  Requires-Dist: pydantic-settings>=2.12.0
22
23
  Requires-Dist: pydantic>=2.12.5
23
24
  Requires-Dist: pytest>=8.4.2
@@ -0,0 +1,8 @@
1
+ ocean_runner/__init__.py,sha256=hRyMrE7K0DEbNRa-iNwA2xFOM85JJvjeKIdiWvcOm4Y,154
2
+ ocean_runner/config.py,sha256=_P8MbKGzL36p8LO_m6nj3cPB0h6L2YL8satxUNXXnUI,1927
3
+ ocean_runner/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ ocean_runner/runner.py,sha256=0-McElMM_dzubLUbRdeDaE0WY_dNj0IN_5cGen4-4bM,6242
5
+ ocean_runner-0.2.23.dist-info/METADATA,sha256=HkaOEgMvm98GQT9VsGMSN6FwTNzzMnocGpZyKu4HgSs,6667
6
+ ocean_runner-0.2.23.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
7
+ ocean_runner-0.2.23.dist-info/licenses/LICENSE,sha256=_B25KqK4amoADWkMN150tnZFm_Fy7VvZpvIC8ZydWdI,1053
8
+ ocean_runner-0.2.23.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- ocean_runner/__init__.py,sha256=hRyMrE7K0DEbNRa-iNwA2xFOM85JJvjeKIdiWvcOm4Y,154
2
- ocean_runner/config.py,sha256=paN2I3ISIxRO1isCIuUgNsL9dsRhEc_n6KjTH6yNZU4,1919
3
- ocean_runner/runner.py,sha256=VaayC8UXn2Iyl1RuUcTap9vyTyDYkvm16p3ucaRAOhQ,5527
4
- ocean_runner-0.2.19.dist-info/METADATA,sha256=4n10dG0cfNAPraB9qJ4WcINyzJNFAxwDQtfZufbs0sU,6635
5
- ocean_runner-0.2.19.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
6
- ocean_runner-0.2.19.dist-info/licenses/LICENSE,sha256=_B25KqK4amoADWkMN150tnZFm_Fy7VvZpvIC8ZydWdI,1053
7
- ocean_runner-0.2.19.dist-info/RECORD,,