ddeutil-workflow 0.0.65__tar.gz → 0.0.67__tar.gz

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.
Files changed (58) hide show
  1. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/PKG-INFO +13 -35
  2. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/README.md +9 -22
  3. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/pyproject.toml +6 -22
  4. ddeutil_workflow-0.0.67/src/ddeutil/workflow/__about__.py +1 -0
  5. ddeutil_workflow-0.0.67/src/ddeutil/workflow/__main__.py +4 -0
  6. ddeutil_workflow-0.0.67/src/ddeutil/workflow/cli.py +68 -0
  7. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/conf.py +1 -5
  8. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/errors.py +0 -6
  9. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/job.py +6 -10
  10. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/logs.py +1 -1
  11. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/result.py +13 -10
  12. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/stages.py +120 -26
  13. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/workflow.py +25 -11
  14. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil_workflow.egg-info/PKG-INFO +13 -35
  15. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil_workflow.egg-info/SOURCES.txt +1 -0
  16. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil_workflow.egg-info/requires.txt +2 -14
  17. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_conf.py +0 -6
  18. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_job_exec_strategy.py +4 -2
  19. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_result.py +4 -1
  20. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_workflow_release.py +52 -0
  21. ddeutil_workflow-0.0.65/src/ddeutil/workflow/__about__.py +0 -1
  22. ddeutil_workflow-0.0.65/src/ddeutil/workflow/__main__.py +0 -30
  23. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/LICENSE +0 -0
  24. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/setup.cfg +0 -0
  25. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/__cron.py +0 -0
  26. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/__init__.py +0 -0
  27. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/__types.py +0 -0
  28. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/api/__init__.py +0 -0
  29. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/api/logs.py +0 -0
  30. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/api/routes/__init__.py +0 -0
  31. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/api/routes/job.py +0 -0
  32. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/api/routes/logs.py +0 -0
  33. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/api/routes/workflows.py +0 -0
  34. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/event.py +0 -0
  35. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/params.py +0 -0
  36. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/reusables.py +0 -0
  37. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil/workflow/utils.py +0 -0
  38. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil_workflow.egg-info/dependency_links.txt +0 -0
  39. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil_workflow.egg-info/entry_points.txt +0 -0
  40. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/src/ddeutil_workflow.egg-info/top_level.txt +0 -0
  41. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test__cron.py +0 -0
  42. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test__regex.py +0 -0
  43. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_errors.py +0 -0
  44. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_event.py +0 -0
  45. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_job.py +0 -0
  46. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_job_exec.py +0 -0
  47. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_logs_audit.py +0 -0
  48. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_logs_trace.py +0 -0
  49. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_params.py +0 -0
  50. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_reusables_call_tag.py +0 -0
  51. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_reusables_func_model.py +0 -0
  52. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_reusables_template.py +0 -0
  53. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_reusables_template_filter.py +0 -0
  54. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_strategy.py +0 -0
  55. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_utils.py +0 -0
  56. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_workflow.py +0 -0
  57. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_workflow_exec.py +0 -0
  58. {ddeutil_workflow-0.0.65 → ddeutil_workflow-0.0.67}/tests/test_workflow_exec_job.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ddeutil-workflow
3
- Version: 0.0.65
4
- Summary: Lightweight workflow orchestration
3
+ Version: 0.0.67
4
+ Summary: Lightweight workflow orchestration with YAML template
5
5
  Author-email: ddeutils <korawich.anu@gmail.com>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/ddeutils/ddeutil-workflow/
@@ -27,7 +27,7 @@ Requires-Dist: ddeutil-io[toml,yaml]>=0.2.14
27
27
  Requires-Dist: pydantic==2.11.4
28
28
  Requires-Dist: pydantic-extra-types==2.10.4
29
29
  Requires-Dist: python-dotenv==1.1.0
30
- Requires-Dist: schedule<2.0.0,==1.2.2
30
+ Requires-Dist: typer==0.15.4
31
31
  Provides-Extra: all
32
32
  Requires-Dist: fastapi<1.0.0,>=0.115.0; extra == "all"
33
33
  Requires-Dist: uvicorn; extra == "all"
@@ -35,18 +35,9 @@ Requires-Dist: httpx; extra == "all"
35
35
  Requires-Dist: ujson; extra == "all"
36
36
  Requires-Dist: aiofiles; extra == "all"
