ocean-runner 0.2.12__py3-none-any.whl → 0.2.13__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/runner.py +66 -31
- {ocean_runner-0.2.12.dist-info → ocean_runner-0.2.13.dist-info}/METADATA +1 -1
- ocean_runner-0.2.13.dist-info/RECORD +7 -0
- ocean_runner-0.2.12.dist-info/RECORD +0 -7
- {ocean_runner-0.2.12.dist-info → ocean_runner-0.2.13.dist-info}/WHEEL +0 -0
- {ocean_runner-0.2.12.dist-info → ocean_runner-0.2.13.dist-info}/licenses/LICENSE +0 -0
ocean_runner/runner.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import inspect
|
|
3
4
|
from dataclasses import InitVar, asdict, dataclass, field
|
|
4
5
|
from logging import Logger
|
|
5
6
|
from pathlib import Path
|
|
@@ -9,9 +10,7 @@ from oceanprotocol_job_details import JobDetails
|
|
|
9
10
|
|
|
10
11
|
from ocean_runner.config import Config
|
|
11
12
|
|
|
12
|
-
JobDetailsT = TypeVar(
|
|
13
|
-
"JobDetailsT",
|
|
14
|
-
)
|
|
13
|
+
JobDetailsT = TypeVar("JobDetailsT")
|
|
15
14
|
ResultT = TypeVar("ResultT")
|
|
16
15
|
|
|
17
16
|
|
|
@@ -21,14 +20,12 @@ def default_error_callback(_: Algorithm, e: Exception) -> None:
|
|
|
21
20
|
|
|
22
21
|
def default_validation(algorithm: Algorithm) -> None:
|
|
23
22
|
algorithm.logger.info("Validating input using default validation")
|
|
24
|
-
|
|
25
23
|
assert algorithm.job_details.ddos, "DDOs missing"
|
|
26
24
|
assert algorithm.job_details.files, "Files missing"
|
|
27
25
|
|
|
28
26
|
|
|
29
27
|
def default_save(*, result: ResultT, base: Path, algorithm: Algorithm) -> None:
|
|
30
28
|
algorithm.logger.info("Saving results using default save")
|
|
31
|
-
|
|
32
29
|
with open(base / "result.txt", "w+") as f:
|
|
33
30
|
f.write(str(result))
|
|
34
31
|
|
|
@@ -37,21 +34,26 @@ def default_save(*, result: ResultT, base: Path, algorithm: Algorithm) -> None:
|
|
|
37
34
|
class Algorithm(Generic[JobDetailsT, ResultT]):
|
|
38
35
|
|
|
39
36
|
config: InitVar[Config | None] = None
|
|
40
|
-
|
|
41
|
-
# Load from config
|
|
42
37
|
logger: Logger = field(init=False)
|
|
43
|
-
|
|
44
38
|
_job_details: JobDetails[JobDetailsT] = field(init=False)
|
|
45
39
|
_result: ResultT | None = field(default=None, init=False)
|
|
46
|
-
|
|
47
40
|
error_callback = default_error_callback
|
|
48
41
|
|
|
49
42
|
def __post_init__(self, config: Config | None) -> None:
|
|
50
43
|
config: Config = config or Config()
|
|
51
|
-
|
|
52
44
|
if config.error_callback:
|
|
53
45
|
self.error_callback = config.error_callback
|
|
54
46
|
|
|
47
|
+
self._setup_logger(config)
|
|
48
|
+
self._load_job_details(config)
|
|
49
|
+
self._load_user_defined_functions()
|
|
50
|
+
self._maybe_autorun(config)
|
|
51
|
+
|
|
52
|
+
# ---------------------
|
|
53
|
+
# Setup helpers
|
|
54
|
+
# ---------------------
|
|
55
|
+
|
|
56
|
+
def _setup_logger(self, config: Config) -> None:
|
|
55
57
|
if config.logger:
|
|
56
58
|
self.logger = config.logger
|
|
57
59
|
else:
|
|
@@ -62,12 +64,11 @@ class Algorithm(Generic[JobDetailsT, ResultT]):
|
|
|
62
64
|
format="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
|
|
63
65
|
datefmt="%Y-%m-%d %H:%M:%S",
|
|
64
66
|
)
|
|
65
|
-
|
|
66
67
|
self.logger = logging.getLogger("ocean_runner")
|
|
67
68
|
|
|
69
|
+
def _load_job_details(self, config: Config) -> None:
|
|
68
70
|
if isinstance(config.environment.base_dir, str):
|
|
69
71
|
config.environment.base_dir = Path(config.environment.base_dir)
|
|
70
|
-
|
|
71
72
|
if config.source_paths:
|
|
72
73
|
import sys
|
|
73
74
|
|
|
@@ -81,11 +82,49 @@ class Algorithm(Generic[JobDetailsT, ResultT]):
|
|
|
81
82
|
transformation_did=config.environment.transformation_did,
|
|
82
83
|
secret=config.environment.secret,
|
|
83
84
|
)
|
|
84
|
-
|
|
85
85
|
self.logger.info("Loaded JobDetails")
|
|
86
86
|
self.logger.debug(asdict(self.job_details))
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
# ---------------------
|
|
89
|
+
# Auto-detect functions
|
|
90
|
+
# ---------------------
|
|
91
|
+
|
|
92
|
+
def _load_user_defined_functions(self) -> None:
|
|
93
|
+
caller = inspect.getmodule(inspect.stack()[2][0])
|
|
94
|
+
if not caller:
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
for name, default in {
|
|
98
|
+
"validation": default_validation,
|
|
99
|
+
"run": None,
|
|
100
|
+
"save": default_save,
|
|
101
|
+
}.items():
|
|
102
|
+
fn = getattr(caller, name, None)
|
|
103
|
+
if callable(fn):
|
|
104
|
+
self.logger.debug(f"Found user-defined '{name}' function")
|
|
105
|
+
setattr(self, f"_user_{name}", fn)
|
|
106
|
+
elif default:
|
|
107
|
+
setattr(self, f"_user_{name}", default)
|
|
108
|
+
|
|
109
|
+
self._caller_module = caller
|
|
110
|
+
|
|
111
|
+
# ---------------------
|
|
112
|
+
# Auto-run logic
|
|
113
|
+
# ---------------------
|
|
114
|
+
|
|
115
|
+
def _maybe_autorun(self, config) -> None:
|
|
116
|
+
"""Automatically runs if caller has __ocean_runner_autorun__ = True"""
|
|
117
|
+
if (
|
|
118
|
+
getattr(self, "_caller_module", None)
|
|
119
|
+
and getattr(self._caller_module, "__ocean_runner_autorun__", False)
|
|
120
|
+
and not getattr(config, "_from_test", False)
|
|
121
|
+
):
|
|
122
|
+
self.logger.info("Auto-running algorithm...")
|
|
123
|
+
self.validate().run().save_results()
|
|
124
|
+
|
|
125
|
+
# ---------------------
|
|
126
|
+
# Main API
|
|
127
|
+
# ---------------------
|
|
89
128
|
|
|
90
129
|
@property
|
|
91
130
|
def job_details(self) -> JobDetails:
|
|
@@ -99,45 +138,41 @@ class Algorithm(Generic[JobDetailsT, ResultT]):
|
|
|
99
138
|
raise Algorithm.Error("Result missing, run the algorithm first")
|
|
100
139
|
return self._result
|
|
101
140
|
|
|
102
|
-
def validate(
|
|
103
|
-
self,
|
|
104
|
-
callback: Callable[[Self], None] = default_validation,
|
|
105
|
-
) -> Self:
|
|
141
|
+
def validate(self, callback: Callable[[Self], None] | None = None) -> Self:
|
|
142
|
+
callback = callback or getattr(self, "_user_validation", default_validation)
|
|
106
143
|
self.logger.info("Validating instance...")
|
|
107
144
|
try:
|
|
108
145
|
callback(self)
|
|
109
146
|
except Exception as e:
|
|
110
147
|
self.error_callback(e)
|
|
111
|
-
|
|
112
148
|
return self
|
|
113
149
|
|
|
114
|
-
def run(
|
|
115
|
-
self,
|
|
116
|
-
|
|
117
|
-
|
|
150
|
+
def run(self, callback: Callable[[Self], ResultT] | None = None) -> Self:
|
|
151
|
+
callback = callback or getattr(self, "_user_run", None)
|
|
152
|
+
if callback is None:
|
|
153
|
+
raise Algorithm.Error("No 'run' function found")
|
|
118
154
|
self.logger.info("Running algorithm...")
|
|
119
155
|
try:
|
|
120
|
-
self._result =
|
|
156
|
+
self._result = callback(self)
|
|
121
157
|
except Exception as e:
|
|
122
158
|
self.error_callback(e)
|
|
123
|
-
|
|
124
159
|
return self
|
|
125
160
|
|
|
126
161
|
def save_results(
|
|
127
162
|
self,
|
|
128
|
-
|
|
163
|
+
callback: Callable[[ResultT, Path, Algorithm], None] | None = None,
|
|
129
164
|
*,
|
|
130
165
|
override_path: Path | None = None,
|
|
131
166
|
) -> None:
|
|
167
|
+
callback = callback or getattr(self, "_user_save", default_save)
|
|
132
168
|
self.logger.info("Saving results...")
|
|
133
169
|
try:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
170
|
+
callback(
|
|
171
|
+
result=self.result,
|
|
172
|
+
base=override_path or self.job_details.paths.outputs,
|
|
137
173
|
algorithm=self,
|
|
138
174
|
)
|
|
139
175
|
except Exception as e:
|
|
140
176
|
self.error_callback(e)
|
|
141
177
|
|
|
142
|
-
|
|
143
|
-
__all__ = [Algorithm]
|
|
178
|
+
class Error(RuntimeError): ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ocean-runner
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.13
|
|
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
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ocean_runner/__init__.py,sha256=awAmE6kZhuwcrD3gT7qFZArdhiuzW-EFTA6tGKhw06k,138
|
|
2
|
+
ocean_runner/config.py,sha256=EgloiUTLBvca4B_pr2eNa8kHYfsyVE73ZxszLCbiDYY,1525
|
|
3
|
+
ocean_runner/runner.py,sha256=-nYH6_TtAEJ9RWv_PWmeDMyfJOhQ1tlrJrNHi7ZmYKo,5941
|
|
4
|
+
ocean_runner-0.2.13.dist-info/METADATA,sha256=orDe6w9hnST2HI33Ta3rU2-kUg9ulFSq9mQhLOhuVxI,5919
|
|
5
|
+
ocean_runner-0.2.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
+
ocean_runner-0.2.13.dist-info/licenses/LICENSE,sha256=_B25KqK4amoADWkMN150tnZFm_Fy7VvZpvIC8ZydWdI,1053
|
|
7
|
+
ocean_runner-0.2.13.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
ocean_runner/__init__.py,sha256=awAmE6kZhuwcrD3gT7qFZArdhiuzW-EFTA6tGKhw06k,138
|
|
2
|
-
ocean_runner/config.py,sha256=EgloiUTLBvca4B_pr2eNa8kHYfsyVE73ZxszLCbiDYY,1525
|
|
3
|
-
ocean_runner/runner.py,sha256=LXkVNYsqELsXciI8T8RWtfbNpI-_kUAtW1aQzsnOAfU,4075
|
|
4
|
-
ocean_runner-0.2.12.dist-info/METADATA,sha256=k9dRV2nI-i3_ZJPETo2DnuDzasRqx_YZhFe3pVy-20M,5919
|
|
5
|
-
ocean_runner-0.2.12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
-
ocean_runner-0.2.12.dist-info/licenses/LICENSE,sha256=_B25KqK4amoADWkMN150tnZFm_Fy7VvZpvIC8ZydWdI,1053
|
|
7
|
-
ocean_runner-0.2.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|