ddeutil-workflow 0.0.64__py3-none-any.whl → 0.0.66__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 +1 -1
- ddeutil/workflow/__main__.py +1 -27
- ddeutil/workflow/api/routes/job.py +2 -2
- ddeutil/workflow/cli.py +66 -0
- ddeutil/workflow/conf.py +1 -9
- ddeutil/workflow/{exceptions.py → errors.py} +46 -11
- ddeutil/workflow/job.py +247 -120
- ddeutil/workflow/logs.py +1 -1
- ddeutil/workflow/params.py +11 -11
- ddeutil/workflow/result.py +84 -10
- ddeutil/workflow/reusables.py +15 -17
- ddeutil/workflow/stages.py +685 -450
- ddeutil/workflow/utils.py +33 -0
- ddeutil/workflow/workflow.py +177 -664
- {ddeutil_workflow-0.0.64.dist-info → ddeutil_workflow-0.0.66.dist-info}/METADATA +15 -13
- ddeutil_workflow-0.0.66.dist-info/RECORD +29 -0
- {ddeutil_workflow-0.0.64.dist-info → ddeutil_workflow-0.0.66.dist-info}/WHEEL +1 -1
- ddeutil_workflow-0.0.64.dist-info/RECORD +0 -28
- {ddeutil_workflow-0.0.64.dist-info → ddeutil_workflow-0.0.66.dist-info}/entry_points.txt +0 -0
- {ddeutil_workflow-0.0.64.dist-info → ddeutil_workflow-0.0.66.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.64.dist-info → ddeutil_workflow-0.0.66.dist-info}/top_level.txt +0 -0
ddeutil/workflow/__about__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__: str = "0.0.
|
1
|
+
__version__: str = "0.0.66"
|
ddeutil/workflow/__init__.py
CHANGED
ddeutil/workflow/__main__.py
CHANGED
@@ -1,30 +1,4 @@
|
|
1
|
-
import
|
2
|
-
|
3
|
-
app = typer.Typer()
|
4
|
-
|
5
|
-
|
6
|
-
@app.callback()
|
7
|
-
def callback():
|
8
|
-
"""
|
9
|
-
Awesome Portal Gun
|
10
|
-
"""
|
11
|
-
|
12
|
-
|
13
|
-
@app.command()
|
14
|
-
def provision():
|
15
|
-
"""
|
16
|
-
Shoot the portal gun
|
17
|
-
"""
|
18
|
-
typer.echo("Shooting portal gun")
|
19
|
-
|
20
|
-
|
21
|
-
@app.command()
|
22
|
-
def job():
|
23
|
-
"""
|
24
|
-
Load the portal gun
|
25
|
-
"""
|
26
|
-
typer.echo("Loading portal gun")
|
27
|
-
|
1
|
+
from .cli import app
|
28
2
|
|
29
3
|
if __name__ == "__main__":
|
30
4
|
app()
|
@@ -12,7 +12,7 @@ from fastapi.responses import UJSONResponse
|
|
12
12
|
from pydantic import BaseModel, Field
|
13
13
|
|
14
14
|
from ...__types import DictData
|
15
|
-
from ...
|
15
|
+
from ...errors import JobError
|
16
16
|
from ...job import Job
|
17
17
|
from ...logs import get_logger
|
18
18
|
from ...result import Result
|
@@ -59,7 +59,7 @@ async def job_execute(
|
|
59
59
|
).context,
|
60
60
|
to=context,
|
61
61
|
)
|
62
|
-
except
|
62
|
+
except JobError as err:
|
63
63
|
rs.trace.error(f"[JOB]: {err.__class__.__name__}: {err}")
|
64
64
|
|
65
65
|
return {
|
ddeutil/workflow/cli.py
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
import json
|
2
|
+
from typing import Annotated, Any
|
3
|
+
|
4
|
+
import typer
|
5
|
+
import uvicorn
|
6
|
+
|
7
|
+
from .__about__ import __version__
|
8
|
+
from .api import app as fastapp
|
9
|
+
from .api.logs import LOGGING_CONFIG
|
10
|
+
|
11
|
+
app = typer.Typer(
|
12
|
+
pretty_exceptions_enable=True,
|
13
|
+
)
|
14
|
+
|
15
|
+
|
16
|
+
@app.callback()
|
17
|
+
def callback():
|
18
|
+
"""
|
19
|
+
Awesome Portal Gun
|
20
|
+
"""
|
21
|
+
typer.echo("Start call from callback function")
|
22
|
+
|
23
|
+
|
24
|
+
@app.command()
|
25
|
+
def version():
|
26
|
+
"""Get the ddeutil-workflow package version."""
|
27
|
+
typer.echo(__version__)
|
28
|
+
|
29
|
+
|
30
|
+
@app.command()
|
31
|
+
def job(
|
32
|
+
params: Annotated[str, typer.Option(help="A job execute parameters")],
|
33
|
+
):
|
34
|
+
"""Job execution on the local.
|
35
|
+
|
36
|
+
Example:
|
37
|
+
... workflow-cli job --params "{\"test\": 1}"
|
38
|
+
"""
|
39
|
+
try:
|
40
|
+
params_dict: dict[str, Any] = json.loads(params)
|
41
|
+
except json.JSONDecodeError as e:
|
42
|
+
raise ValueError(f"params does not support format: {params!r}.") from e
|
43
|
+
typer.echo(f"Job params: {params_dict}")
|
44
|
+
|
45
|
+
|
46
|
+
@app.command()
|
47
|
+
def api(
|
48
|
+
host: Annotated[str, typer.Option(help="A host url.")] = "0.0.0.0",
|
49
|
+
port: Annotated[int, typer.Option(help="A port url.")] = 80,
|
50
|
+
debug: Annotated[bool, typer.Option(help="A debug mode flag")] = True,
|
51
|
+
):
|
52
|
+
"""
|
53
|
+
Provision API application from the FastAPI.
|
54
|
+
"""
|
55
|
+
|
56
|
+
uvicorn.run(
|
57
|
+
fastapp,
|
58
|
+
host=host,
|
59
|
+
port=port,
|
60
|
+
log_config=uvicorn.config.LOGGING_CONFIG | LOGGING_CONFIG,
|
61
|
+
log_level=("DEBUG" if debug else "INFO"),
|
62
|
+
)
|
63
|
+
|
64
|
+
|
65
|
+
if __name__ == "__main__":
|
66
|
+
app()
|
ddeutil/workflow/conf.py
CHANGED
@@ -18,7 +18,7 @@ from zoneinfo import ZoneInfo
|
|
18
18
|
from ddeutil.core import str2bool
|
19
19
|
from ddeutil.io import YamlFlResolve, search_env_replace
|
20
20
|
from ddeutil.io.paths import glob_files, is_ignored, read_ignore
|
21
|
-
from pydantic import SecretStr
|
21
|
+
from pydantic import SecretStr
|
22
22
|
|
23
23
|
from .__types import DictData
|
24
24
|
|
@@ -141,10 +141,6 @@ class Config: # pragma: no cov
|
|
141
141
|
def log_datetime_format(self) -> str:
|
142
142
|
return env("LOG_DATETIME_FORMAT", "%Y-%m-%d %H:%M:%S")
|
143
143
|
|
144
|
-
@property
|
145
|
-
def stage_raise_error(self) -> bool:
|
146
|
-
return str2bool(env("CORE_STAGE_RAISE_ERROR", "false"))
|
147
|
-
|
148
144
|
@property
|
149
145
|
def stage_default_id(self) -> bool:
|
150
146
|
return str2bool(env("CORE_STAGE_DEFAULT_ID", "false"))
|
@@ -474,7 +470,3 @@ class CallerSecret(SecretStr): # pragma: no cov
|
|
474
470
|
:rtype: str
|
475
471
|
"""
|
476
472
|
return pass_env(super().get_secret_value())
|
477
|
-
|
478
|
-
|
479
|
-
# NOTE: Define the caller secret type for use it directly in the caller func.
|
480
|
-
CallerSecretType = TypeAdapter(CallerSecret)
|
@@ -11,6 +11,8 @@ from __future__ import annotations
|
|
11
11
|
|
12
12
|
from typing import Literal, Optional, TypedDict, Union, overload
|
13
13
|
|
14
|
+
from .__types import DictData, StrOrInt
|
15
|
+
|
14
16
|
|
15
17
|
class ErrorData(TypedDict):
|
16
18
|
"""Error data type dict for typing necessary keys of return of to_dict func
|
@@ -21,7 +23,7 @@ class ErrorData(TypedDict):
|
|
21
23
|
message: str
|
22
24
|
|
23
25
|
|
24
|
-
def to_dict(exception: Exception) -> ErrorData: # pragma: no cov
|
26
|
+
def to_dict(exception: Exception, **kwargs) -> ErrorData: # pragma: no cov
|
25
27
|
"""Create dict data from exception instance.
|
26
28
|
|
27
29
|
:param exception: An exception object.
|
@@ -31,17 +33,27 @@ def to_dict(exception: Exception) -> ErrorData: # pragma: no cov
|
|
31
33
|
return {
|
32
34
|
"name": exception.__class__.__name__,
|
33
35
|
"message": str(exception),
|
36
|
+
**kwargs,
|
34
37
|
}
|
35
38
|
|
36
39
|
|
37
|
-
class
|
40
|
+
class BaseError(Exception):
|
38
41
|
"""Base Workflow exception class will implement the `refs` argument for
|
39
42
|
making an error context to the result context.
|
40
43
|
"""
|
41
44
|
|
42
|
-
def __init__(
|
45
|
+
def __init__(
|
46
|
+
self,
|
47
|
+
message: str,
|
48
|
+
*,
|
49
|
+
refs: Optional[StrOrInt] = None,
|
50
|
+
context: Optional[DictData] = None,
|
51
|
+
params: Optional[DictData] = None,
|
52
|
+
) -> None:
|
43
53
|
super().__init__(message)
|
44
54
|
self.refs: Optional[str] = refs
|
55
|
+
self.context: DictData = context or {}
|
56
|
+
self.params: DictData = params or {}
|
45
57
|
|
46
58
|
@overload
|
47
59
|
def to_dict(
|
@@ -54,7 +66,9 @@ class BaseWorkflowException(Exception):
|
|
54
66
|
) -> ErrorData: ... # pragma: no cov
|
55
67
|
|
56
68
|
def to_dict(
|
57
|
-
self,
|
69
|
+
self,
|
70
|
+
with_refs: bool = False,
|
71
|
+
**kwargs,
|
58
72
|
) -> Union[ErrorData, dict[str, ErrorData]]:
|
59
73
|
"""Return ErrorData data from the current exception object. If with_refs
|
60
74
|
flag was set, it will return mapping of refs and itself data.
|
@@ -64,22 +78,43 @@ class BaseWorkflowException(Exception):
|
|
64
78
|
data: ErrorData = to_dict(self)
|
65
79
|
if with_refs and (self.refs is not None and self.refs != "EMPTY"):
|
66
80
|
return {self.refs: data}
|
67
|
-
return data
|
81
|
+
return data | kwargs
|
82
|
+
|
83
|
+
|
84
|
+
class UtilError(BaseError): ...
|
85
|
+
|
86
|
+
|
87
|
+
class ResultError(UtilError): ...
|
88
|
+
|
89
|
+
|
90
|
+
class StageError(BaseError): ...
|
91
|
+
|
92
|
+
|
93
|
+
class StageRetryError(StageError): ...
|
94
|
+
|
95
|
+
|
96
|
+
class StageCancelError(StageError): ...
|
97
|
+
|
98
|
+
|
99
|
+
class StageSkipError(StageError): ...
|
100
|
+
|
101
|
+
|
102
|
+
class JobError(BaseError): ...
|
68
103
|
|
69
104
|
|
70
|
-
class
|
105
|
+
class JobCancelError(JobError): ...
|
71
106
|
|
72
107
|
|
73
|
-
class
|
108
|
+
class JobSkipError(JobError): ...
|
74
109
|
|
75
110
|
|
76
|
-
class
|
111
|
+
class WorkflowError(BaseError): ...
|
77
112
|
|
78
113
|
|
79
|
-
class
|
114
|
+
class WorkflowCancelError(WorkflowError): ...
|
80
115
|
|
81
116
|
|
82
|
-
class
|
117
|
+
class WorkflowTimeoutError(WorkflowError): ...
|
83
118
|
|
84
119
|
|
85
|
-
class
|
120
|
+
class ParamError(WorkflowError): ...
|