37
37
  Requires-Dist: aiohttp; extra == "all"
38
- Provides-Extra: api
39
- Requires-Dist: fastapi<1.0.0,>=0.115.0; extra == "api"
40
- Requires-Dist: uvicorn; extra == "api"
41
- Requires-Dist: httpx; extra == "api"
42
- Requires-Dist: ujson; extra == "api"
43
- Provides-Extra: async
44
- Requires-Dist: aiofiles; extra == "async"
45
- Requires-Dist: aiohttp; extra == "async"
38
+ Requires-Dist: requests==2.32.3; extra == "all"
46
39
  Provides-Extra: docker
47
40
  Requires-Dist: docker==7.1.0; extra == "docker"
48
- Provides-Extra: self-hosted
49
- Requires-Dist: requests==2.32.3; extra == "self-hosted"
50
41
  Dynamic: license-file
51
42
 
52
43
  # Workflow Orchestration
@@ -142,10 +133,10 @@ the base deps.
142
133
  If you want to install this package with application add-ons, you should add
143
134
  `app` in installation;
144
135
 
145
- | Use-case | Install Optional | Support |
146
- |----------------|--------------------------|:-------------------:|
147
- | Python | `ddeutil-workflow` | :heavy_check_mark: |
148
- | FastAPI Server | `ddeutil-workflow[api]` | :heavy_check_mark: |
136
+ | Use-case | Install Optional | Support |
137
+ |----------------|-------------------------|:-------:|
138
+ | Python | `ddeutil-workflow` ||
139
+ | FastAPI Server | `ddeutil-workflow[all]` | ✅ |
149
140
 
150
141
  ## 🎯 Usage
151
142
 
@@ -300,40 +291,27 @@ it will use default value and do not raise any error to you.
300
291
  ## :rocket: Deployment
301
292
 
302
293
  This package able to run as an application service for receive manual trigger
303
- from any node via RestAPI or use to be Scheduler background application
304
- like crontab job but via Python API or FastAPI app.
294
+ from any node via RestAPI with the FastAPI package.
305
295
 
306
296
  ### API Server
307
297
 
308
298
  This server use FastAPI package to be the base application.
309
299
 
310
300
  ```shell
311
- (.venv) $ uvicorn ddeutil.workflow.api:app \
312
- --host 127.0.0.1 \
313
- --port 80 \
314
- --no-access-log
301
+ (.venv) $ workflow-cli api --host 127.0.0.1 --port 80
315
302
  ```
316
303
 
317
304
  > [!NOTE]
318
305
  > If this package already deploy, it is able to use multiprocess;
319
- > `uvicorn ddeutil.workflow.api:app --host 127.0.0.1 --port 80 --workers 4`
320
-
321
- ### Local Schedule
322
-
323
- > [!WARNING]
324
- > This CLI does not implement yet.
325
-
326
- ```shell
327
- (.venv) $ ddeutil-workflow schedule
328
- ```
306
+ > `$ workflow-cli api --host 127.0.0.1 --port 80 --workers 4`
329
307
 
330
308
  ### Docker Container
331
309
 
332
310
  Build a Docker container from this package.
333
311
 
334
312
  ```shell
335
- $ docker build -t ddeutil-workflow:latest -f .container/Dockerfile .
336
- $ docker run -i ddeutil-workflow:latest ddeutil-workflow
313
+ $ docker pull ghcr.io/ddeutils/ddeutil-workflow:latest
314
+ $ docker run --rm ghcr.io/ddeutils/ddeutil-workflow:latest ddeutil-worker
337
315
  ```
338
316
 
339
317
  ## :speech_balloon: Contribute
@@ -91,10 +91,10 @@ the base deps.
91
91
  If you want to install this package with application add-ons, you should add
92
92
  `app` in installation;
93
93
 
94
- | Use-case | Install Optional | Support |
95
- |----------------|--------------------------|:-------------------:|
96
- | Python | `ddeutil-workflow` | :heavy_check_mark: |
97
- | FastAPI Server | `ddeutil-workflow[api]` | :heavy_check_mark: |
94
+ | Use-case | Install Optional | Support |
95
+ |----------------|-------------------------|:-------:|
96
+ | Python | `ddeutil-workflow` ||
97
+ | FastAPI Server | `ddeutil-workflow[all]` | ✅ |
98
98
 
99
99
  ## 🎯 Usage
100
100
 
