ddeutil-workflow 0.0.49__py3-none-any.whl → 0.0.51__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 +8 -26
- ddeutil/workflow/conf.py +11 -11
- ddeutil/workflow/cron.py +46 -20
- ddeutil/workflow/exceptions.py +3 -3
- ddeutil/workflow/job.py +269 -145
- ddeutil/workflow/logs.py +23 -19
- ddeutil/workflow/params.py +56 -16
- ddeutil/workflow/result.py +12 -4
- ddeutil/workflow/reusables.py +4 -2
- ddeutil/workflow/scheduler.py +5 -1
- ddeutil/workflow/stages.py +580 -217
- ddeutil/workflow/utils.py +42 -38
- ddeutil/workflow/workflow.py +92 -95
- {ddeutil_workflow-0.0.49.dist-info → ddeutil_workflow-0.0.51.dist-info}/METADATA +71 -14
- ddeutil_workflow-0.0.51.dist-info/RECORD +31 -0
- ddeutil_workflow-0.0.49.dist-info/RECORD +0 -31
- {ddeutil_workflow-0.0.49.dist-info → ddeutil_workflow-0.0.51.dist-info}/WHEEL +0 -0
- {ddeutil_workflow-0.0.49.dist-info → ddeutil_workflow-0.0.51.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.49.dist-info → ddeutil_workflow-0.0.51.dist-info}/top_level.txt +0 -0
ddeutil/workflow/__about__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__: str = "0.0.
|
1
|
+
__version__: str = "0.0.51"
|
ddeutil/workflow/__init__.py
CHANGED
@@ -11,25 +11,9 @@ from .conf import (
|
|
11
11
|
config,
|
12
12
|
env,
|
13
13
|
)
|
14
|
-
from .cron import
|
15
|
-
|
16
|
-
|
17
|
-
interval2crontab,
|
18
|
-
)
|
19
|
-
from .exceptions import (
|
20
|
-
JobException,
|
21
|
-
ParamValueException,
|
22
|
-
StageException,
|
23
|
-
UtilException,
|
24
|
-
WorkflowException,
|
25
|
-
)
|
26
|
-
from .job import (
|
27
|
-
Job,
|
28
|
-
RunsOn,
|
29
|
-
Strategy,
|
30
|
-
local_execute,
|
31
|
-
local_execute_strategy,
|
32
|
-
)
|
14
|
+
from .cron import *
|
15
|
+
from .exceptions import *
|
16
|
+
from .job import *
|
33
17
|
from .logs import (
|
34
18
|
Audit,
|
35
19
|
AuditModel,
|
@@ -41,14 +25,9 @@ from .logs import (
|
|
41
25
|
get_dt_tznow,
|
42
26
|
get_trace,
|
43
27
|
)
|
44
|
-
from .params import
|
45
|
-
ChoiceParam,
|
46
|
-
DatetimeParam,
|
47
|
-
IntParam,
|
48
|
-
Param,
|
49
|
-
StrParam,
|
50
|
-
)
|
28
|
+
from .params import *
|
51
29
|
from .result import (
|
30
|
+
CANCEL,
|
52
31
|
FAILED,
|
53
32
|
SKIP,
|
54
33
|
SUCCESS,
|
@@ -101,6 +80,9 @@ from .utils import (
|
|
101
80
|
get_diff_sec,
|
102
81
|
get_dt_now,
|
103
82
|
make_exec,
|
83
|
+
reach_next_minute,
|
84
|
+
replace_sec,
|
85
|
+
wait_to_next_minute,
|
104
86
|
)
|
105
87
|
from .workflow import (
|
106
88
|
Release,
|
ddeutil/workflow/conf.py
CHANGED
@@ -53,7 +53,6 @@ class Config: # pragma: no cov
|
|
53
53
|
The config value can change when you call that config property again.
|
54
54
|
"""
|
55
55
|
|
56
|
-
# NOTE: Core
|
57
56
|
@property
|
58
57
|
def conf_path(self) -> Path:
|
59
58
|
"""Config path that keep all workflow template YAML files.
|
@@ -73,9 +72,13 @@ class Config: # pragma: no cov
|
|
73
72
|
|
74
73
|
@property
|
75
74
|
def generate_id_simple_mode(self) -> bool:
|
75
|
+
"""Flag for generate running ID with simple mode. That does not use
|
76
|
+
`md5` function after generate simple mode.
|
77
|
+
|
78
|
+
:rtype: bool
|
79
|
+
"""
|
76
80
|
return str2bool(env("CORE_GENERATE_ID_SIMPLE_MODE", "true"))
|
77
81
|
|
78
|
-
# NOTE: Register
|
79
82
|
@property
|
80
83
|
def registry_caller(self) -> list[str]:
|
81
84
|
"""Register Caller that is a list of importable string for the call
|
@@ -98,13 +101,16 @@ class Config: # pragma: no cov
|
|
98
101
|
)
|
99
102
|
return [r.strip() for r in regis_filter_str.split(",")]
|
100
103
|
|
101
|
-
# NOTE: Log
|
102
104
|
@property
|
103
105
|
def trace_path(self) -> Path:
|
104
106
|
return Path(env("LOG_TRACE_PATH", "./logs"))
|
105
107
|
|
106
108
|
@property
|
107
109
|
def debug(self) -> bool:
|
110
|
+
"""Debug flag for echo log that use DEBUG mode.
|
111
|
+
|
112
|
+
:rtype: bool
|
113
|
+
"""
|
108
114
|
return str2bool(env("LOG_DEBUG_MODE", "true"))
|
109
115
|
|
110
116
|
@property
|
@@ -144,7 +150,6 @@ class Config: # pragma: no cov
|
|
144
150
|
def log_datetime_format(self) -> str:
|
145
151
|
return env("LOG_DATETIME_FORMAT", "%Y-%m-%d %H:%M:%S")
|
146
152
|
|
147
|
-
# NOTE: Stage
|
148
153
|
@property
|
149
154
|
def stage_raise_error(self) -> bool:
|
150
155
|
return str2bool(env("CORE_STAGE_RAISE_ERROR", "false"))
|
@@ -153,11 +158,6 @@ class Config: # pragma: no cov
|
|
153
158
|
def stage_default_id(self) -> bool:
|
154
159
|
return str2bool(env("CORE_STAGE_DEFAULT_ID", "false"))
|
155
160
|
|
156
|
-
# NOTE: Job
|
157
|
-
@property
|
158
|
-
def job_raise_error(self) -> bool:
|
159
|
-
return str2bool(env("CORE_JOB_RAISE_ERROR", "true"))
|
160
|
-
|
161
161
|
@property
|
162
162
|
def max_cron_per_workflow(self) -> int:
|
163
163
|
"""The maximum on value that store in workflow model.
|
@@ -360,13 +360,13 @@ def dynamic(
|
|
360
360
|
:param extras: An extra values that pass at run-time.
|
361
361
|
"""
|
362
362
|
rsx: Optional[T] = extras[key] if extras and key in extras else None
|
363
|
-
rs: Optional[T] =
|
363
|
+
rs: Optional[T] = getattr(config, key, None) if f is None else f
|
364
364
|
if rsx is not None and not isinstance(rsx, type(rs)):
|
365
365
|
raise TypeError(
|
366
366
|
f"Type of config {key!r} from extras: {rsx!r} does not valid "
|
367
367
|
f"as config {type(rs)}."
|
368
368
|
)
|
369
|
-
return rsx
|
369
|
+
return rsx if rsx is not None else rs
|
370
370
|
|
371
371
|
|
372
372
|
class Loader(SimLoad):
|
ddeutil/workflow/cron.py
CHANGED
@@ -16,18 +16,13 @@ from pydantic.functional_validators import field_validator, model_validator
|
|
16
16
|
from typing_extensions import Self
|
17
17
|
|
18
18
|
from .__cron import WEEKDAYS, CronJob, CronJobYear, CronRunner, Options
|
19
|
-
from .__types import DictData, DictStr
|
19
|
+
from .__types import DictData, DictStr
|
20
20
|
from .conf import Loader
|
21
21
|
|
22
|
-
__all__: TupleStr = (
|
23
|
-
"On",
|
24
|
-
"YearOn",
|
25
|
-
"interval2crontab",
|
26
|
-
)
|
27
|
-
|
28
22
|
|
29
23
|
def interval2crontab(
|
30
24
|
interval: Literal["daily", "weekly", "monthly"],
|
25
|
+
*,
|
31
26
|
day: str | None = None,
|
32
27
|
time: str = "00:00",
|
33
28
|
) -> str:
|
@@ -67,7 +62,7 @@ class On(BaseModel):
|
|
67
62
|
"""On Pydantic model (Warped crontab object by model).
|
68
63
|
|
69
64
|
See Also:
|
70
|
-
*
|
65
|
+
* `generate()` is the main use-case of this schedule object.
|
71
66
|
"""
|
72
67
|
|
73
68
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
@@ -76,12 +71,18 @@ class On(BaseModel):
|
|
76
71
|
DictData,
|
77
72
|
Field(
|
78
73
|
default_factory=dict,
|
79
|
-
description=
|
74
|
+
description=(
|
75
|
+
"An extras parameters that want to pass to the CronJob field."
|
76
|
+
),
|
80
77
|
),
|
81
78
|
]
|
82
79
|
cronjob: Annotated[
|
83
80
|
CronJob,
|
84
|
-
Field(
|
81
|
+
Field(
|
82
|
+
description=(
|
83
|
+
"A Cronjob object that use for validate and generate datetime.",
|
84
|
+
),
|
85
|
+
),
|
85
86
|
]
|
86
87
|
tz: Annotated[
|
87
88
|
str,
|
@@ -118,6 +119,8 @@ class On(BaseModel):
|
|
118
119
|
|
119
120
|
:param name: A name of config that will get from loader.
|
120
121
|
:param extras: An extra parameter that will keep in extras.
|
122
|
+
|
123
|
+
:rtype: Self
|
121
124
|
"""
|
122
125
|
extras: DictData = extras or {}
|
123
126
|
loader: Loader = Loader(name, externals=extras)
|
@@ -142,9 +145,7 @@ class On(BaseModel):
|
|
142
145
|
)
|
143
146
|
)
|
144
147
|
if "cronjob" not in loader_data:
|
145
|
-
raise ValueError(
|
146
|
-
"Config does not set ``cronjob`` or ``interval`` keys"
|
147
|
-
)
|
148
|
+
raise ValueError("Config does not set `cronjob` or `interval` keys")
|
148
149
|
return cls.model_validate(
|
149
150
|
obj=dict(
|
150
151
|
cronjob=loader_data.pop("cronjob"),
|
@@ -155,7 +156,13 @@ class On(BaseModel):
|
|
155
156
|
|
156
157
|
@model_validator(mode="before")
|
157
158
|
def __prepare_values(cls, values: DictData) -> DictData:
|
158
|
-
"""Extract tz key from value and change name to timezone key.
|
159
|
+
"""Extract tz key from value and change name to timezone key.
|
160
|
+
|
161
|
+
:param values: (DictData) A data that want to pass for create an On
|
162
|
+
model.
|
163
|
+
|
164
|
+
:rtype: DictData
|
165
|
+
"""
|
159
166
|
if tz := values.pop("tz", None):
|
160
167
|
values["timezone"] = tz
|
161
168
|
return values
|
@@ -170,8 +177,8 @@ class On(BaseModel):
|
|
170
177
|
try:
|
171
178
|
_ = ZoneInfo(value)
|
172
179
|
return value
|
173
|
-
except ZoneInfoNotFoundError as
|
174
|
-
raise ValueError(f"Invalid timezone: {value}") from
|
180
|
+
except ZoneInfoNotFoundError as e:
|
181
|
+
raise ValueError(f"Invalid timezone: {value}") from e
|
175
182
|
|
176
183
|
@field_validator(
|
177
184
|
"cronjob", mode="before", json_schema_input_type=Union[CronJob, str]
|
@@ -180,9 +187,13 @@ class On(BaseModel):
|
|
180
187
|
cls, value: str | CronJob, info: ValidationInfo
|
181
188
|
) -> CronJob:
|
182
189
|
"""Prepare crontab value that able to receive with string type.
|
183
|
-
This step will get options kwargs from extras and pass to the
|
190
|
+
This step will get options kwargs from extras field and pass to the
|
184
191
|
CronJob object.
|
185
192
|
|
193
|
+
:param value: (str | CronJobYear) A cronjob value that want to create.
|
194
|
+
:param info: (ValidationInfo) A validation info object that use to get
|
195
|
+
the extra parameters for create cronjob.
|
196
|
+
|
186
197
|
:rtype: CronJob
|
187
198
|
"""
|
188
199
|
extras: DictData = info.data.get("extras", {})
|
@@ -203,12 +214,17 @@ class On(BaseModel):
|
|
203
214
|
def __serialize_cronjob(self, value: CronJob) -> str:
|
204
215
|
"""Serialize the cronjob field that store with CronJob object.
|
205
216
|
|
217
|
+
:param value: (CronJob) The CronJob field.
|
218
|
+
|
206
219
|
:rtype: str
|
207
220
|
"""
|
208
221
|
return str(value)
|
209
222
|
|
210
223
|
def generate(self, start: str | datetime) -> CronRunner:
|
211
|
-
"""Return
|
224
|
+
"""Return CronRunner object from an initial datetime.
|
225
|
+
|
226
|
+
:param start: (str | datetime) A string or datetime for generate the
|
227
|
+
CronRunner object.
|
212
228
|
|
213
229
|
:rtype: CronRunner
|
214
230
|
"""
|
@@ -242,16 +258,26 @@ class YearOn(On):
|
|
242
258
|
# NOTE: This is fields of the base schedule.
|
243
259
|
cronjob: Annotated[
|
244
260
|
CronJobYear,
|
245
|
-
Field(
|
261
|
+
Field(
|
262
|
+
description=(
|
263
|
+
"A Cronjob object that use for validate and generate datetime.",
|
264
|
+
),
|
265
|
+
),
|
246
266
|
]
|
247
267
|
|
248
268
|
@field_validator(
|
249
|
-
"cronjob", mode="before", json_schema_input_type=Union[
|
269
|
+
"cronjob", mode="before", json_schema_input_type=Union[CronJobYear, str]
|
250
270
|
)
|
251
271
|
def __prepare_cronjob(
|
252
272
|
cls, value: str | CronJobYear, info: ValidationInfo
|
253
273
|
) -> CronJobYear:
|
254
274
|
"""Prepare crontab value that able to receive with string type.
|
275
|
+
This step will get options kwargs from extras field and pass to the
|
276
|
+
CronJobYear object.
|
277
|
+
|
278
|
+
:param value: (str | CronJobYear) A cronjob value that want to create.
|
279
|
+
:param info: (ValidationInfo) A validation info object that use to get
|
280
|
+
the extra parameters for create cronjob.
|
255
281
|
|
256
282
|
:rtype: CronJobYear
|
257
283
|
"""
|
ddeutil/workflow/exceptions.py
CHANGED
@@ -39,6 +39,9 @@ class BaseWorkflowException(Exception):
|
|
39
39
|
class UtilException(BaseWorkflowException): ...
|
40
40
|
|
41
41
|
|
42
|
+
class ResultException(UtilException): ...
|
43
|
+
|
44
|
+
|
42
45
|
class StageException(BaseWorkflowException): ...
|
43
46
|
|
44
47
|
|
@@ -48,9 +51,6 @@ class JobException(BaseWorkflowException): ...
|
|
48
51
|
class WorkflowException(BaseWorkflowException): ...
|
49
52
|
|
50
53
|
|
51
|
-
class WorkflowFailException(WorkflowException): ...
|
52
|
-
|
53
|
-
|
54
54
|
class ParamValueException(WorkflowException): ...
|
55
55
|
|
56
56
|
|