ddeutil-workflow 0.0.58__py3-none-any.whl → 0.0.59__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/__cron.py +3 -3
- ddeutil/workflow/conf.py +6 -4
- ddeutil/workflow/event.py +2 -2
- ddeutil/workflow/exceptions.py +3 -3
- ddeutil/workflow/job.py +35 -34
- ddeutil/workflow/logs.py +78 -51
- ddeutil/workflow/params.py +9 -5
- ddeutil/workflow/result.py +18 -18
- ddeutil/workflow/reusables.py +9 -9
- ddeutil/workflow/scheduler.py +8 -8
- ddeutil/workflow/stages.py +70 -70
- ddeutil/workflow/utils.py +6 -6
- ddeutil/workflow/workflow.py +31 -31
- {ddeutil_workflow-0.0.58.dist-info → ddeutil_workflow-0.0.59.dist-info}/METADATA +6 -3
- ddeutil_workflow-0.0.59.dist-info/RECORD +31 -0
- {ddeutil_workflow-0.0.58.dist-info → ddeutil_workflow-0.0.59.dist-info}/WHEEL +1 -1
- ddeutil_workflow-0.0.58.dist-info/RECORD +0 -31
- {ddeutil_workflow-0.0.58.dist-info → ddeutil_workflow-0.0.59.dist-info}/entry_points.txt +0 -0
- {ddeutil_workflow-0.0.58.dist-info → ddeutil_workflow-0.0.59.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.58.dist-info → ddeutil_workflow-0.0.59.dist-info}/top_level.txt +0 -0
ddeutil/workflow/result.py
CHANGED
@@ -3,16 +3,16 @@
|
|
3
3
|
# Licensed under the MIT License. See LICENSE in the project root for
|
4
4
|
# license information.
|
5
5
|
# ------------------------------------------------------------------------------
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
"""A Result module. It is the data context transfer objects that use by all
|
7
|
+
object in this package. This module provide Status enum object and Result
|
8
|
+
dataclass.
|
9
9
|
"""
|
10
10
|
from __future__ import annotations
|
11
11
|
|
12
12
|
from dataclasses import field
|
13
13
|
from datetime import datetime
|
14
14
|
from enum import IntEnum
|
15
|
-
from typing import Optional
|
15
|
+
from typing import Optional, Union
|
16
16
|
|
17
17
|
from pydantic import ConfigDict
|
18
18
|
from pydantic.dataclasses import dataclass
|
@@ -22,7 +22,7 @@ from typing_extensions import Self
|
|
22
22
|
from .__types import DictData
|
23
23
|
from .conf import dynamic
|
24
24
|
from .exceptions import ResultException
|
25
|
-
from .logs import
|
25
|
+
from .logs import TraceModel, get_dt_tznow, get_trace
|
26
26
|
from .utils import default_gen_id, gen_id, get_dt_now
|
27
27
|
|
28
28
|
|
@@ -31,11 +31,11 @@ class Status(IntEnum):
|
|
31
31
|
Result dataclass object.
|
32
32
|
"""
|
33
33
|
|
34
|
-
SUCCESS
|
35
|
-
FAILED
|
36
|
-
WAIT
|
37
|
-
SKIP
|
38
|
-
CANCEL
|
34
|
+
SUCCESS = 0
|
35
|
+
FAILED = 1
|
36
|
+
WAIT = 2
|
37
|
+
SKIP = 3
|
38
|
+
CANCEL = 4
|
39
39
|
|
40
40
|
@property
|
41
41
|
def emoji(self) -> str:
|
@@ -75,16 +75,16 @@ class Result:
|
|
75
75
|
parent_run_id: Optional[str] = field(default=None, compare=False)
|
76
76
|
ts: datetime = field(default_factory=get_dt_tznow, compare=False)
|
77
77
|
|
78
|
-
trace: Optional[
|
78
|
+
trace: Optional[TraceModel] = field(default=None, compare=False, repr=False)
|
79
79
|
extras: DictData = field(default_factory=dict, compare=False, repr=False)
|
80
80
|
|
81
81
|
@classmethod
|
82
82
|
def construct_with_rs_or_id(
|
83
83
|
cls,
|
84
|
-
result: Result
|
85
|
-
run_id: str
|
86
|
-
parent_run_id: str
|
87
|
-
id_logic: str
|
84
|
+
result: Optional[Result] = None,
|
85
|
+
run_id: Optional[str] = None,
|
86
|
+
parent_run_id: Optional[str] = None,
|
87
|
+
id_logic: Optional[str] = None,
|
88
88
|
*,
|
89
89
|
extras: DictData | None = None,
|
90
90
|
) -> Self:
|
@@ -121,7 +121,7 @@ class Result:
|
|
121
121
|
:rtype: Self
|
122
122
|
"""
|
123
123
|
if self.trace is None: # pragma: no cov
|
124
|
-
self.trace:
|
124
|
+
self.trace: TraceModel = get_trace(
|
125
125
|
self.run_id,
|
126
126
|
parent_run_id=self.parent_run_id,
|
127
127
|
extras=self.extras,
|
@@ -136,14 +136,14 @@ class Result:
|
|
136
136
|
:rtype: Self
|
137
137
|
"""
|
138
138
|
self.parent_run_id: str = running_id
|
139
|
-
self.trace:
|
139
|
+
self.trace: TraceModel = get_trace(
|
140
140
|
self.run_id, parent_run_id=running_id, extras=self.extras
|
141
141
|
)
|
142
142
|
return self
|
143
143
|
|
144
144
|
def catch(
|
145
145
|
self,
|
146
|
-
status: int
|
146
|
+
status: Union[int, Status],
|
147
147
|
context: DictData | None = None,
|
148
148
|
**kwargs,
|
149
149
|
) -> Self:
|
ddeutil/workflow/reusables.py
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
"""Reusables module that keep any templating functions."""
|
8
8
|
from __future__ import annotations
|
9
9
|
|
10
|
+
import copy
|
10
11
|
import inspect
|
11
12
|
import logging
|
12
13
|
from ast import Call, Constant, Expr, Module, Name, parse
|
@@ -35,7 +36,7 @@ logger = logging.getLogger("ddeutil.workflow")
|
|
35
36
|
logging.getLogger("asyncio").setLevel(logging.INFO)
|
36
37
|
|
37
38
|
|
38
|
-
FILTERS: dict[str,
|
39
|
+
FILTERS: dict[str, Callable] = { # pragma: no cov
|
39
40
|
"abs": abs,
|
40
41
|
"str": str,
|
41
42
|
"int": int,
|
@@ -258,9 +259,9 @@ def str2template(
|
|
258
259
|
value: str,
|
259
260
|
params: DictData,
|
260
261
|
*,
|
261
|
-
filters: dict[str, FilterRegistry]
|
262
|
+
filters: Optional[dict[str, FilterRegistry]] = None,
|
262
263
|
registers: Optional[list[str]] = None,
|
263
|
-
) -> str:
|
264
|
+
) -> Optional[str]:
|
264
265
|
"""(Sub-function) Pass param to template string that can search by
|
265
266
|
``RE_CALLER`` regular expression.
|
266
267
|
|
@@ -326,7 +327,7 @@ def str2template(
|
|
326
327
|
def param2template(
|
327
328
|
value: T,
|
328
329
|
params: DictData,
|
329
|
-
filters: dict[str, FilterRegistry]
|
330
|
+
filters: Optional[dict[str, FilterRegistry]] = None,
|
330
331
|
*,
|
331
332
|
extras: Optional[DictData] = None,
|
332
333
|
) -> T:
|
@@ -381,7 +382,7 @@ def datetime_format(value: datetime, fmt: str = "%Y-%m-%d %H:%M:%S") -> str:
|
|
381
382
|
|
382
383
|
|
383
384
|
@custom_filter("coalesce") # pragma: no cov
|
384
|
-
def coalesce(value: T
|
385
|
+
def coalesce(value: Optional[T], default: Any) -> T:
|
385
386
|
"""Coalesce with default value if the main value is None."""
|
386
387
|
return default if value is None else value
|
387
388
|
|
@@ -450,11 +451,10 @@ def make_registry(
|
|
450
451
|
:rtype: dict[str, Registry]
|
451
452
|
"""
|
452
453
|
rs: dict[str, Registry] = {}
|
453
|
-
regis_calls: list[str] =
|
454
|
-
"registry_caller", f=registries
|
455
|
-
)
|
454
|
+
regis_calls: list[str] = copy.deepcopy(
|
455
|
+
dynamic("registry_caller", f=registries)
|
456
|
+
)
|
456
457
|
regis_calls.extend(["ddeutil.vendors"])
|
457
|
-
|
458
458
|
for module in regis_calls:
|
459
459
|
# NOTE: try to sequential import task functions
|
460
460
|
try:
|
ddeutil/workflow/scheduler.py
CHANGED
@@ -335,9 +335,9 @@ class Schedule(BaseModel):
|
|
335
335
|
def pending(
|
336
336
|
self,
|
337
337
|
*,
|
338
|
-
stop: datetime
|
338
|
+
stop: Optional[datetime] = None,
|
339
339
|
audit: type[Audit] | None = None,
|
340
|
-
parent_run_id: str
|
340
|
+
parent_run_id: Optional[str] = None,
|
341
341
|
) -> Result: # pragma: no cov
|
342
342
|
"""Pending this schedule tasks with the schedule package.
|
343
343
|
|
@@ -384,7 +384,7 @@ DecoratorCancelJob = Callable[[ReturnResultOrCancel], ReturnResultOrCancel]
|
|
384
384
|
|
385
385
|
def catch_exceptions(
|
386
386
|
cancel_on_failure: bool = False,
|
387
|
-
parent_run_id: str
|
387
|
+
parent_run_id: Optional[str] = None,
|
388
388
|
) -> DecoratorCancelJob:
|
389
389
|
"""Catch exception error from scheduler job that running with schedule
|
390
390
|
package and return CancelJob if this function raise an error.
|
@@ -440,7 +440,7 @@ def schedule_task(
|
|
440
440
|
threads: ReleaseThreads,
|
441
441
|
audit: type[Audit],
|
442
442
|
*,
|
443
|
-
parent_run_id: str
|
443
|
+
parent_run_id: Optional[str] = None,
|
444
444
|
extras: Optional[DictData] = None,
|
445
445
|
) -> ResultOrCancel:
|
446
446
|
"""Schedule task function that generate thread of workflow task release
|
@@ -558,7 +558,7 @@ def schedule_task(
|
|
558
558
|
|
559
559
|
def monitor(
|
560
560
|
threads: ReleaseThreads,
|
561
|
-
parent_run_id: str
|
561
|
+
parent_run_id: Optional[str] = None,
|
562
562
|
) -> None: # pragma: no cov
|
563
563
|
"""Monitoring function that running every five minute for track long-running
|
564
564
|
thread instance from the schedule_control function that run every minute.
|
@@ -685,11 +685,11 @@ def scheduler_pending(
|
|
685
685
|
|
686
686
|
def schedule_control(
|
687
687
|
schedules: list[str],
|
688
|
-
stop: datetime
|
688
|
+
stop: Optional[datetime] = None,
|
689
689
|
*,
|
690
690
|
extras: DictData | None = None,
|
691
691
|
audit: type[Audit] | None = None,
|
692
|
-
parent_run_id: str
|
692
|
+
parent_run_id: Optional[str] = None,
|
693
693
|
) -> Result: # pragma: no cov
|
694
694
|
"""Scheduler control function that run the chuck of schedules every minute
|
695
695
|
and this function release monitoring thread for tracking undead thread in
|
@@ -744,7 +744,7 @@ def schedule_control(
|
|
744
744
|
|
745
745
|
|
746
746
|
def schedule_runner(
|
747
|
-
stop: datetime
|
747
|
+
stop: Optional[datetime] = None,
|
748
748
|
*,
|
749
749
|
max_process: int | None = None,
|
750
750
|
extras: DictData | None = None,
|
ddeutil/workflow/stages.py
CHANGED
@@ -141,8 +141,8 @@ class BaseStage(BaseModel, ABC):
|
|
141
141
|
self,
|
142
142
|
params: DictData,
|
143
143
|
*,
|
144
|
-
result: Result
|
145
|
-
event: Event
|
144
|
+
result: Optional[Result] = None,
|
145
|
+
event: Optional[Event] = None,
|
146
146
|
) -> Result:
|
147
147
|
"""Execute abstraction method that action something by sub-model class.
|
148
148
|
This is important method that make this class is able to be the stage.
|
@@ -162,12 +162,12 @@ class BaseStage(BaseModel, ABC):
|
|
162
162
|
self,
|
163
163
|
params: DictData,
|
164
164
|
*,
|
165
|
-
run_id: str
|
166
|
-
parent_run_id: str
|
167
|
-
result: Result
|
168
|
-
event: Event
|
169
|
-
raise_error: bool
|
170
|
-
) -> Result
|
165
|
+
run_id: Optional[str] = None,
|
166
|
+
parent_run_id: Optional[str] = None,
|
167
|
+
result: Optional[Result] = None,
|
168
|
+
event: Optional[Event] = None,
|
169
|
+
raise_error: Optional[bool] = None,
|
170
|
+
) -> Union[Result, DictData]:
|
171
171
|
"""Handler stage execution result from the stage `execute` method.
|
172
172
|
|
173
173
|
This stage exception handler still use ok-error concept, but it
|
@@ -376,8 +376,8 @@ class BaseAsyncStage(BaseStage):
|
|
376
376
|
self,
|
377
377
|
params: DictData,
|
378
378
|
*,
|
379
|
-
result: Result
|
380
|
-
event: Event
|
379
|
+
result: Optional[Result] = None,
|
380
|
+
event: Optional[Event] = None,
|
381
381
|
) -> Result:
|
382
382
|
raise NotImplementedError(
|
383
383
|
"Async Stage should implement `execute` method."
|
@@ -388,8 +388,8 @@ class BaseAsyncStage(BaseStage):
|
|
388
388
|
self,
|
389
389
|
params: DictData,
|
390
390
|
*,
|
391
|
-
result: Result
|
392
|
-
event: Event
|
391
|
+
result: Optional[Result] = None,
|
392
|
+
event: Optional[Event] = None,
|
393
393
|
) -> Result:
|
394
394
|
"""Async execution method for this Empty stage that only logging out to
|
395
395
|
stdout.
|
@@ -411,11 +411,11 @@ class BaseAsyncStage(BaseStage):
|
|
411
411
|
self,
|
412
412
|
params: DictData,
|
413
413
|
*,
|
414
|
-
run_id: str
|
415
|
-
parent_run_id: str
|
416
|
-
result: Result
|
417
|
-
event: Event
|
418
|
-
raise_error: bool
|
414
|
+
run_id: Optional[str] = None,
|
415
|
+
parent_run_id: Optional[str] = None,
|
416
|
+
result: Optional[Result] = None,
|
417
|
+
event: Optional[Event] = None,
|
418
|
+
raise_error: Optional[bool] = None,
|
419
419
|
) -> Result:
|
420
420
|
"""Async Handler stage execution result from the stage `execute` method.
|
421
421
|
|
@@ -487,8 +487,8 @@ class EmptyStage(BaseAsyncStage):
|
|
487
487
|
self,
|
488
488
|
params: DictData,
|
489
489
|
*,
|
490
|
-
result: Result
|
491
|
-
event: Event
|
490
|
+
result: Optional[Result] = None,
|
491
|
+
event: Optional[Event] = None,
|
492
492
|
) -> Result:
|
493
493
|
"""Execution method for the Empty stage that do only logging out to
|
494
494
|
stdout.
|
@@ -528,8 +528,8 @@ class EmptyStage(BaseAsyncStage):
|
|
528
528
|
self,
|
529
529
|
params: DictData,
|
530
530
|
*,
|
531
|
-
result: Result
|
532
|
-
event: Event
|
531
|
+
result: Optional[Result] = None,
|
532
|
+
event: Optional[Event] = None,
|
533
533
|
) -> Result:
|
534
534
|
"""Async execution method for this Empty stage that only logging out to
|
535
535
|
stdout.
|
@@ -599,13 +599,13 @@ class BashStage(BaseAsyncStage):
|
|
599
599
|
|
600
600
|
@contextlib.asynccontextmanager
|
601
601
|
async def acreate_sh_file(
|
602
|
-
self, bash: str, env: DictStr, run_id: str
|
602
|
+
self, bash: str, env: DictStr, run_id: Optional[str] = None
|
603
603
|
) -> AsyncIterator[TupleStr]:
|
604
604
|
"""Async create and write `.sh` file with the `aiofiles` package.
|
605
605
|
|
606
606
|
:param bash: (str) A bash statement.
|
607
607
|
:param env: (DictStr) An environment variable that set before run bash.
|
608
|
-
:param run_id: (str
|
608
|
+
:param run_id: (Optional[str]) A running stage ID that use for writing sh
|
609
609
|
file instead generate by UUID4.
|
610
610
|
|
611
611
|
:rtype: AsyncIterator[TupleStr]
|
@@ -635,14 +635,14 @@ class BashStage(BaseAsyncStage):
|
|
635
635
|
|
636
636
|
@contextlib.contextmanager
|
637
637
|
def create_sh_file(
|
638
|
-
self, bash: str, env: DictStr, run_id: str
|
638
|
+
self, bash: str, env: DictStr, run_id: Optional[str] = None
|
639
639
|
) -> Iterator[TupleStr]:
|
640
640
|
"""Create and write the `.sh` file before giving this file name to
|
641
641
|
context. After that, it will auto delete this file automatic.
|
642
642
|
|
643
643
|
:param bash: (str) A bash statement.
|
644
644
|
:param env: (DictStr) An environment variable that set before run bash.
|
645
|
-
:param run_id: (str
|
645
|
+
:param run_id: (Optional[str]) A running stage ID that use for writing sh
|
646
646
|
file instead generate by UUID4.
|
647
647
|
|
648
648
|
:rtype: Iterator[TupleStr]
|
@@ -673,8 +673,8 @@ class BashStage(BaseAsyncStage):
|
|
673
673
|
self,
|
674
674
|
params: DictData,
|
675
675
|
*,
|
676
|
-
result: Result
|
677
|
-
event: Event
|
676
|
+
result: Optional[Result] = None,
|
677
|
+
event: Optional[Event] = None,
|
678
678
|
) -> Result:
|
679
679
|
"""Execute bash statement with the Python build-in `subprocess` package.
|
680
680
|
It will catch result from the `subprocess.run` returning output like
|
@@ -730,8 +730,8 @@ class BashStage(BaseAsyncStage):
|
|
730
730
|
self,
|
731
731
|
params: DictData,
|
732
732
|
*,
|
733
|
-
result: Result
|
734
|
-
event: Event
|
733
|
+
result: Optional[Result] = None,
|
734
|
+
event: Optional[Event] = None,
|
735
735
|
) -> Result:
|
736
736
|
"""Async execution method for this Bash stage that only logging out to
|
737
737
|
stdout.
|
@@ -858,8 +858,8 @@ class PyStage(BaseAsyncStage):
|
|
858
858
|
self,
|
859
859
|
params: DictData,
|
860
860
|
*,
|
861
|
-
result: Result
|
862
|
-
event: Event
|
861
|
+
result: Optional[Result] = None,
|
862
|
+
event: Optional[Event] = None,
|
863
863
|
) -> Result:
|
864
864
|
"""Execute the Python statement that pass all globals and input params
|
865
865
|
to globals argument on `exec` build-in function.
|
@@ -916,8 +916,8 @@ class PyStage(BaseAsyncStage):
|
|
916
916
|
self,
|
917
917
|
params: DictData,
|
918
918
|
*,
|
919
|
-
result: Result
|
920
|
-
event: Event
|
919
|
+
result: Optional[Result] = None,
|
920
|
+
event: Optional[Event] = None,
|
921
921
|
) -> Result:
|
922
922
|
"""Async execution method for this Bash stage that only logging out to
|
923
923
|
stdout.
|
@@ -1018,8 +1018,8 @@ class CallStage(BaseAsyncStage):
|
|
1018
1018
|
self,
|
1019
1019
|
params: DictData,
|
1020
1020
|
*,
|
1021
|
-
result: Result
|
1022
|
-
event: Event
|
1021
|
+
result: Optional[Result] = None,
|
1022
|
+
event: Optional[Event] = None,
|
1023
1023
|
) -> Result:
|
1024
1024
|
"""Execute this caller function with its argument parameter.
|
1025
1025
|
|
@@ -1108,8 +1108,8 @@ class CallStage(BaseAsyncStage):
|
|
1108
1108
|
self,
|
1109
1109
|
params: DictData,
|
1110
1110
|
*,
|
1111
|
-
result: Result
|
1112
|
-
event: Event
|
1111
|
+
result: Optional[Result] = None,
|
1112
|
+
event: Optional[Event] = None,
|
1113
1113
|
) -> Result:
|
1114
1114
|
"""Async execution method for this Bash stage that only logging out to
|
1115
1115
|
stdout.
|
@@ -1266,8 +1266,8 @@ class TriggerStage(BaseStage):
|
|
1266
1266
|
self,
|
1267
1267
|
params: DictData,
|
1268
1268
|
*,
|
1269
|
-
result: Result
|
1270
|
-
event: Event
|
1269
|
+
result: Optional[Result] = None,
|
1270
|
+
event: Optional[Event] = None,
|
1271
1271
|
) -> Result:
|
1272
1272
|
"""Trigger another workflow execution. It will wait the trigger
|
1273
1273
|
workflow running complete before catching its result.
|
@@ -1298,7 +1298,7 @@ class TriggerStage(BaseStage):
|
|
1298
1298
|
event=event,
|
1299
1299
|
)
|
1300
1300
|
if rs.status == FAILED:
|
1301
|
-
err_msg: str
|
1301
|
+
err_msg: Optional[str] = (
|
1302
1302
|
f" with:\n{msg}"
|
1303
1303
|
if (msg := rs.context.get("errors", {}).get("message"))
|
1304
1304
|
else "."
|
@@ -1319,8 +1319,8 @@ class BaseNestedStage(BaseStage):
|
|
1319
1319
|
self,
|
1320
1320
|
params: DictData,
|
1321
1321
|
*,
|
1322
|
-
result: Result
|
1323
|
-
event: Event
|
1322
|
+
result: Optional[Result] = None,
|
1323
|
+
event: Optional[Event] = None,
|
1324
1324
|
) -> Result:
|
1325
1325
|
"""Execute abstraction method that action something by sub-model class.
|
1326
1326
|
This is important method that make this class is able to be the nested
|
@@ -1390,7 +1390,7 @@ class ParallelStage(BaseNestedStage):
|
|
1390
1390
|
params: DictData,
|
1391
1391
|
result: Result,
|
1392
1392
|
*,
|
1393
|
-
event: Event
|
1393
|
+
event: Optional[Event] = None,
|
1394
1394
|
) -> Result:
|
1395
1395
|
"""Execute all stage with specific branch ID.
|
1396
1396
|
|
@@ -1487,8 +1487,8 @@ class ParallelStage(BaseNestedStage):
|
|
1487
1487
|
self,
|
1488
1488
|
params: DictData,
|
1489
1489
|
*,
|
1490
|
-
result: Result
|
1491
|
-
event: Event
|
1490
|
+
result: Optional[Result] = None,
|
1491
|
+
event: Optional[Event] = None,
|
1492
1492
|
) -> Result:
|
1493
1493
|
"""Execute parallel each branch via multi-threading pool.
|
1494
1494
|
|
@@ -1526,7 +1526,7 @@ class ParallelStage(BaseNestedStage):
|
|
1526
1526
|
context: DictData = {}
|
1527
1527
|
status: Status = SUCCESS
|
1528
1528
|
|
1529
|
-
futures: list[Future] =
|
1529
|
+
futures: list[Future] = [
|
1530
1530
|
executor.submit(
|
1531
1531
|
self.execute_branch,
|
1532
1532
|
branch=branch,
|
@@ -1535,7 +1535,7 @@ class ParallelStage(BaseNestedStage):
|
|
1535
1535
|
event=event,
|
1536
1536
|
)
|
1537
1537
|
for branch in self.parallel
|
1538
|
-
|
1538
|
+
]
|
1539
1539
|
|
1540
1540
|
for future in as_completed(futures):
|
1541
1541
|
try:
|
@@ -1605,7 +1605,7 @@ class ForEachStage(BaseNestedStage):
|
|
1605
1605
|
params: DictData,
|
1606
1606
|
result: Result,
|
1607
1607
|
*,
|
1608
|
-
event: Event
|
1608
|
+
event: Optional[Event] = None,
|
1609
1609
|
) -> Result:
|
1610
1610
|
"""Execute all nested stage that set on this stage with specific foreach
|
1611
1611
|
item parameter.
|
@@ -1709,8 +1709,8 @@ class ForEachStage(BaseNestedStage):
|
|
1709
1709
|
self,
|
1710
1710
|
params: DictData,
|
1711
1711
|
*,
|
1712
|
-
result: Result
|
1713
|
-
event: Event
|
1712
|
+
result: Optional[Result] = None,
|
1713
|
+
event: Optional[Event] = None,
|
1714
1714
|
) -> Result:
|
1715
1715
|
"""Execute the stages that pass each item form the foreach field.
|
1716
1716
|
|
@@ -1775,7 +1775,7 @@ class ForEachStage(BaseNestedStage):
|
|
1775
1775
|
status: Status = SUCCESS
|
1776
1776
|
|
1777
1777
|
done, not_done = wait(futures, return_when=FIRST_EXCEPTION)
|
1778
|
-
if len(done) != len(futures):
|
1778
|
+
if len(list(done)) != len(futures):
|
1779
1779
|
result.trace.warning(
|
1780
1780
|
"[STAGE]: Set event for stop pending for-each stage."
|
1781
1781
|
)
|
@@ -1795,7 +1795,7 @@ class ForEachStage(BaseNestedStage):
|
|
1795
1795
|
result.trace.debug(
|
1796
1796
|
f"[STAGE]: ... Foreach-Stage set failed event{nd}"
|
1797
1797
|
)
|
1798
|
-
done:
|
1798
|
+
done: Iterator[Future] = as_completed(futures)
|
1799
1799
|
|
1800
1800
|
for future in done:
|
1801
1801
|
try:
|
@@ -1862,7 +1862,7 @@ class UntilStage(BaseNestedStage):
|
|
1862
1862
|
loop: int,
|
1863
1863
|
params: DictData,
|
1864
1864
|
result: Result,
|
1865
|
-
event: Event
|
1865
|
+
event: Optional[Event] = None,
|
1866
1866
|
) -> tuple[Result, T]:
|
1867
1867
|
"""Execute all stage with specific loop and item.
|
1868
1868
|
|
@@ -1975,8 +1975,8 @@ class UntilStage(BaseNestedStage):
|
|
1975
1975
|
self,
|
1976
1976
|
params: DictData,
|
1977
1977
|
*,
|
1978
|
-
result: Result
|
1979
|
-
event: Event
|
1978
|
+
result: Optional[Result] = None,
|
1979
|
+
event: Optional[Event] = None,
|
1980
1980
|
) -> Result:
|
1981
1981
|
"""Execute until loop with checking until condition.
|
1982
1982
|
|
@@ -2113,7 +2113,7 @@ class CaseStage(BaseNestedStage):
|
|
2113
2113
|
params: DictData,
|
2114
2114
|
result: Result,
|
2115
2115
|
*,
|
2116
|
-
event: Event
|
2116
|
+
event: Optional[Event] = None,
|
2117
2117
|
) -> Result:
|
2118
2118
|
"""Execute case.
|
2119
2119
|
|
@@ -2198,8 +2198,8 @@ class CaseStage(BaseNestedStage):
|
|
2198
2198
|
self,
|
2199
2199
|
params: DictData,
|
2200
2200
|
*,
|
2201
|
-
result: Result
|
2202
|
-
event: Event
|
2201
|
+
result: Optional[Result] = None,
|
2202
|
+
event: Optional[Event] = None,
|
2203
2203
|
) -> Result:
|
2204
2204
|
"""Execute case-match condition that pass to the case field.
|
2205
2205
|
|
@@ -2291,8 +2291,8 @@ class RaiseStage(BaseAsyncStage):
|
|
2291
2291
|
self,
|
2292
2292
|
params: DictData,
|
2293
2293
|
*,
|
2294
|
-
result: Result
|
2295
|
-
event: Event
|
2294
|
+
result: Optional[Result] = None,
|
2295
|
+
event: Optional[Event] = None,
|
2296
2296
|
) -> Result:
|
2297
2297
|
"""Raise the StageException object with the message field execution.
|
2298
2298
|
|
@@ -2313,8 +2313,8 @@ class RaiseStage(BaseAsyncStage):
|
|
2313
2313
|
self,
|
2314
2314
|
params: DictData,
|
2315
2315
|
*,
|
2316
|
-
result: Result
|
2317
|
-
event: Event
|
2316
|
+
result: Optional[Result] = None,
|
2317
|
+
event: Optional[Event] = None,
|
2318
2318
|
) -> Result:
|
2319
2319
|
"""Async execution method for this Empty stage that only logging out to
|
2320
2320
|
stdout.
|
@@ -2367,7 +2367,7 @@ class DockerStage(BaseStage): # pragma: no cov
|
|
2367
2367
|
env: DictData = Field(
|
2368
2368
|
default_factory=dict,
|
2369
2369
|
description=(
|
2370
|
-
"An environment variable that want pass to Docker container."
|
2370
|
+
"An environment variable that want pass to Docker container."
|
2371
2371
|
),
|
2372
2372
|
)
|
2373
2373
|
volume: DictData = Field(
|
@@ -2385,7 +2385,7 @@ class DockerStage(BaseStage): # pragma: no cov
|
|
2385
2385
|
self,
|
2386
2386
|
params: DictData,
|
2387
2387
|
result: Result,
|
2388
|
-
event: Event
|
2388
|
+
event: Optional[Event] = None,
|
2389
2389
|
) -> Result:
|
2390
2390
|
"""Execute Docker container task.
|
2391
2391
|
|
@@ -2473,8 +2473,8 @@ class DockerStage(BaseStage): # pragma: no cov
|
|
2473
2473
|
self,
|
2474
2474
|
params: DictData,
|
2475
2475
|
*,
|
2476
|
-
result: Result
|
2477
|
-
event: Event
|
2476
|
+
result: Optional[Result] = None,
|
2477
|
+
event: Optional[Event] = None,
|
2478
2478
|
) -> Result:
|
2479
2479
|
"""Execute the Docker image via Python API.
|
2480
2480
|
|
@@ -2518,7 +2518,7 @@ class VirtualPyStage(PyStage): # pragma: no cov
|
|
2518
2518
|
py: str,
|
2519
2519
|
values: DictData,
|
2520
2520
|
deps: list[str],
|
2521
|
-
run_id: str
|
2521
|
+
run_id: Optional[str] = None,
|
2522
2522
|
) -> Iterator[str]:
|
2523
2523
|
"""Create the .py file with an input Python string statement.
|
2524
2524
|
|
@@ -2526,7 +2526,7 @@ class VirtualPyStage(PyStage): # pragma: no cov
|
|
2526
2526
|
:param values: A variable that want to set before running this
|
2527
2527
|
:param deps: An additional Python dependencies that want install before
|
2528
2528
|
run this python stage.
|
2529
|
-
:param run_id: (str
|
2529
|
+
:param run_id: (Optional[str]) A running ID of this stage execution.
|
2530
2530
|
"""
|
2531
2531
|
run_id: str = run_id or uuid.uuid4()
|
2532
2532
|
f_name: str = f"{run_id}.py"
|
@@ -2565,8 +2565,8 @@ class VirtualPyStage(PyStage): # pragma: no cov
|
|
2565
2565
|
self,
|
2566
2566
|
params: DictData,
|
2567
2567
|
*,
|
2568
|
-
result: Result
|
2569
|
-
event: Event
|
2568
|
+
result: Optional[Result] = None,
|
2569
|
+
event: Optional[Event] = None,
|
2570
2570
|
) -> Result:
|
2571
2571
|
"""Execute the Python statement via Python virtual environment.
|
2572
2572
|
|
ddeutil/workflow/utils.py
CHANGED
@@ -15,7 +15,7 @@ from inspect import isfunction
|
|
15
15
|
from itertools import chain, islice, product
|
16
16
|
from pathlib import Path
|
17
17
|
from random import randrange
|
18
|
-
from typing import Any, Final, TypeVar
|
18
|
+
from typing import Any, Final, Optional, TypeVar, Union
|
19
19
|
from zoneinfo import ZoneInfo
|
20
20
|
|
21
21
|
from ddeutil.core import hash_str
|
@@ -63,7 +63,7 @@ def clear_tz(dt: datetime) -> datetime:
|
|
63
63
|
return dt.replace(tzinfo=None)
|
64
64
|
|
65
65
|
|
66
|
-
def get_dt_now(tz: ZoneInfo
|
66
|
+
def get_dt_now(tz: Optional[ZoneInfo] = None, offset: float = 0.0) -> datetime:
|
67
67
|
"""Return the current datetime object.
|
68
68
|
|
69
69
|
:param tz: A ZoneInfo object for replace timezone of return datetime object.
|
@@ -76,7 +76,7 @@ def get_dt_now(tz: ZoneInfo | None = None, offset: float = 0.0) -> datetime:
|
|
76
76
|
|
77
77
|
|
78
78
|
def get_d_now(
|
79
|
-
tz: ZoneInfo
|
79
|
+
tz: Optional[ZoneInfo] = None, offset: float = 0.0
|
80
80
|
) -> date: # pragma: no cov
|
81
81
|
"""Return the current date object.
|
82
82
|
|
@@ -147,7 +147,7 @@ def gen_id(
|
|
147
147
|
*,
|
148
148
|
sensitive: bool = True,
|
149
149
|
unique: bool = False,
|
150
|
-
simple_mode: bool
|
150
|
+
simple_mode: Optional[bool] = None,
|
151
151
|
extras: DictData | None = None,
|
152
152
|
) -> str:
|
153
153
|
"""Generate running ID for able to tracking. This generates process use
|
@@ -197,7 +197,7 @@ def default_gen_id() -> str:
|
|
197
197
|
return gen_id("manual", unique=True)
|
198
198
|
|
199
199
|
|
200
|
-
def make_exec(path: str
|
200
|
+
def make_exec(path: Union[Path, str]) -> None:
|
201
201
|
"""Change mode of file to be executable file.
|
202
202
|
|
203
203
|
:param path: A file path that want to make executable permission.
|
@@ -244,7 +244,7 @@ def cross_product(matrix: Matrix) -> Iterator[DictData]:
|
|
244
244
|
)
|
245
245
|
|
246
246
|
|
247
|
-
def batch(iterable: Iterator[Any]
|
247
|
+
def batch(iterable: Union[Iterator[Any], range], n: int) -> Iterator[Any]:
|
248
248
|
"""Batch data into iterators of length n. The last batch may be shorter.
|
249
249
|
|
250
250
|
Example:
|