@@ -249,40 +249,27 @@ it will use default value and do not raise any error to you.
249
249
  ## :rocket: Deployment
250
250
 
251
251
  This package able to run as an application service for receive manual trigger
252
- from any node via RestAPI or use to be Scheduler background application
253
- like crontab job but via Python API or FastAPI app.
252
+ from any node via RestAPI with the FastAPI package.
254
253
 
255
254
  ### API Server
256
255
 
257
256
  This server use FastAPI package to be the base application.
258
257
 
259
258
  ```shell
260
- (.venv) $ uvicorn ddeutil.workflow.api:app \
261
- --host 127.0.0.1 \
262
- --port 80 \
263
- --no-access-log
259
+ (.venv) $ workflow-cli api --host 127.0.0.1 --port 80
264
260
  ```
265
261
 
266
262
  > [!NOTE]
267
263
  > If this package already deploy, it is able to use multiprocess;
268
- > `uvicorn ddeutil.workflow.api:app --host 127.0.0.1 --port 80 --workers 4`
269
-
270
- ### Local Schedule
271
-
272
- > [!WARNING]
273
- > This CLI does not implement yet.
274
-
275
- ```shell
276
- (.venv) $ ddeutil-workflow schedule
277
- ```
264
+ > `$ workflow-cli api --host 127.0.0.1 --port 80 --workers 4`
278
265
 
279
266
  ### Docker Container
280
267
 
281
268
  Build a Docker container from this package.
282
269
 
283
270
  ```shell
284
- $ docker build -t ddeutil-workflow:latest -f .container/Dockerfile .
285
- $ docker run -i ddeutil-workflow:latest ddeutil-workflow
271
+ $ docker pull ghcr.io/ddeutils/ddeutil-workflow:latest
272
+ $ docker run --rm ghcr.io/ddeutils/ddeutil-workflow:latest ddeutil-worker
286
273
  ```
287
274
 
288
275
  ## :speech_balloon: Contribute
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ddeutil-workflow"
7
- description = "Lightweight workflow orchestration"
7
+ description = "Lightweight workflow orchestration with YAML template"
8
8
  readme = {file = "README.md", content-type = "text/markdown"}
9
9
  license = {text = "MIT"}
10
10
  authors = [{ name = "ddeutils", email = "korawich.anu@gmail.com" }]
@@ -30,7 +30,7 @@ dependencies = [
30
30
  "pydantic==2.11.4",
31
31
  "pydantic-extra-types==2.10.4",
32
32
  "python-dotenv==1.1.0",
33
- "schedule==1.2.2,<2.0.0",
33
+ "typer==0.15.4",
34
34
  ]
35
35
  dynamic = ["version"]
36
36
 
@@ -42,23 +42,11 @@ all = [
42
42
  "ujson",
43
43
  "aiofiles",
44
44
  "aiohttp",
45
- ]
46
- api = [
47
- "fastapi>=0.115.0,<1.0.0",
48
- "uvicorn",
49
- "httpx",
50
- "ujson",
51
- ]
52
- async = [
53
- "aiofiles",
54
- "aiohttp",
45
+ "requests==2.32.3",
55
46
  ]
56
47
  docker = [
57
48
  "docker==7.1.0",
58
49
  ]
59
- self_hosted = [
60
- "requests==2.32.3",
61
- ]
62
50
 
63
51
  [project.urls]
64
52
  Homepage = "https://github.com/ddeutils/ddeutil-workflow/"
@@ -90,15 +78,13 @@ omit = [
90
78
  "src/ddeutil/workflow/__about__.py",
91
79
  "src/ddeutil/workflow/__cron.py",
92
80
  "src/ddeutil/workflow/__main__.py",
81
+ "src/ddeutil/workflow/cli.py",
93
82
  "src/ddeutil/workflow/api/__init__.py",
94
83
  "src/ddeutil/workflow/api/logs.py",
95
- "src/ddeutil/workflow/api/utils.py",
96
84
  "src/ddeutil/workflow/api/routes/__init__.py",
97
85
  "src/ddeutil/workflow/api/routes/job.py",
98
86
  "src/ddeutil/workflow/api/routes/logs.py",
99
- "src/ddeutil/workflow/api/routes/schedules.py",
100
87
  "src/ddeutil/workflow/api/routes/workflows.py",
101
- "app.py",
102
88
  ]
103
89
 
