ddeutil-workflow 0.0.40__py3-none-any.whl → 0.0.41__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/__init__.py +21 -25
- ddeutil/workflow/api/api.py +1 -1
- ddeutil/workflow/api/routes/logs.py +1 -2
- ddeutil/workflow/api/routes/workflows.py +1 -1
- ddeutil/workflow/conf.py +11 -1
- ddeutil/workflow/job.py +55 -4
- ddeutil/workflow/logs.py +334 -72
- ddeutil/workflow/params.py +1 -0
- ddeutil/workflow/result.py +6 -15
- ddeutil/workflow/{templates.py → reusables.py} +195 -9
- ddeutil/workflow/scheduler.py +1 -1
- ddeutil/workflow/stages.py +188 -24
- ddeutil/workflow/utils.py +11 -0
- ddeutil/workflow/workflow.py +16 -8
- {ddeutil_workflow-0.0.40.dist-info → ddeutil_workflow-0.0.41.dist-info}/METADATA +7 -1
- ddeutil_workflow-0.0.41.dist-info/RECORD +31 -0
- ddeutil/workflow/audit.py +0 -257
- ddeutil/workflow/caller.py +0 -179
- ddeutil_workflow-0.0.40.dist-info/RECORD +0 -33
- {ddeutil_workflow-0.0.40.dist-info → ddeutil_workflow-0.0.41.dist-info}/WHEEL +0 -0
- {ddeutil_workflow-0.0.40.dist-info → ddeutil_workflow-0.0.41.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.40.dist-info → ddeutil_workflow-0.0.41.dist-info}/top_level.txt +0 -0
ddeutil/workflow/__about__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__: str = "0.0.
|
1
|
+
__version__: str = "0.0.41"
|
ddeutil/workflow/__init__.py
CHANGED
@@ -5,17 +5,6 @@
|
|
5
5
|
# ------------------------------------------------------------------------------
|
6
6
|
from .__cron import CronJob, CronRunner
|
7
7
|
from .__types import Re
|
8
|
-
from .audit import (
|
9
|
-
Audit,
|
10
|
-
get_audit,
|
11
|
-
)
|
12
|
-
from .caller import (
|
13
|
-
ReturnTagFunc,
|
14
|
-
TagFunc,
|
15
|
-
extract_call,
|
16
|
-
make_registry,
|
17
|
-
tag,
|
18
|
-
)
|
19
8
|
from .conf import (
|
20
9
|
Config,
|
21
10
|
Loader,
|
@@ -43,8 +32,10 @@ from .job import (
|
|
43
32
|
local_execute_strategy,
|
44
33
|
)
|
45
34
|
from .logs import (
|
35
|
+
Audit,
|
46
36
|
TraceData,
|
47
37
|
TraceLog,
|
38
|
+
get_audit,
|
48
39
|
get_dt_tznow,
|
49
40
|
get_trace,
|
50
41
|
)
|
@@ -58,7 +49,24 @@ from .params import (
|
|
58
49
|
from .result import (
|
59
50
|
Result,
|
60
51
|
Status,
|
61
|
-
|
52
|
+
)
|
53
|
+
from .reusables import (
|
54
|
+
FILTERS,
|
55
|
+
FilterFunc,
|
56
|
+
FilterRegistry,
|
57
|
+
ReturnTagFunc,
|
58
|
+
TagFunc,
|
59
|
+
custom_filter,
|
60
|
+
extract_call,
|
61
|
+
get_args_const,
|
62
|
+
has_template,
|
63
|
+
make_filter_registry,
|
64
|
+
make_registry,
|
65
|
+
map_post_filter,
|
66
|
+
not_in_template,
|
67
|
+
param2template,
|
68
|
+
str2template,
|
69
|
+
tag,
|
62
70
|
)
|
63
71
|
from .scheduler import (
|
64
72
|
Schedule,
|
@@ -77,22 +85,10 @@ from .stages import (
|
|
77
85
|
Stage,
|
78
86
|
TriggerStage,
|
79
87
|
)
|
80
|
-
from .templates import (
|
81
|
-
FILTERS,
|
82
|
-
FilterFunc,
|
83
|
-
FilterRegistry,
|
84
|
-
custom_filter,
|
85
|
-
get_args_const,
|
86
|
-
has_template,
|
87
|
-
make_filter_registry,
|
88
|
-
map_post_filter,
|
89
|
-
not_in_template,
|
90
|
-
param2template,
|
91
|
-
str2template,
|
92
|
-
)
|
93
88
|
from .utils import (
|
94
89
|
batch,
|
95
90
|
cross_product,
|
91
|
+
default_gen_id,
|
96
92
|
delay,
|
97
93
|
filter_func,
|
98
94
|
gen_id,
|
ddeutil/workflow/api/api.py
CHANGED
@@ -109,7 +109,7 @@ if config.enable_route_workflow:
|
|
109
109
|
|
110
110
|
# NOTE: Enable the schedules route.
|
111
111
|
if config.enable_route_schedule:
|
112
|
-
from ..
|
112
|
+
from ..logs import get_audit
|
113
113
|
from ..scheduler import schedule_task
|
114
114
|
from .routes import schedule
|
115
115
|
|
@@ -10,8 +10,7 @@ from fastapi import APIRouter, Path, Query
|
|
10
10
|
from fastapi import status as st
|
11
11
|
from fastapi.responses import UJSONResponse
|
12
12
|
|
13
|
-
from ...
|
14
|
-
from ...logs import get_trace_obj
|
13
|
+
from ...logs import get_audit, get_trace_obj
|
15
14
|
|
16
15
|
log_route = APIRouter(
|
17
16
|
prefix="/logs",
|
@@ -15,8 +15,8 @@ from fastapi.responses import UJSONResponse
|
|
15
15
|
from pydantic import BaseModel
|
16
16
|
|
17
17
|
from ...__types import DictData
|
18
|
-
from ...audit import Audit, get_audit
|
19
18
|
from ...conf import Loader, get_logger
|
19
|
+
from ...logs import Audit, get_audit
|
20
20
|
from ...result import Result
|
21
21
|
from ...workflow import Workflow
|
22
22
|
|
ddeutil/workflow/conf.py
CHANGED
@@ -24,6 +24,7 @@ PREFIX: str = "WORKFLOW"
|
|
24
24
|
|
25
25
|
|
26
26
|
def env(var: str, default: str | None = None) -> str | None: # pragma: no cov
|
27
|
+
"""Get environment variable with uppercase and adding prefix string."""
|
27
28
|
return os.getenv(f"{PREFIX}_{var.upper().replace(' ', '_')}", default)
|
28
29
|
|
29
30
|
|
@@ -94,11 +95,19 @@ class Config(BaseConfig): # pragma: no cov
|
|
94
95
|
# NOTE: Register
|
95
96
|
@property
|
96
97
|
def regis_call(self) -> list[str]:
|
98
|
+
"""Register Caller module importer str.
|
99
|
+
|
100
|
+
:rtype: list[str]
|
101
|
+
"""
|
97
102
|
regis_call_str: str = env("CORE_REGISTRY", ".")
|
98
103
|
return [r.strip() for r in regis_call_str.split(",")]
|
99
104
|
|
100
105
|
@property
|
101
106
|
def regis_filter(self) -> list[str]:
|
107
|
+
"""Register Filter module.
|
108
|
+
|
109
|
+
:rtype: list[str]
|
110
|
+
"""
|
102
111
|
regis_filter_str: str = env(
|
103
112
|
"CORE_REGISTRY_FILTER", "ddeutil.workflow.templates"
|
104
113
|
)
|
@@ -326,7 +335,8 @@ class SimLoad:
|
|
326
335
|
def filter_yaml(cls, file: Path, name: str | None = None) -> DictData:
|
327
336
|
if any(file.suffix.endswith(s) for s in (".yml", ".yaml")):
|
328
337
|
values: DictData = YamlFlResolve(file).read()
|
329
|
-
|
338
|
+
if values is not None:
|
339
|
+
return values.get(name, {}) if name else values
|
330
340
|
return {}
|
331
341
|
|
332
342
|
@cached_property
|
ddeutil/workflow/job.py
CHANGED
@@ -39,8 +39,8 @@ from .exceptions import (
|
|
39
39
|
UtilException,
|
40
40
|
)
|
41
41
|
from .result import Result, Status
|
42
|
+
from .reusables import has_template, param2template
|
42
43
|
from .stages import Stage
|
43
|
-
from .templates import has_template, param2template
|
44
44
|
from .utils import cross_product, filter_func, gen_id
|
45
45
|
|
46
46
|
MatrixFilter = list[dict[str, Union[str, int]]]
|
@@ -344,6 +344,10 @@ class Job(BaseModel):
|
|
344
344
|
default_factory=Strategy,
|
345
345
|
description="A strategy matrix that want to generate.",
|
346
346
|
)
|
347
|
+
extras: DictData = Field(
|
348
|
+
default_factory=dict,
|
349
|
+
description="An extra override values.",
|
350
|
+
)
|
347
351
|
|
348
352
|
@field_validator("desc", mode="after")
|
349
353
|
def ___prepare_desc__(cls, value: str) -> str:
|
@@ -394,6 +398,8 @@ class Job(BaseModel):
|
|
394
398
|
"""
|
395
399
|
for stage in self.stages:
|
396
400
|
if stage_id == (stage.id or ""):
|
401
|
+
if self.extras:
|
402
|
+
stage.extras = self.extras
|
397
403
|
return stage
|
398
404
|
raise ValueError(f"Stage ID {stage_id} does not exists")
|
399
405
|
|
@@ -596,7 +602,7 @@ def local_execute_strategy(
|
|
596
602
|
*,
|
597
603
|
result: Result | None = None,
|
598
604
|
event: Event | None = None,
|
599
|
-
raise_error: bool =
|
605
|
+
raise_error: bool | None = None,
|
600
606
|
) -> Result:
|
601
607
|
"""Local job strategy execution with passing dynamic parameters from the
|
602
608
|
workflow execution to strategy matrix.
|
@@ -694,12 +700,16 @@ def local_execute_strategy(
|
|
694
700
|
params=context,
|
695
701
|
run_id=result.run_id,
|
696
702
|
parent_run_id=result.parent_run_id,
|
703
|
+
event=event,
|
697
704
|
).context,
|
698
705
|
to=context,
|
699
706
|
)
|
700
707
|
except (StageException, UtilException) as err:
|
701
708
|
result.trace.error(f"[JOB]: {err.__class__.__name__}: {err}")
|
702
|
-
|
709
|
+
do_raise: bool = (
|
710
|
+
config.job_raise_error if raise_error is None else raise_error
|
711
|
+
)
|
712
|
+
if do_raise:
|
703
713
|
raise JobException(
|
704
714
|
f"Stage execution error: {err.__class__.__name__}: "
|
705
715
|
f"{err}"
|
@@ -735,7 +745,7 @@ def local_execute(
|
|
735
745
|
parent_run_id: str | None = None,
|
736
746
|
result: Result | None = None,
|
737
747
|
event: Event | None = None,
|
738
|
-
raise_error: bool =
|
748
|
+
raise_error: bool | None = None,
|
739
749
|
) -> Result:
|
740
750
|
"""Local job execution with passing dynamic parameters from the workflow
|
741
751
|
execution. It will generate matrix values at the first step and run
|
@@ -865,3 +875,44 @@ def local_execute(
|
|
865
875
|
context.update({"errors": err.to_dict()})
|
866
876
|
|
867
877
|
return result.catch(status=status, context=context)
|
878
|
+
|
879
|
+
|
880
|
+
def self_hosted_execute(
|
881
|
+
job: Job,
|
882
|
+
params: DictData,
|
883
|
+
*,
|
884
|
+
run_id: str | None = None,
|
885
|
+
parent_run_id: str | None = None,
|
886
|
+
result: Result | None = None,
|
887
|
+
event: Event | None = None,
|
888
|
+
raise_error: bool | None = None,
|
889
|
+
) -> Result: # pragma: no cov
|
890
|
+
result: Result = Result.construct_with_rs_or_id(
|
891
|
+
result,
|
892
|
+
run_id=run_id,
|
893
|
+
parent_run_id=parent_run_id,
|
894
|
+
id_logic=(job.id or "not-set"),
|
895
|
+
)
|
896
|
+
|
897
|
+
if event and event.is_set():
|
898
|
+
return result.catch(status=Status.FAILED)
|
899
|
+
|
900
|
+
import requests
|
901
|
+
|
902
|
+
resp = requests.post(
|
903
|
+
job.runs_on.args.host,
|
904
|
+
data={"job": job.model_dump(), "params": params},
|
905
|
+
)
|
906
|
+
|
907
|
+
if resp.status_code != 200:
|
908
|
+
do_raise: bool = (
|
909
|
+
config.job_raise_error if raise_error is None else raise_error
|
910
|
+
)
|
911
|
+
if do_raise:
|
912
|
+
raise JobException(
|
913
|
+
f"Job execution error from request to self-hosted: "
|
914
|
+
f"{job.runs_on.args.host!r}"
|
915
|
+
)
|
916
|
+
|
917
|
+
return result.catch(status=Status.FAILED)
|
918
|
+
return result.catch(status=Status.SUCCESS)
|