ddeutil-workflow 0.0.14__py3-none-any.whl → 0.0.16__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.
- ddeutil/workflow/__about__.py +1 -1
- ddeutil/workflow/__types.py +58 -13
- ddeutil/workflow/api.py +3 -4
- ddeutil/workflow/cli.py +2 -5
- ddeutil/workflow/conf.py +280 -3
- ddeutil/workflow/job.py +44 -25
- ddeutil/workflow/log.py +5 -8
- ddeutil/workflow/on.py +1 -1
- ddeutil/workflow/repeat.py +2 -5
- ddeutil/workflow/route.py +4 -11
- ddeutil/workflow/scheduler.py +97 -64
- ddeutil/workflow/stage.py +44 -30
- ddeutil/workflow/utils.py +91 -266
- {ddeutil_workflow-0.0.14.dist-info → ddeutil_workflow-0.0.16.dist-info}/METADATA +39 -23
- ddeutil_workflow-0.0.16.dist-info/RECORD +22 -0
- {ddeutil_workflow-0.0.14.dist-info → ddeutil_workflow-0.0.16.dist-info}/WHEEL +1 -1
- ddeutil_workflow-0.0.14.dist-info/RECORD +0 -22
- {ddeutil_workflow-0.0.14.dist-info → ddeutil_workflow-0.0.16.dist-info}/LICENSE +0 -0
- {ddeutil_workflow-0.0.14.dist-info → ddeutil_workflow-0.0.16.dist-info}/entry_points.txt +0 -0
- {ddeutil_workflow-0.0.14.dist-info → ddeutil_workflow-0.0.16.dist-info}/top_level.txt +0 -0
ddeutil/workflow/stage.py
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
# Licensed under the MIT License. See LICENSE in the project root for
|
4
4
|
# license information.
|
5
5
|
# ------------------------------------------------------------------------------
|
6
|
-
"""Stage Model that use for getting stage data template from Job Model.
|
7
|
-
The stage
|
6
|
+
"""Stage Model that use for getting stage data template from the Job Model.
|
7
|
+
The stage handle the minimize task that run in some thread (same thread at
|
8
8
|
its job owner) that mean it is the lowest executor of a workflow workflow that
|
9
9
|
can tracking logs.
|
10
10
|
|
@@ -12,11 +12,13 @@ can tracking logs.
|
|
12
12
|
handle stage error on this stage model. I think stage model should have a lot of
|
13
13
|
usecase and it does not worry when I want to create a new one.
|
14
14
|
|
15
|
-
Execution --> Ok
|
16
|
-
--> Error
|
15
|
+
Execution --> Ok --> Result with 0
|
16
|
+
--> Error --> Raise StageException
|
17
|
+
--> Result with 1 (if env var was set)
|
17
18
|
|
18
|
-
On the context I/O that pass to stage object at execute process. The
|
19
|
-
method
|
19
|
+
On the context I/O that pass to a stage object at execute process. The
|
20
|
+
execute method receives a `params={"params": {...}}` value for mapping to
|
21
|
+
template searching.
|
20
22
|
"""
|
21
23
|
from __future__ import annotations
|
22
24
|
|
@@ -24,6 +26,7 @@ import contextlib
|
|
24
26
|
import inspect
|
25
27
|
import subprocess
|
26
28
|
import sys
|
29
|
+
import time
|
27
30
|
import uuid
|
28
31
|
from abc import ABC, abstractmethod
|
29
32
|
from collections.abc import Iterator
|
@@ -60,6 +63,8 @@ from .utils import (
|
|
60
63
|
)
|
61
64
|
|
62
65
|
P = ParamSpec("P")
|
66
|
+
ReturnResult = Callable[P, Result]
|
67
|
+
DecoratorResult = Callable[[ReturnResult], ReturnResult]
|
63
68
|
logger = get_logger("ddeutil.workflow")
|
64
69
|
|
65
70
|
|
@@ -77,7 +82,7 @@ __all__: TupleStr = (
|
|
77
82
|
)
|
78
83
|
|
79
84
|
|
80
|
-
def handler_result(message: str | None = None) ->
|
85
|
+
def handler_result(message: str | None = None) -> DecoratorResult:
|
81
86
|
"""Decorator function for handler result from the stage execution. This
|
82
87
|
function should to use with execution method only.
|
83
88
|
|
@@ -85,25 +90,33 @@ def handler_result(message: str | None = None) -> Callable[P, Result]:
|
|
85
90
|
you force catching an output result with error message by specific
|
86
91
|
environment variable,`WORKFLOW_CORE_STAGE_RAISE_ERROR`.
|
87
92
|
|
88
|
-
Execution --> Ok --> Result
|
93
|
+
Execution --> Ok --> Result
|
94
|
+
status: 0
|
95
|
+
context:
|
96
|
+
outputs: ...
|
89
97
|
--> Error --> Raise StageException
|
90
|
-
--> Result
|
98
|
+
--> Result (if env var was set)
|
99
|
+
status: 1
|
100
|
+
context:
|
101
|
+
error: ...
|
102
|
+
error_message: ...
|
91
103
|
|
92
104
|
On the last step, it will set the running ID on a return result object
|
93
105
|
from current stage ID before release the final result.
|
94
106
|
|
95
107
|
:param message: A message that want to add at prefix of exception statement.
|
108
|
+
:type message: str | None (Default=None)
|
96
109
|
:rtype: Callable[P, Result]
|
97
110
|
"""
|
98
111
|
# NOTE: The prefix message string that want to add on the first exception
|
99
112
|
# message dialog.
|
100
113
|
#
|
101
|
-
#
|
114
|
+
# >>> ValueError: {message}
|
102
115
|
# ... raise value error from the stage execution process.
|
103
116
|
#
|
104
117
|
message: str = message or ""
|
105
118
|
|
106
|
-
def decorator(func:
|
119
|
+
def decorator(func: ReturnResult) -> ReturnResult:
|
107
120
|
|
108
121
|
@wraps(func)
|
109
122
|
def wrapped(self: Stage, *args, **kwargs):
|
@@ -172,7 +185,7 @@ class BaseStage(BaseModel, ABC):
|
|
172
185
|
)
|
173
186
|
|
174
187
|
@model_validator(mode="after")
|
175
|
-
def
|
188
|
+
def __prepare_running_id__(self) -> Self:
|
176
189
|
"""Prepare stage running ID that use default value of field and this
|
177
190
|
method will validate name and id fields should not contain any template
|
178
191
|
parameter (exclude matrix template).
|
@@ -232,7 +245,7 @@ class BaseStage(BaseModel, ABC):
|
|
232
245
|
:param to: A context data that want to add output result.
|
233
246
|
:rtype: DictData
|
234
247
|
"""
|
235
|
-
if
|
248
|
+
if self.id is None and not config.stage_default_id:
|
236
249
|
logger.debug(
|
237
250
|
f"({self.run_id}) [STAGE]: Output does not set because this "
|
238
251
|
f"stage does not set ID or default stage ID config flag not be "
|
@@ -252,7 +265,7 @@ class BaseStage(BaseModel, ABC):
|
|
252
265
|
)
|
253
266
|
|
254
267
|
# NOTE: Set the output to that stage generated ID with ``outputs`` key.
|
255
|
-
logger.debug(f"({self.run_id}) [STAGE]: Set outputs
|
268
|
+
logger.debug(f"({self.run_id}) [STAGE]: Set outputs to {_id!r}")
|
256
269
|
to["stages"][_id] = {"outputs": output}
|
257
270
|
return to
|
258
271
|
|
@@ -293,6 +306,11 @@ class EmptyStage(BaseStage):
|
|
293
306
|
default=None,
|
294
307
|
description="A string statement that want to logging",
|
295
308
|
)
|
309
|
+
sleep: float = Field(
|
310
|
+
default=0,
|
311
|
+
description="A second value to sleep before finish execution",
|
312
|
+
ge=0,
|
313
|
+
)
|
296
314
|
|
297
315
|
def execute(self, params: DictData) -> Result:
|
298
316
|
"""Execution method for the Empty stage that do only logging out to
|
@@ -310,6 +328,8 @@ class EmptyStage(BaseStage):
|
|
310
328
|
f"({self.run_id}) [STAGE]: Empty-Execute: {self.name!r}: "
|
311
329
|
f"( {param2template(self.echo, params=params) or '...'} )"
|
312
330
|
)
|
331
|
+
if self.sleep > 0:
|
332
|
+
time.sleep(self.sleep)
|
313
333
|
return Result(status=0, context={})
|
314
334
|
|
315
335
|
|
@@ -342,7 +362,7 @@ class BashStage(BaseStage):
|
|
342
362
|
)
|
343
363
|
|
344
364
|
@contextlib.contextmanager
|
345
|
-
def
|
365
|
+
def prepare_bash(self, bash: str, env: DictStr) -> Iterator[TupleStr]:
|
346
366
|
"""Return context of prepared bash statement that want to execute. This
|
347
367
|
step will write the `.sh` file before giving this file name to context.
|
348
368
|
After that, it will auto delete this file automatic.
|
@@ -385,15 +405,12 @@ class BashStage(BaseStage):
|
|
385
405
|
:rtype: Result
|
386
406
|
"""
|
387
407
|
bash: str = param2template(dedent(self.bash), params)
|
388
|
-
with self.
|
408
|
+
with self.prepare_bash(
|
389
409
|
bash=bash, env=param2template(self.env, params)
|
390
410
|
) as sh:
|
391
411
|
logger.info(f"({self.run_id}) [STAGE]: Shell-Execute: {sh}")
|
392
412
|
rs: CompletedProcess = subprocess.run(
|
393
|
-
sh,
|
394
|
-
shell=False,
|
395
|
-
capture_output=True,
|
396
|
-
text=True,
|
413
|
+
sh, shell=False, capture_output=True, text=True
|
397
414
|
)
|
398
415
|
if rs.returncode > 0:
|
399
416
|
# NOTE: Prepare stderr message that returning from subprocess.
|
@@ -410,8 +427,8 @@ class BashStage(BaseStage):
|
|
410
427
|
status=0,
|
411
428
|
context={
|
412
429
|
"return_code": rs.returncode,
|
413
|
-
"stdout": rs.stdout.rstrip("\n"),
|
414
|
-
"stderr": rs.stderr.rstrip("\n"),
|
430
|
+
"stdout": rs.stdout.rstrip("\n") or None,
|
431
|
+
"stderr": rs.stderr.rstrip("\n") or None,
|
415
432
|
},
|
416
433
|
)
|
417
434
|
|
@@ -545,14 +562,14 @@ class HookStage(BaseStage):
|
|
545
562
|
>>> stage = {
|
546
563
|
... "name": "Task stage execution",
|
547
564
|
... "uses": "tasks/function-name@tag-name",
|
548
|
-
... "args": {
|
549
|
-
... "FOO": "BAR",
|
550
|
-
... },
|
565
|
+
... "args": {"FOO": "BAR"},
|
551
566
|
... }
|
552
567
|
"""
|
553
568
|
|
554
569
|
uses: str = Field(
|
555
|
-
description=
|
570
|
+
description=(
|
571
|
+
"A pointer that want to load function from the hook registry."
|
572
|
+
),
|
556
573
|
)
|
557
574
|
args: DictData = Field(
|
558
575
|
default_factory=dict,
|
@@ -613,10 +630,7 @@ class TriggerStage(BaseStage):
|
|
613
630
|
>>> stage = {
|
614
631
|
... "name": "Trigger workflow stage execution",
|
615
632
|
... "trigger": 'workflow-name-for-loader',
|
616
|
-
... "params": {
|
617
|
-
... "run-date": "2024-08-01",
|
618
|
-
... "source": "src",
|
619
|
-
... },
|
633
|
+
... "params": {"run-date": "2024-08-01", "source": "src"},
|
620
634
|
... }
|
621
635
|
"""
|
622
636
|
|