104
90
  [tool.coverage.report]
@@ -110,12 +96,10 @@ exclude_lines = [
110
96
  [tool.pytest.ini_options]
111
97
  pythonpath = ["src"]
112
98
  asyncio_default_fixture_loop_scope = "fuction"
113
- # NOTE: You can deslect multiple markers by '-m "not (poke or api)"'
99
+ # NOTE: You can deslect multiple markers by '-m "not (asyncio or api)"'
114
100
  markers = [
115
- "poke: marks tests as slow by poking (deselect with '-m \"not poke\"')",
116
- "schedule: marks tests as schedule (deselect with '-m \"not schedule\"')",
117
101
  "api: marks tests as api (deselect with '-m \"not api\"')",
118
- "asyncio: marks async testcases",
102
+ "asyncio: marks async test cases",
119
103
  ]
120
104
  console_output_style = "count"
121
105
  addopts = [
@@ -0,0 +1 @@
1
+ __version__: str = "0.0.67"
@@ -0,0 +1,4 @@
1
+ from .cli import app
2
+
3
+ if __name__ == "__main__":
4
+ app()
@@ -0,0 +1,68 @@
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
+ worker: Annotated[int, typer.Option(help="A worker number")] = None,
52
+ ):
53
+ """
54
+ Provision API application from the FastAPI.
55
+ """
56
+
57
+ uvicorn.run(
58
+ fastapp,
59
+ host=host,
60
+ port=port,
61
+ log_config=uvicorn.config.LOGGING_CONFIG | LOGGING_CONFIG,
62
+ log_level=("DEBUG" if debug else "INFO"),
63
+ workers=worker,
64
+ )
65
+
66
+
67
+ if __name__ == "__main__":
68
+ app()
@@ -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, TypeAdapter
21
+ from pydantic import SecretStr
22
22
 
23
23
  from .__types import DictData
24
24
 
@@ -470,7 +470,3 @@ class CallerSecret(SecretStr): # pragma: no cov
470
470
  :rtype: str
471
471
  """
472
472
  return pass_env(super().get_secret_value())
473
-
474
-
475
- # NOTE: Define the caller secret type for use it directly in the caller func.
476
- CallerSecretType = TypeAdapter(CallerSecret)
@@ -90,9 +90,6 @@ class ResultError(UtilError): ...
90
90
  class StageError(BaseError): ...
91
91
 
92
92
 
93
- class StageRetryError(StageError): ...
94
-
95
-
96
93
  class StageCancelError(StageError): ...
97
94
 
98
95
 
@@ -114,9 +111,6 @@ class WorkflowError(BaseError): ...
114
111
  class WorkflowCancelError(WorkflowError): ...
115
112
 
116
113
 
117
- class WorkflowSkipError(WorkflowError): ...
118
-
119
-
120
114
  class WorkflowTimeoutError(WorkflowError): ...
121
115
 
122
116
 
@@ -39,7 +39,6 @@ from pydantic import BaseModel, Discriminator, Field, SecretStr, Tag
39
39
  from pydantic.functional_validators import field_validator, model_validator
40
40
  from typing_extensions import Self
41
41
 
42
- from . import JobSkipError
43
42
  from .__types import DictData, DictStr, Matrix, StrOrNone
44
43
  from .errors import JobCancelError, JobError, to_dict
45
44
  from .result import (
@@ -774,7 +773,7 @@ def local_execute_strategy(
774
773
  *,
775
774
  result: Optional[Result] = None,
776
775
  event: Optional[Event] = None,
777
- ) -> Result:
776
+ ) -> tuple[Status, Result]:
778
777
  """Local strategy execution with passing dynamic parameters from the
779
778
  job execution and strategy matrix.
780
779
 
@@ -799,7 +798,7 @@ def local_execute_strategy(
799
798
  :raise JobError: If stage execution raise any error as `StageError`.
800
799
  :raise JobError: If the result from execution has `FAILED` status.
801
800
 
802
- :rtype: Result
801
+ :rtype: tuple[Status, Result]
803
802
  """
804
803
  result: Result = result or Result(
805
804
  run_id=gen_id(job.id or "EMPTY", unique=True),
@@ -899,9 +898,7 @@ def local_execute_strategy(
899
898
  },
900
899
  },
901
900
  )
902
- if status == SKIP:
903
- raise JobSkipError("All stage was skipped.")
904
- return result
901
+ return status, result
905
902
 
906
903
 
907
904
  def local_execute(
@@ -1017,14 +1014,13 @@ def local_execute(
1017
1014
 
1018
1015
  for i, future in enumerate(done, start=0):
1019
1016
  try:
1020
- statuses[i] = future.result().status
1017
+ statuses[i], _ = future.result()
1021
1018
  except JobError as e:
1022
1019
  statuses[i] = get_status_from_error(e)
1023
1020
  result.trace.error(
1024
- f"[JOB]: {ls} Error Handler:||{e.__class__.__name__}: {e}"
1021
+ f"[JOB]: {ls} Handler:||{e.__class__.__name__}: {e}"
1025
1022
  )
1026
- if not isinstance(e, JobSkipError):
1027
- mark_errors(context, e)
1023
+ mark_errors(context, e)
1028
1024
  except CancelledError:
1029
1025
  pass
1030
1026
 
@@ -848,7 +848,7 @@ class FileAudit(BaseAudit):
848
848
  "audit_path", extras=self.extras
849
849
  ) / self.filename_fmt.format(name=self.name, release=self.release)
850
850
 
851
- def save(self, excluded: Optional[list[str]]) -> Self:
851
+ def save(self, excluded: Optional[list[str]] = None) -> Self:
852
852
  """Save logging data that receive a context data from a workflow
853
853
  execution result.
854
854
 
@@ -11,7 +11,7 @@ from __future__ import annotations
11
11
 
12
12
  from dataclasses import field
13
13
  from datetime import datetime
14
- from enum import IntEnum, auto
14
+ from enum import Enum
15
15
  from typing import Optional, Union
16
16
 
17
17
  from pydantic import ConfigDict
@@ -28,7 +28,6 @@ from . import (
28
28
  StageSkipError,
29
29
  WorkflowCancelError,
30
30
  WorkflowError,
31
- WorkflowSkipError,
32
31
  )
33
32
  from .__types import DictData
34
33
  from .conf import dynamic
@@ -37,16 +36,16 @@ from .logs import TraceModel, get_dt_tznow, get_trace
37
36
  from .utils import default_gen_id, gen_id, get_dt_now
38
37
 
39
38
 
40
- class Status(IntEnum):
39
+ class Status(str, Enum):
41
40
  """Status Int Enum object that use for tracking execution status to the
42
41
  Result dataclass object.
43
42
  """
44
43
 
45
- SUCCESS = auto()
46
- FAILED = auto()
47
- WAIT = auto()
48
- SKIP = auto()
49
- CANCEL = auto()
44
+ SUCCESS = "SUCCESS"
45
+ FAILED = "FAILED"
46
+ WAIT = "WAIT"
47
+ SKIP = "SKIP"
48
+ CANCEL = "CANCEL"
50
49
 
51
50
  @property
52
51
  def emoji(self) -> str: # pragma: no cov
@@ -68,6 +67,9 @@ class Status(IntEnum):
68
67
  def __str__(self) -> str:
69
68
  return self.name
70
69
 
70
+ def is_result(self) -> bool:
71
+ return self in ResultStatuses
72
+
71
73
 
72
74
  SUCCESS = Status.SUCCESS
73
75
  FAILED = Status.FAILED
@@ -75,6 +77,8 @@ WAIT = Status.WAIT
75
77
  SKIP = Status.SKIP
76
78
  CANCEL = Status.CANCEL
77
79
 
80
+ ResultStatuses: list[Status] = [SUCCESS, FAILED, CANCEL, SKIP]
81
+
78
82
 
79
83
  def validate_statuses(statuses: list[Status]) -> Status:
80
84
  """Validate the final status from list of Status object.
@@ -106,13 +110,12 @@ def get_status_from_error(
106
110
  JobSkipError,
107
111
  WorkflowError,
108
112
  WorkflowCancelError,
109
- WorkflowSkipError,
110
113
  Exception,
111
114
  BaseException,
112
115
  ]
113
116
  ) -> Status:
114
117
  """Get the Status from the error object."""
115
- if isinstance(error, (StageSkipError, JobSkipError, WorkflowSkipError)):
118
+ if isinstance(error, (StageSkipError, JobSkipError)):
116
119
  return SKIP
117
120
  elif isinstance(
118
121
  error, (StageCancelError, JobCancelError, WorkflowCancelError)