ddeutil-workflow 0.0.66__tar.gz → 0.0.68__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.
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/PKG-INFO +14 -36
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/README.md +9 -22
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/pyproject.toml +8 -22
- ddeutil_workflow-0.0.68/src/ddeutil/workflow/__about__.py +1 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/api/__init__.py +20 -19
- ddeutil_workflow-0.0.66/src/ddeutil/workflow/api/logs.py → ddeutil_workflow-0.0.68/src/ddeutil/workflow/api/log_conf.py +28 -15
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/api/routes/__init__.py +3 -3
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/api/routes/job.py +42 -16
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/api/routes/logs.py +7 -7
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/api/routes/workflows.py +10 -9
- ddeutil_workflow-0.0.68/src/ddeutil/workflow/cli.py +119 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/conf.py +7 -3
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/errors.py +0 -3
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/event.py +4 -3
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/logs.py +18 -14
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/result.py +12 -7
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/stages.py +149 -35
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/utils.py +1 -52
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil_workflow.egg-info/PKG-INFO +14 -36
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil_workflow.egg-info/SOURCES.txt +1 -1
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil_workflow.egg-info/requires.txt +3 -15
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_result.py +4 -1
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_utils.py +0 -10
- ddeutil_workflow-0.0.66/src/ddeutil/workflow/__about__.py +0 -1
- ddeutil_workflow-0.0.66/src/ddeutil/workflow/cli.py +0 -66
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/LICENSE +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/setup.cfg +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/__cron.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/__init__.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/__main__.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/__types.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/job.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/params.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/reusables.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/workflow.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil_workflow.egg-info/dependency_links.txt +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil_workflow.egg-info/entry_points.txt +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil_workflow.egg-info/top_level.txt +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test__cron.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test__regex.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_conf.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_errors.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_event.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_job.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_job_exec.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_job_exec_strategy.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_logs_audit.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_logs_trace.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_params.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_reusables_call_tag.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_reusables_func_model.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_reusables_template.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_reusables_template_filter.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_strategy.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_workflow.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_workflow_exec.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_workflow_exec_job.py +0 -0
- {ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/tests/test_workflow_release.py +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ddeutil-workflow
|
3
|
-
Version: 0.0.
|
4
|
-
Summary: Lightweight workflow orchestration
|
3
|
+
Version: 0.0.68
|
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/
|
@@ -24,10 +24,10 @@ Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
25
25
|
Requires-Dist: ddeutil[checksum]>=0.4.8
|
26
26
|
Requires-Dist: ddeutil-io[toml,yaml]>=0.2.14
|
27
|
-
Requires-Dist: pydantic==2.11.
|
27
|
+
Requires-Dist: pydantic==2.11.5
|
28
28
|
Requires-Dist: pydantic-extra-types==2.10.4
|
29
29
|
Requires-Dist: python-dotenv==1.1.0
|
30
|
-
Requires-Dist: typer
|
30
|
+
Requires-Dist: typer>=0.16.0
|
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
|
-
|
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
|
146
|
-
|
147
|
-
| Python | `ddeutil-workflow`
|
148
|
-
| FastAPI Server | `ddeutil-workflow[
|
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
|
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) $
|
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
|
-
>
|
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
|
336
|
-
$ docker run
|
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
|
95
|
-
|
96
|
-
| Python | `ddeutil-workflow`
|
97
|
-
| FastAPI Server | `ddeutil-workflow[
|
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
|
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) $
|
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
|
-
>
|
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
|
285
|
-
$ docker run
|
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" }]
|
@@ -27,11 +27,10 @@ requires-python = ">=3.9.13"
|
|
27
27
|
dependencies = [
|
28
28
|
"ddeutil[checksum]>=0.4.8",
|
29
29
|
"ddeutil-io[yaml,toml]>=0.2.14",
|
30
|
-
"pydantic==2.11.
|
30
|
+
"pydantic==2.11.5",
|
31
31
|
"pydantic-extra-types==2.10.4",
|
32
32
|
"python-dotenv==1.1.0",
|
33
|
-
|
34
|
-
"typer==0.15.4",
|
33
|
+
"typer>=0.16.0",
|
35
34
|
]
|
36
35
|
dynamic = ["version"]
|
37
36
|
|
@@ -43,23 +42,11 @@ all = [
|
|
43
42
|
"ujson",
|
44
43
|
"aiofiles",
|
45
44
|
"aiohttp",
|
46
|
-
|
47
|
-
api = [
|
48
|
-
"fastapi>=0.115.0,<1.0.0",
|
49
|
-
"uvicorn",
|
50
|
-
"httpx",
|
51
|
-
"ujson",
|
52
|
-
]
|
53
|
-
async = [
|
54
|
-
"aiofiles",
|
55
|
-
"aiohttp",
|
45
|
+
"requests==2.32.3",
|
56
46
|
]
|
57
47
|
docker = [
|
58
48
|
"docker==7.1.0",
|
59
49
|
]
|
60
|
-
self_hosted = [
|
61
|
-
"requests==2.32.3",
|
62
|
-
]
|
63
50
|
|
64
51
|
[project.urls]
|
65
52
|
Homepage = "https://github.com/ddeutils/ddeutil-workflow/"
|
@@ -91,9 +78,10 @@ omit = [
|
|
91
78
|
"src/ddeutil/workflow/__about__.py",
|
92
79
|
"src/ddeutil/workflow/__cron.py",
|
93
80
|
"src/ddeutil/workflow/__main__.py",
|
81
|
+
"src/ddeutil/workflow/__types.py",
|
94
82
|
"src/ddeutil/workflow/cli.py",
|
95
83
|
"src/ddeutil/workflow/api/__init__.py",
|
96
|
-
"src/ddeutil/workflow/api/
|
84
|
+
"src/ddeutil/workflow/api/log_conf.py",
|
97
85
|
"src/ddeutil/workflow/api/routes/__init__.py",
|
98
86
|
"src/ddeutil/workflow/api/routes/job.py",
|
99
87
|
"src/ddeutil/workflow/api/routes/logs.py",
|
@@ -109,12 +97,10 @@ exclude_lines = [
|
|
109
97
|
[tool.pytest.ini_options]
|
110
98
|
pythonpath = ["src"]
|
111
99
|
asyncio_default_fixture_loop_scope = "fuction"
|
112
|
-
# NOTE: You can deslect multiple markers by '-m "not (
|
100
|
+
# NOTE: You can deslect multiple markers by '-m "not (asyncio or api)"'
|
113
101
|
markers = [
|
114
|
-
"poke: marks tests as slow by poking (deselect with '-m \"not poke\"')",
|
115
|
-
"schedule: marks tests as schedule (deselect with '-m \"not schedule\"')",
|
116
102
|
"api: marks tests as api (deselect with '-m \"not api\"')",
|
117
|
-
"asyncio: marks async
|
103
|
+
"asyncio: marks async test cases",
|
118
104
|
]
|
119
105
|
console_output_style = "count"
|
120
106
|
addopts = [
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__: str = "0.0.68"
|
@@ -6,6 +6,7 @@
|
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
8
|
import contextlib
|
9
|
+
import logging
|
9
10
|
from collections.abc import AsyncIterator
|
10
11
|
|
11
12
|
from dotenv import load_dotenv
|
@@ -19,11 +20,10 @@ from fastapi.responses import UJSONResponse
|
|
19
20
|
|
20
21
|
from ..__about__ import __version__
|
21
22
|
from ..conf import api_config
|
22
|
-
from ..logs import get_logger
|
23
23
|
from .routes import job, log, workflow
|
24
24
|
|
25
25
|
load_dotenv()
|
26
|
-
logger =
|
26
|
+
logger = logging.getLogger("uvicorn.error")
|
27
27
|
|
28
28
|
|
29
29
|
@contextlib.asynccontextmanager
|
@@ -58,12 +58,16 @@ app.add_middleware(
|
|
58
58
|
|
59
59
|
|
60
60
|
@app.get(path="/", response_class=UJSONResponse)
|
61
|
-
async def health():
|
61
|
+
async def health() -> UJSONResponse:
|
62
62
|
"""Index view that not return any template without json status."""
|
63
|
-
|
63
|
+
logger.info("[API]: Workflow API Application already running ...")
|
64
|
+
return UJSONResponse(
|
65
|
+
content={"message": "Workflow already start up with healthy status."},
|
66
|
+
status_code=st.HTTP_200_OK,
|
67
|
+
)
|
64
68
|
|
65
69
|
|
66
|
-
# NOTE Add the jobs and logs routes by default.
|
70
|
+
# NOTE: Add the jobs and logs routes by default.
|
67
71
|
app.include_router(job, prefix=api_config.prefix_path)
|
68
72
|
app.include_router(log, prefix=api_config.prefix_path)
|
69
73
|
app.include_router(workflow, prefix=api_config.prefix_path)
|
@@ -71,21 +75,18 @@ app.include_router(workflow, prefix=api_config.prefix_path)
|
|
71
75
|
|
72
76
|
@app.exception_handler(RequestValidationError)
|
73
77
|
async def validation_exception_handler(
|
74
|
-
request: Request,
|
75
|
-
|
78
|
+
request: Request,
|
79
|
+
exc: RequestValidationError,
|
80
|
+
) -> UJSONResponse:
|
81
|
+
"""Error Handler for model validate does not valid."""
|
76
82
|
_ = request
|
77
83
|
return UJSONResponse(
|
78
84
|
status_code=st.HTTP_422_UNPROCESSABLE_ENTITY,
|
79
|
-
content=jsonable_encoder(
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
uvicorn.run(
|
87
|
-
app,
|
88
|
-
host="0.0.0.0",
|
89
|
-
port=80,
|
90
|
-
log_level="DEBUG",
|
85
|
+
content=jsonable_encoder(
|
86
|
+
{
|
87
|
+
"message": "Body does not parsing with model.",
|
88
|
+
"detail": exc.errors(),
|
89
|
+
"body": exc.body,
|
90
|
+
}
|
91
|
+
),
|
91
92
|
)
|
@@ -1,6 +1,8 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
1
3
|
from ..conf import config
|
2
4
|
|
3
|
-
LOGGING_CONFIG = { # pragma: no cov
|
5
|
+
LOGGING_CONFIG: dict[str, Any] = { # pragma: no cov
|
4
6
|
"version": 1,
|
5
7
|
"disable_existing_loggers": False,
|
6
8
|
"formatters": {
|
@@ -22,38 +24,49 @@ LOGGING_CONFIG = { # pragma: no cov
|
|
22
24
|
"stream": "ext://sys.stderr",
|
23
25
|
},
|
24
26
|
"stream_handler": {
|
27
|
+
# "formatter": "standard",
|
25
28
|
"formatter": "custom_formatter",
|
26
29
|
"class": "logging.StreamHandler",
|
27
30
|
"stream": "ext://sys.stdout",
|
28
31
|
},
|
29
|
-
"file_handler": {
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
},
|
32
|
+
# "file_handler": {
|
33
|
+
# "formatter": "custom_formatter",
|
34
|
+
# "class": "logging.handlers.RotatingFileHandler",
|
35
|
+
# "filename": "logs/app.log",
|
36
|
+
# "maxBytes": 1024 * 1024 * 1,
|
37
|
+
# "backupCount": 3,
|
38
|
+
# },
|
36
39
|
},
|
37
40
|
"loggers": {
|
38
41
|
"uvicorn": {
|
39
|
-
"handlers": ["default", "file_handler"],
|
42
|
+
# "handlers": ["default", "file_handler"],
|
43
|
+
"handlers": ["default"],
|
40
44
|
"level": "DEBUG" if config.debug else "INFO",
|
41
45
|
"propagate": False,
|
42
46
|
},
|
43
47
|
"uvicorn.access": {
|
44
|
-
"handlers": ["stream_handler", "file_handler"],
|
48
|
+
# "handlers": ["stream_handler", "file_handler"],
|
49
|
+
"handlers": ["stream_handler"],
|
45
50
|
"level": "DEBUG" if config.debug else "INFO",
|
46
51
|
"propagate": False,
|
47
52
|
},
|
48
53
|
"uvicorn.error": {
|
49
|
-
"handlers": ["stream_handler", "file_handler"],
|
54
|
+
# "handlers": ["stream_handler", "file_handler"],
|
55
|
+
"handlers": ["stream_handler"],
|
50
56
|
"level": "DEBUG" if config.debug else "INFO",
|
51
57
|
"propagate": False,
|
52
58
|
},
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
"uvicorn.asgi": {
|
60
|
+
# "handlers": ["stream_handler", "file_handler"],
|
61
|
+
"handlers": ["stream_handler"],
|
62
|
+
"level": "TRACE",
|
63
|
+
"propagate": False,
|
64
|
+
},
|
65
|
+
# "ddeutil.workflow": {
|
66
|
+
# "handlers": ["stream_handler"],
|
67
|
+
# "level": "INFO",
|
68
|
+
# # "propagate": False,
|
69
|
+
# "propagate": True,
|
57
70
|
# },
|
58
71
|
},
|
59
72
|
}
|
{ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/api/routes/__init__.py
RENAMED
@@ -3,6 +3,6 @@
|
|
3
3
|
# Licensed under the MIT License. See LICENSE in the project root for
|
4
4
|
# license information.
|
5
5
|
# ------------------------------------------------------------------------------
|
6
|
-
from .job import
|
7
|
-
from .logs import
|
8
|
-
from .workflows import
|
6
|
+
from .job import router as job
|
7
|
+
from .logs import router as log
|
8
|
+
from .workflows import router as workflow
|
@@ -5,20 +5,21 @@
|
|
5
5
|
# ------------------------------------------------------------------------------
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
|
+
import logging
|
8
9
|
from typing import Any, Optional
|
9
10
|
|
10
11
|
from fastapi import APIRouter
|
12
|
+
from fastapi import status as st
|
11
13
|
from fastapi.responses import UJSONResponse
|
12
14
|
from pydantic import BaseModel, Field
|
13
15
|
|
14
16
|
from ...__types import DictData
|
15
17
|
from ...errors import JobError
|
16
18
|
from ...job import Job
|
17
|
-
from ...logs import get_logger
|
18
19
|
from ...result import Result
|
19
20
|
|
20
|
-
logger =
|
21
|
-
|
21
|
+
logger = logging.getLogger("uvicorn.error")
|
22
|
+
router = APIRouter(prefix="/job", tags=["job"])
|
22
23
|
|
23
24
|
|
24
25
|
class ResultCreate(BaseModel):
|
@@ -32,14 +33,19 @@ class ResultCreate(BaseModel):
|
|
32
33
|
)
|
33
34
|
|
34
35
|
|
35
|
-
@
|
36
|
+
@router.post(
|
37
|
+
path="/execute/",
|
38
|
+
response_class=UJSONResponse,
|
39
|
+
status_code=st.HTTP_200_OK,
|
40
|
+
)
|
36
41
|
async def job_execute(
|
37
42
|
result: ResultCreate,
|
38
43
|
job: Job,
|
39
44
|
params: dict[str, Any],
|
40
45
|
extras: Optional[dict[str, Any]] = None,
|
41
|
-
):
|
46
|
+
) -> UJSONResponse:
|
42
47
|
"""Execute job via RestAPI with execute route path."""
|
48
|
+
logger.info("[API]: Start execute job ...")
|
43
49
|
rs: Result = Result(
|
44
50
|
run_id=result.run_id,
|
45
51
|
parent_run_id=result.parent_run_id,
|
@@ -61,15 +67,35 @@ async def job_execute(
|
|
61
67
|
)
|
62
68
|
except JobError as err:
|
63
69
|
rs.trace.error(f"[JOB]: {err.__class__.__name__}: {err}")
|
70
|
+
return UJSONResponse(
|
71
|
+
content={
|
72
|
+
"message": str(err),
|
73
|
+
"result": {
|
74
|
+
"run_id": rs.run_id,
|
75
|
+
"parent_run_id": rs.parent_run_id,
|
76
|
+
},
|
77
|
+
"job": job.model_dump(
|
78
|
+
by_alias=True,
|
79
|
+
exclude_none=False,
|
80
|
+
exclude_unset=True,
|
81
|
+
),
|
82
|
+
"params": params,
|
83
|
+
"context": context,
|
84
|
+
},
|
85
|
+
status_code=st.HTTP_500_INTERNAL_SERVER_ERROR,
|
86
|
+
)
|
64
87
|
|
65
|
-
return
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
88
|
+
return UJSONResponse(
|
89
|
+
content={
|
90
|
+
"message": "Execute job via RestAPI successful.",
|
91
|
+
"result": {"run_id": rs.run_id, "parent_run_id": rs.parent_run_id},
|
92
|
+
"job": job.model_dump(
|
93
|
+
by_alias=True,
|
94
|
+
exclude_none=False,
|
95
|
+
exclude_unset=True,
|
96
|
+
),
|
97
|
+
"params": params,
|
98
|
+
"context": context,
|
99
|
+
},
|
100
|
+
status_code=st.HTTP_200_OK,
|
101
|
+
)
|
@@ -13,14 +13,14 @@ from fastapi.responses import UJSONResponse
|
|
13
13
|
from ...logs import get_audit
|
14
14
|
from ...result import Result
|
15
15
|
|
16
|
-
|
16
|
+
router = APIRouter(
|
17
17
|
prefix="/logs",
|
18
18
|
tags=["logs"],
|
19
19
|
default_response_class=UJSONResponse,
|
20
20
|
)
|
21
21
|
|
22
22
|
|
23
|
-
@
|
23
|
+
@router.get(
|
24
24
|
path="/traces/",
|
25
25
|
response_class=UJSONResponse,
|
26
26
|
status_code=st.HTTP_200_OK,
|
@@ -50,7 +50,7 @@ async def get_traces(
|
|
50
50
|
}
|
51
51
|
|
52
52
|
|
53
|
-
@
|
53
|
+
@router.get(
|
54
54
|
path="/traces/{run_id}",
|
55
55
|
response_class=UJSONResponse,
|
56
56
|
status_code=st.HTTP_200_OK,
|
@@ -77,7 +77,7 @@ async def get_trace_with_id(run_id: str):
|
|
77
77
|
}
|
78
78
|
|
79
79
|
|
80
|
-
@
|
80
|
+
@router.get(
|
81
81
|
path="/audits/",
|
82
82
|
response_class=UJSONResponse,
|
83
83
|
status_code=st.HTTP_200_OK,
|
@@ -94,7 +94,7 @@ async def get_audits():
|
|
94
94
|
}
|
95
95
|
|
96
96
|
|
97
|
-
@
|
97
|
+
@router.get(
|
98
98
|
path="/audits/{workflow}/",
|
99
99
|
response_class=UJSONResponse,
|
100
100
|
status_code=st.HTTP_200_OK,
|
@@ -113,7 +113,7 @@ async def get_audit_with_workflow(workflow: str):
|
|
113
113
|
}
|
114
114
|
|
115
115
|
|
116
|
-
@
|
116
|
+
@router.get(
|
117
117
|
path="/audits/{workflow}/{release}",
|
118
118
|
response_class=UJSONResponse,
|
119
119
|
status_code=st.HTTP_200_OK,
|
@@ -140,7 +140,7 @@ async def get_audit_with_workflow_release(
|
|
140
140
|
}
|
141
141
|
|
142
142
|
|
143
|
-
@
|
143
|
+
@router.get(
|
144
144
|
path="/audits/{workflow}/{release}/{run_id}",
|
145
145
|
response_class=UJSONResponse,
|
146
146
|
status_code=st.HTTP_200_OK,
|
{ddeutil_workflow-0.0.66 → ddeutil_workflow-0.0.68}/src/ddeutil/workflow/api/routes/workflows.py
RENAMED
@@ -5,6 +5,7 @@
|
|
5
5
|
# ------------------------------------------------------------------------------
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
|
+
import logging
|
8
9
|
from dataclasses import asdict
|
9
10
|
from datetime import datetime
|
10
11
|
from typing import Any
|
@@ -16,19 +17,19 @@ from pydantic import BaseModel
|
|
16
17
|
|
17
18
|
from ...__types import DictData
|
18
19
|
from ...conf import Loader
|
19
|
-
from ...logs import
|
20
|
+
from ...logs import AuditModel, get_audit
|
20
21
|
from ...result import Result
|
21
22
|
from ...workflow import Workflow
|
22
23
|
|
23
|
-
logger =
|
24
|
-
|
24
|
+
logger = logging.getLogger("uvicorn.error")
|
25
|
+
router = APIRouter(
|
25
26
|
prefix="/workflows",
|
26
27
|
tags=["workflows"],
|
27
28
|
default_response_class=UJSONResponse,
|
28
29
|
)
|
29
30
|
|
30
31
|
|
31
|
-
@
|
32
|
+
@router.get(path="/", status_code=st.HTTP_200_OK)
|
32
33
|
async def get_workflows() -> DictData:
|
33
34
|
"""Return all workflow workflows that exists in config path."""
|
34
35
|
workflows: DictData = dict(Loader.finds(Workflow))
|
@@ -39,7 +40,7 @@ async def get_workflows() -> DictData:
|
|
39
40
|
}
|
40
41
|
|
41
42
|
|
42
|
-
@
|
43
|
+
@router.get(path="/{name}", status_code=st.HTTP_200_OK)
|
43
44
|
async def get_workflow_by_name(name: str) -> DictData:
|
44
45
|
"""Return model of workflow that passing an input workflow name."""
|
45
46
|
try:
|
@@ -63,7 +64,7 @@ class ExecutePayload(BaseModel):
|
|
63
64
|
params: dict[str, Any]
|
64
65
|
|
65
66
|
|
66
|
-
@
|
67
|
+
@router.post(path="/{name}/execute", status_code=st.HTTP_202_ACCEPTED)
|
67
68
|
async def workflow_execute(name: str, payload: ExecutePayload) -> DictData:
|
68
69
|
"""Return model of workflow that passing an input workflow name."""
|
69
70
|
try:
|
@@ -88,7 +89,7 @@ async def workflow_execute(name: str, payload: ExecutePayload) -> DictData:
|
|
88
89
|
return asdict(result)
|
89
90
|
|
90
91
|
|
91
|
-
@
|
92
|
+
@router.get(path="/{name}/audits", status_code=st.HTTP_200_OK)
|
92
93
|
async def get_workflow_audits(name: str):
|
93
94
|
try:
|
94
95
|
return {
|
@@ -109,11 +110,11 @@ async def get_workflow_audits(name: str):
|
|
109
110
|
) from None
|
110
111
|
|
111
112
|
|
112
|
-
@
|
113
|
+
@router.get(path="/{name}/audits/{release}", status_code=st.HTTP_200_OK)
|
113
114
|
async def get_workflow_release_audit(name: str, release: str):
|
114
115
|
"""Get Workflow audit log with an input release value."""
|
115
116
|
try:
|
116
|
-
audit:
|
117
|
+
audit: AuditModel = get_audit().find_audit_with_release(
|
117
118
|
name=name,
|
118
119
|
release=datetime.strptime(release, "%Y%m%d%H%M%S"),
|
119
120
|
)
|