ddeutil-workflow 0.0.25__tar.gz → 0.0.26.post0__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 (65) hide show
  1. {ddeutil_workflow-0.0.25/src/ddeutil_workflow.egg-info → ddeutil_workflow-0.0.26.post0}/PKG-INFO +34 -50
  2. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/README.md +33 -48
  3. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/pyproject.toml +0 -5
  4. ddeutil_workflow-0.0.26.post0/src/ddeutil/workflow/__about__.py +1 -0
  5. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/api/route.py +40 -3
  6. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/conf.py +21 -22
  7. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0/src/ddeutil_workflow.egg-info}/PKG-INFO +34 -50
  8. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil_workflow.egg-info/SOURCES.txt +0 -3
  9. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil_workflow.egg-info/requires.txt +0 -1
  10. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_conf_log.py +9 -3
  11. ddeutil_workflow-0.0.25/src/ddeutil/workflow/__about__.py +0 -1
  12. ddeutil_workflow-0.0.25/src/ddeutil/workflow/cli.py +0 -108
  13. ddeutil_workflow-0.0.25/src/ddeutil_workflow.egg-info/entry_points.txt +0 -2
  14. ddeutil_workflow-0.0.25/tests/test_cli.py +0 -44
  15. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/LICENSE +0 -0
  16. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/setup.cfg +0 -0
  17. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/__cron.py +0 -0
  18. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/__init__.py +0 -0
  19. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/__types.py +0 -0
  20. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/api/__init__.py +0 -0
  21. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/api/api.py +0 -0
  22. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/api/repeat.py +0 -0
  23. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/cron.py +0 -0
  24. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/exceptions.py +0 -0
  25. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/job.py +0 -0
  26. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/params.py +0 -0
  27. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/result.py +0 -0
  28. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/scheduler.py +0 -0
  29. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/stage.py +0 -0
  30. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/utils.py +0 -0
  31. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil/workflow/workflow.py +0 -0
  32. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil_workflow.egg-info/dependency_links.txt +0 -0
  33. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/src/ddeutil_workflow.egg-info/top_level.txt +0 -0
  34. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test__cron.py +0 -0
  35. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test__regex.py +0 -0
  36. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_conf.py +0 -0
  37. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_cron_on.py +0 -0
  38. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_job.py +0 -0
  39. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_job_exec_py.py +0 -0
  40. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_job_exec_strategy.py +0 -0
  41. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_job_strategy.py +0 -0
  42. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_params.py +0 -0
  43. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_result.py +0 -0
  44. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_schedule.py +0 -0
  45. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_schedule_control.py +0 -0
  46. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_schedule_tasks.py +0 -0
  47. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_stage.py +0 -0
  48. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_stage_exec_bash.py +0 -0
  49. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_stage_exec_hook.py +0 -0
  50. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_stage_exec_py.py +0 -0
  51. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_stage_exec_trigger.py +0 -0
  52. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_utils.py +0 -0
  53. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_utils_filter.py +0 -0
  54. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_utils_tag.py +0 -0
  55. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_utils_template.py +0 -0
  56. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow.py +0 -0
  57. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_exec.py +0 -0
  58. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_exec_hook.py +0 -0
  59. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_exec_needs.py +0 -0
  60. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_job_exec.py +0 -0
  61. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_poke.py +0 -0
  62. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_release.py +0 -0
  63. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_release_and_queue.py +0 -0
  64. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_schedule.py +0 -0
  65. {ddeutil_workflow-0.0.25 → ddeutil_workflow-0.0.26.post0}/tests/test_workflow_task.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ddeutil-workflow
3
- Version: 0.0.25
3
+ Version: 0.0.26.post0
4
4
  Summary: Lightweight workflow orchestration with less dependencies
5
5
  Author-email: ddeutils <korawich.anu@gmail.com>
6
6
  License: MIT
@@ -26,7 +26,6 @@ Requires-Dist: ddeutil>=0.4.3
26
26
  Requires-Dist: ddeutil-io[toml,yaml]>=0.2.3
27
27
  Requires-Dist: pydantic==2.10.4
28
28
  Requires-Dist: python-dotenv==1.0.1
29
- Requires-Dist: typer==0.15.1
30
29
  Requires-Dist: schedule<2.0.0,==1.2.2
31
30
  Provides-Extra: api
32
31
  Requires-Dist: fastapi<1.0.0,>=0.115.0; extra == "api"
@@ -80,20 +79,10 @@ This project need `ddeutil` and `ddeutil-io` extension namespace packages.
80
79
  If you want to install this package with application add-ons, you should add
81
80
  `app` in installation;
82
81
 
83
- | Usecase | Install Optional | Support |
84
- |-------------------|------------------------------------------|--------------------|
85
- | Python & CLI | `pip install ddeutil-workflow` | :heavy_check_mark: |
86
- | FastAPI Server | `pip install ddeutil-workflow[api]` | :heavy_check_mark: |
87
-
88
- > :egg: **Docker Images** supported:
89
- >
90
- > | Docker Image | Python Version | Support |
91
- > |-----------------------------|----------------|---------|
92
- > | ddeutil-workflow:latest | `3.9` | :x: |
93
- > | ddeutil-workflow:python3.10 | `3.10` | :x: |
94
- > | ddeutil-workflow:python3.11 | `3.11` | :x: |
95
- > | ddeutil-workflow:python3.12 | `3.12` | :x: |
96
- > | ddeutil-workflow:python3.12 | `3.13` | :x: |
82
+ | Usecase | Install Optional | Support |
83
+ |----------------|------------------------------------------|--------------------|
84
+ | Python | `pip install ddeutil-workflow` | :heavy_check_mark: |
85
+ | FastAPI Server | `pip install ddeutil-workflow[api]` | :heavy_check_mark: |
97
86
 
98
87
  ## :beers: Usage
99
88
 
@@ -110,7 +99,7 @@ use-case.
110
99
  run-py-local:
111
100
 
112
101
  # Validate model that use to parsing exists for template file
113
- type: ddeutil.workflow.workflow.Workflow
102
+ type: Workflow
114
103
  on:
115
104
  # If workflow deploy to schedule, it will running every 5 minutes
116
105
  # with Asia/Bangkok timezone.
@@ -161,7 +150,7 @@ So, this package provide the `Schedule` template for this action.
161
150
  schedule-run-local-wf:
162
151
 
163
152
  # Validate model that use to parsing exists for template file
164
- type: ddeutil.workflow.scheduler.Schedule
153
+ type: Schedule
165
154
  workflows:
166
155
 
167
156
  # Map existing workflow that want to deploy with scheduler application.
@@ -179,35 +168,36 @@ The main configuration that use to dynamic changing with your propose of this
179
168
  application. If any configuration values do not set yet, it will use default value
180
169
  and do not raise any error to you.
181
170
 
182
- | Environment | Component | Default | Description | Remark |
183
- |:----------------------------------------|:----------:|:---------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|--------|
184
- | `WORKFLOW_ROOT_PATH` | Core | . | The root path of the workflow application. | |
185
- | `WORKFLOW_CORE_REGISTRY` | Core | src,src.ddeutil.workflow,tests,tests.utils | List of importable string for the hook stage. | |
186
- | `WORKFLOW_CORE_REGISTRY_FILTER` | Core | src.ddeutil.workflow.utils,ddeutil.workflow.utils | List of importable string for the filter template. | |
187
- | `WORKFLOW_CORE_PATH_CONF` | Core | conf | The config path that keep all template `.yaml` files. | |
188
- | `WORKFLOW_CORE_TIMEZONE` | Core | Asia/Bangkok | A Timezone string value that will pass to `ZoneInfo` object. | |
189
- | `WORKFLOW_CORE_STAGE_DEFAULT_ID` | Core | true | A flag that enable default stage ID that use for catch an execution output. | |
190
- | `WORKFLOW_CORE_STAGE_RAISE_ERROR` | Core | false | A flag that all stage raise StageException from stage execution. | |
191
- | `WORKFLOW_CORE_JOB_DEFAULT_ID` | Core | false | A flag that enable default job ID that use for catch an execution output. The ID that use will be sequence number. | |
192
- | `WORKFLOW_CORE_JOB_RAISE_ERROR` | Core | true | A flag that all job raise JobException from job strategy execution. | |
193
- | `WORKFLOW_CORE_MAX_NUM_POKING` | Core | 4 | . | |
194
- | `WORKFLOW_CORE_MAX_JOB_PARALLEL` | Core | 2 | The maximum job number that able to run parallel in workflow executor. | |
195
- | `WORKFLOW_CORE_MAX_JOB_EXEC_TIMEOUT` | Core | 600 | | |
196
- | `WORKFLOW_CORE_MAX_CRON_PER_WORKFLOW` | Core | 5 | | |
197
- | `WORKFLOW_CORE_MAX_QUEUE_COMPLETE_HIST` | Core | 16 | | |
198
- | `WORKFLOW_CORE_GENERATE_ID_SIMPLE_MODE` | Core | true | A flog that enable generating ID with `md5` algorithm. | |
199
- | `WORKFLOW_LOG_DEBUG_MODE` | Log | true | A flag that enable logging with debug level mode. | |
200
- | `WORKFLOW_LOG_ENABLE_WRITE` | Log | true | A flag that enable logging object saving log to its destination. | |
201
- | `WORKFLOW_APP_MAX_PROCESS` | Schedule | 2 | The maximum process worker number that run in scheduler app module. | |
202
- | `WORKFLOW_APP_MAX_SCHEDULE_PER_PROCESS` | Schedule | 100 | A schedule per process that run parallel. | |
203
- | `WORKFLOW_APP_STOP_BOUNDARY_DELTA` | Schedule | '{"minutes": 5, "seconds": 20}' | A time delta value that use to stop scheduler app in json string format. | |
171
+ | Environment | Component | Default | Description | Remark |
172
+ |:-------------------------------------------|:---------:|:-----------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|--------|
173
+ | **WORKFLOW_ROOT_PATH** | Core | `.` | The root path of the workflow application. | |
174
+ | **WORKFLOW_CORE_REGISTRY** | Core | `src,src.ddeutil.workflow,tests,tests.utils` | List of importable string for the hook stage. | |
175
+ | **WORKFLOW_CORE_REGISTRY_FILTER** | Core | `src.ddeutil.workflow.utils,ddeutil.workflow.utils` | List of importable string for the filter template. | |
176
+ | **WORKFLOW_CORE_PATH_CONF** | Core | `conf` | The config path that keep all template `.yaml` files. | |
177
+ | **WORKFLOW_CORE_TIMEZONE** | Core | `Asia/Bangkok` | A Timezone string value that will pass to `ZoneInfo` object. | |
178
+ | **WORKFLOW_CORE_STAGE_DEFAULT_ID** | Core | `true` | A flag that enable default stage ID that use for catch an execution output. | |
179
+ | **WORKFLOW_CORE_STAGE_RAISE_ERROR** | Core | `false` | A flag that all stage raise StageException from stage execution. | |
180
+ | **WORKFLOW_CORE_JOB_DEFAULT_ID** | Core | `false` | A flag that enable default job ID that use for catch an execution output. The ID that use will be sequence number. | |
181
+ | **WORKFLOW_CORE_JOB_RAISE_ERROR** | Core | `true` | A flag that all job raise JobException from job strategy execution. | |
182
+ | **WORKFLOW_CORE_MAX_NUM_POKING** | Core | `4` | . | |
183
+ | **WORKFLOW_CORE_MAX_JOB_PARALLEL** | Core | `2` | The maximum job number that able to run parallel in workflow executor. | |
184
+ | **WORKFLOW_CORE_MAX_JOB_EXEC_TIMEOUT** | Core | `600` | | |
185
+ | **WORKFLOW_CORE_MAX_CRON_PER_WORKFLOW** | Core | `5` | | |
186
+ | **WORKFLOW_CORE_MAX_QUEUE_COMPLETE_HIST** | Core | `16` | | |
187
+ | **WORKFLOW_CORE_GENERATE_ID_SIMPLE_MODE** | Core | `true` | A flog that enable generating ID with `md5` algorithm. | |
188
+ | **WORKFLOW_LOG_PATH** | Log | `./logs` | The log path of the workflow saving log. | |
189
+ | **WORKFLOW_LOG_DEBUG_MODE** | Log | `true` | A flag that enable logging with debug level mode. | |
190
+ | **WORKFLOW_LOG_ENABLE_WRITE** | Log | `true` | A flag that enable logging object saving log to its destination. | |
191
+ | **WORKFLOW_APP_MAX_PROCESS** | Schedule | `2` | The maximum process worker number that run in scheduler app module. | |
192
+ | **WORKFLOW_APP_MAX_SCHEDULE_PER_PROCESS** | Schedule | `100` | A schedule per process that run parallel. | |
193
+ | **WORKFLOW_APP_STOP_BOUNDARY_DELTA** | Schedule | `'{"minutes": 5, "seconds": 20}'` | A time delta value that use to stop scheduler app in json string format. | |
204
194
 
205
195
  **API Application**:
206
196
 
207
- | Environment | Component | Default | Description | Remark |
208
- |:--------------------------------------|:-----------:|---------|------------------------------------------------------------------------------------|--------|
209
- | `WORKFLOW_API_ENABLE_ROUTE_WORKFLOW` | API | true | A flag that enable workflow route to manage execute manually and workflow logging. | |
210
- | `WORKFLOW_API_ENABLE_ROUTE_SCHEDULE` | API | true | A flag that enable run scheduler. | |
197
+ | Environment | Component | Default | Description | Remark |
198
+ |:----------------------------------------|:-----------:|---------|------------------------------------------------------------------------------------|--------|
199
+ | **WORKFLOW_API_ENABLE_ROUTE_WORKFLOW** | API | `true` | A flag that enable workflow route to manage execute manually and workflow logging. | |
200
+ | **WORKFLOW_API_ENABLE_ROUTE_SCHEDULE** | API | `true` | A flag that enable run scheduler. | |
211
201
 
212
202
  ## :rocket: Deployment
213
203
 
@@ -215,12 +205,6 @@ This package able to run as a application service for receive manual trigger
215
205
  from the master node via RestAPI or use to be Scheduler background service
216
206
  like crontab job but via Python API.
217
207
 
218
- ### CLI
219
-
220
- ```shell
221
- (venv) $ ddeutil-workflow schedule
222
- ```
223
-
224
208
  ### API Server
225
209
 
226
210
  ```shell
@@ -47,20 +47,10 @@ This project need `ddeutil` and `ddeutil-io` extension namespace packages.
47
47
  If you want to install this package with application add-ons, you should add
48
48
  `app` in installation;
49
49
 
50
- | Usecase | Install Optional | Support |
51
- |-------------------|------------------------------------------|--------------------|
52
- | Python & CLI | `pip install ddeutil-workflow` | :heavy_check_mark: |
53
- | FastAPI Server | `pip install ddeutil-workflow[api]` | :heavy_check_mark: |
54
-
55
- > :egg: **Docker Images** supported:
56
- >
57
- > | Docker Image | Python Version | Support |
58
- > |-----------------------------|----------------|---------|
59
- > | ddeutil-workflow:latest | `3.9` | :x: |
60
- > | ddeutil-workflow:python3.10 | `3.10` | :x: |
61
- > | ddeutil-workflow:python3.11 | `3.11` | :x: |
62
- > | ddeutil-workflow:python3.12 | `3.12` | :x: |
63
- > | ddeutil-workflow:python3.12 | `3.13` | :x: |
50
+ | Usecase | Install Optional | Support |
51
+ |----------------|------------------------------------------|--------------------|
52
+ | Python | `pip install ddeutil-workflow` | :heavy_check_mark: |
53
+ | FastAPI Server | `pip install ddeutil-workflow[api]` | :heavy_check_mark: |
64
54
 
65
55
  ## :beers: Usage
66
56
 
@@ -77,7 +67,7 @@ use-case.
77
67
  run-py-local:
78
68
 
79
69
  # Validate model that use to parsing exists for template file
80
- type: ddeutil.workflow.workflow.Workflow
70
+ type: Workflow
81
71
  on:
82
72
  # If workflow deploy to schedule, it will running every 5 minutes
83
73
  # with Asia/Bangkok timezone.
@@ -128,7 +118,7 @@ So, this package provide the `Schedule` template for this action.
128
118
  schedule-run-local-wf:
129
119
 
130
120
  # Validate model that use to parsing exists for template file
131
- type: ddeutil.workflow.scheduler.Schedule
121
+ type: Schedule
132
122
  workflows:
133
123
 
134
124
  # Map existing workflow that want to deploy with scheduler application.
@@ -146,35 +136,36 @@ The main configuration that use to dynamic changing with your propose of this
146
136
  application. If any configuration values do not set yet, it will use default value
147
137
  and do not raise any error to you.
148
138
 
149
- | Environment | Component | Default | Description | Remark |
150
- |:----------------------------------------|:----------:|:---------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|--------|
151
- | `WORKFLOW_ROOT_PATH` | Core | . | The root path of the workflow application. | |
152
- | `WORKFLOW_CORE_REGISTRY` | Core | src,src.ddeutil.workflow,tests,tests.utils | List of importable string for the hook stage. | |
153
- | `WORKFLOW_CORE_REGISTRY_FILTER` | Core | src.ddeutil.workflow.utils,ddeutil.workflow.utils | List of importable string for the filter template. | |
154
- | `WORKFLOW_CORE_PATH_CONF` | Core | conf | The config path that keep all template `.yaml` files. | |
155
- | `WORKFLOW_CORE_TIMEZONE` | Core | Asia/Bangkok | A Timezone string value that will pass to `ZoneInfo` object. | |
156
- | `WORKFLOW_CORE_STAGE_DEFAULT_ID` | Core | true | A flag that enable default stage ID that use for catch an execution output. | |
157
- | `WORKFLOW_CORE_STAGE_RAISE_ERROR` | Core | false | A flag that all stage raise StageException from stage execution. | |
158
- | `WORKFLOW_CORE_JOB_DEFAULT_ID` | Core | false | A flag that enable default job ID that use for catch an execution output. The ID that use will be sequence number. | |
159
- | `WORKFLOW_CORE_JOB_RAISE_ERROR` | Core | true | A flag that all job raise JobException from job strategy execution. | |
160
- | `WORKFLOW_CORE_MAX_NUM_POKING` | Core | 4 | . | |
161
- | `WORKFLOW_CORE_MAX_JOB_PARALLEL` | Core | 2 | The maximum job number that able to run parallel in workflow executor. | |
162
- | `WORKFLOW_CORE_MAX_JOB_EXEC_TIMEOUT` | Core | 600 | | |
163
- | `WORKFLOW_CORE_MAX_CRON_PER_WORKFLOW` | Core | 5 | | |
164
- | `WORKFLOW_CORE_MAX_QUEUE_COMPLETE_HIST` | Core | 16 | | |
165
- | `WORKFLOW_CORE_GENERATE_ID_SIMPLE_MODE` | Core | true | A flog that enable generating ID with `md5` algorithm. | |
166
- | `WORKFLOW_LOG_DEBUG_MODE` | Log | true | A flag that enable logging with debug level mode. | |
167
- | `WORKFLOW_LOG_ENABLE_WRITE` | Log | true | A flag that enable logging object saving log to its destination. | |
168
- | `WORKFLOW_APP_MAX_PROCESS` | Schedule | 2 | The maximum process worker number that run in scheduler app module. | |
169
- | `WORKFLOW_APP_MAX_SCHEDULE_PER_PROCESS` | Schedule | 100 | A schedule per process that run parallel. | |
170
- | `WORKFLOW_APP_STOP_BOUNDARY_DELTA` | Schedule | '{"minutes": 5, "seconds": 20}' | A time delta value that use to stop scheduler app in json string format. | |
139
+ | Environment | Component | Default | Description | Remark |
140
+ |:-------------------------------------------|:---------:|:-----------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|--------|
141
+ | **WORKFLOW_ROOT_PATH** | Core | `.` | The root path of the workflow application. | |
142
+ | **WORKFLOW_CORE_REGISTRY** | Core | `src,src.ddeutil.workflow,tests,tests.utils` | List of importable string for the hook stage. | |
143
+ | **WORKFLOW_CORE_REGISTRY_FILTER** | Core | `src.ddeutil.workflow.utils,ddeutil.workflow.utils` | List of importable string for the filter template. | |
144
+ | **WORKFLOW_CORE_PATH_CONF** | Core | `conf` | The config path that keep all template `.yaml` files. | |
145
+ | **WORKFLOW_CORE_TIMEZONE** | Core | `Asia/Bangkok` | A Timezone string value that will pass to `ZoneInfo` object. | |
146
+ | **WORKFLOW_CORE_STAGE_DEFAULT_ID** | Core | `true` | A flag that enable default stage ID that use for catch an execution output. | |
147
+ | **WORKFLOW_CORE_STAGE_RAISE_ERROR** | Core | `false` | A flag that all stage raise StageException from stage execution. | |
148
+ | **WORKFLOW_CORE_JOB_DEFAULT_ID** | Core | `false` | A flag that enable default job ID that use for catch an execution output. The ID that use will be sequence number. | |
149
+ | **WORKFLOW_CORE_JOB_RAISE_ERROR** | Core | `true` | A flag that all job raise JobException from job strategy execution. | |
150
+ | **WORKFLOW_CORE_MAX_NUM_POKING** | Core | `4` | . | |
151
+ | **WORKFLOW_CORE_MAX_JOB_PARALLEL** | Core | `2` | The maximum job number that able to run parallel in workflow executor. | |
152
+ | **WORKFLOW_CORE_MAX_JOB_EXEC_TIMEOUT** | Core | `600` | | |
153
+ | **WORKFLOW_CORE_MAX_CRON_PER_WORKFLOW** | Core | `5` | | |
154
+ | **WORKFLOW_CORE_MAX_QUEUE_COMPLETE_HIST** | Core | `16` | | |
155
+ | **WORKFLOW_CORE_GENERATE_ID_SIMPLE_MODE** | Core | `true` | A flog that enable generating ID with `md5` algorithm. | |
156
+ | **WORKFLOW_LOG_PATH** | Log | `./logs` | The log path of the workflow saving log. | |
157
+ | **WORKFLOW_LOG_DEBUG_MODE** | Log | `true` | A flag that enable logging with debug level mode. | |
158
+ | **WORKFLOW_LOG_ENABLE_WRITE** | Log | `true` | A flag that enable logging object saving log to its destination. | |
159
+ | **WORKFLOW_APP_MAX_PROCESS** | Schedule | `2` | The maximum process worker number that run in scheduler app module. | |
160
+ | **WORKFLOW_APP_MAX_SCHEDULE_PER_PROCESS** | Schedule | `100` | A schedule per process that run parallel. | |
161
+ | **WORKFLOW_APP_STOP_BOUNDARY_DELTA** | Schedule | `'{"minutes": 5, "seconds": 20}'` | A time delta value that use to stop scheduler app in json string format. | |
171
162
 
172
163
  **API Application**:
173
164
 
174
- | Environment | Component | Default | Description | Remark |
175
- |:--------------------------------------|:-----------:|---------|------------------------------------------------------------------------------------|--------|
176
- | `WORKFLOW_API_ENABLE_ROUTE_WORKFLOW` | API | true | A flag that enable workflow route to manage execute manually and workflow logging. | |
177
- | `WORKFLOW_API_ENABLE_ROUTE_SCHEDULE` | API | true | A flag that enable run scheduler. | |
165
+ | Environment | Component | Default | Description | Remark |
166
+ |:----------------------------------------|:-----------:|---------|------------------------------------------------------------------------------------|--------|
167
+ | **WORKFLOW_API_ENABLE_ROUTE_WORKFLOW** | API | `true` | A flag that enable workflow route to manage execute manually and workflow logging. | |
168
+ | **WORKFLOW_API_ENABLE_ROUTE_SCHEDULE** | API | `true` | A flag that enable run scheduler. | |
178
169
 
179
170
  ## :rocket: Deployment
180
171
 
@@ -182,12 +173,6 @@ This package able to run as a application service for receive manual trigger
182
173
  from the master node via RestAPI or use to be Scheduler background service
183
174
  like crontab job but via Python API.
184
175
 
185
- ### CLI
186
-
187
- ```shell
188
- (venv) $ ddeutil-workflow schedule
189
- ```
190
-
191
176
  ### API Server
192
177
 
193
178
  ```shell
@@ -30,7 +30,6 @@ dependencies = [
30
30
  "ddeutil-io[yaml,toml]>=0.2.3",
31
31
  "pydantic==2.10.4",
32
32
  "python-dotenv==1.0.1",
33
- "typer==0.15.1",
34
33
  "schedule==1.2.2,<2.0.0",
35
34
  ]
36
35
  dynamic = ["version"]
@@ -44,9 +43,6 @@ api = [
44
43
  Homepage = "https://github.com/ddeutils/ddeutil-workflow/"
45
44
  "Source Code" = "https://github.com/ddeutils/ddeutil-workflow/"
46
45
 
47
- [project.scripts]
48
- ddeutil-workflow = "ddeutil.workflow.cli:cli"
49
-
50
46
  [tool.setuptools.dynamic]
51
47
  version = {attr = "ddeutil.workflow.__about__.__version__"}
52
48
 
@@ -65,7 +61,6 @@ source = ["ddeutil.workflow"]
65
61
  omit = [
66
62
  "src/ddeutil/workflow/__about__.py",
67
63
  "src/ddeutil/workflow/__cron.py",
68
- "src/ddeutil/workflow/cli.py",
69
64
  "src/ddeutil/workflow/api/__init__.py",
70
65
  "src/ddeutil/workflow/api/api.py",
71
66
  "src/ddeutil/workflow/api/repeat.py",
@@ -0,0 +1 @@
1
+ __version__: str = "0.0.26.post0"
@@ -16,7 +16,7 @@ from fastapi.responses import UJSONResponse
16
16
  from pydantic import BaseModel
17
17
 
18
18
  from ..__types import DictData
19
- from ..conf import Loader, config, get_logger
19
+ from ..conf import FileLog, Loader, config, get_logger
20
20
  from ..result import Result
21
21
  from ..scheduler import Schedule
22
22
  from ..workflow import Workflow
@@ -99,12 +99,49 @@ async def execute_workflow(name: str, payload: ExecutePayload) -> DictData:
99
99
 
100
100
  @workflow_route.get(path="/{name}/logs")
101
101
  async def get_workflow_logs(name: str):
102
- return {"message": f"Getting workflow {name!r} logs"}
102
+ try:
103
+ return {
104
+ "message": f"Getting workflow {name!r} logs",
105
+ "logs": [
106
+ log.model_dump(
107
+ by_alias=True,
108
+ exclude_none=True,
109
+ exclude_unset=True,
110
+ exclude_defaults=True,
111
+ )
112
+ for log in FileLog.find_logs(name=name)
113
+ ],
114
+ }
115
+ except FileNotFoundError:
116
+ raise HTTPException(
117
+ status_code=st.HTTP_404_NOT_FOUND,
118
+ detail=f"Does not found log for workflow {name!r}",
119
+ ) from None
103
120
 
104
121
 
105
122
  @workflow_route.get(path="/{name}/logs/{release}")
106
123
  async def get_workflow_release_log(name: str, release: str):
107
- return {"message": f"Getting workflow {name!r} log in release {release}"}
124
+ try:
125
+ log: FileLog = FileLog.find_log_with_release(
126
+ name=name, release=datetime.strptime(release, "%Y%m%d%H%M%S")
127
+ )
128
+ except FileNotFoundError:
129
+ raise HTTPException(
130
+ status_code=st.HTTP_404_NOT_FOUND,
131
+ detail=(
132
+ f"Does not found log for workflow {name!r} "
133
+ f"with release {release!r}"
134
+ ),
135
+ ) from None
136
+ return {
137
+ "message": f"Getting workflow {name!r} log in release {release}",
138
+ "log": log.model_dump(
139
+ by_alias=True,
140
+ exclude_none=True,
141
+ exclude_unset=True,
142
+ exclude_defaults=True,
143
+ ),
144
+ }
108
145
 
109
146
 
110
147
  @workflow_route.delete(
@@ -17,7 +17,7 @@ from typing import ClassVar, Optional, TypeVar, Union
17
17
  from zoneinfo import ZoneInfo
18
18
 
19
19
  from ddeutil.core import str2bool
20
- from ddeutil.io import PathSearch, YamlFlResolve
20
+ from ddeutil.io import YamlFlResolve
21
21
  from dotenv import load_dotenv
22
22
  from pydantic import BaseModel, Field
23
23
  from pydantic.functional_validators import model_validator
@@ -93,6 +93,7 @@ class Config:
93
93
  enable_write_log: bool = str2bool(
94
94
  os.getenv("WORKFLOW_LOG_ENABLE_WRITE", "false")
95
95
  )
96
+ log_path: Path = Path(os.getenv("WORKFLOW_LOG_PATH", "./logs"))
96
97
 
97
98
  # NOTE: Stage
98
99
  stage_raise_error: bool = str2bool(
@@ -161,14 +162,6 @@ class Config:
161
162
  f"timedelta with {self.stop_boundary_delta_str}."
162
163
  ) from err
163
164
 
164
- def refresh_dotenv(self) -> Self:
165
- """Reload environment variables from the current stage."""
166
- self.tz: ZoneInfo = ZoneInfo(env("WORKFLOW_CORE_TIMEZONE", "UTC"))
167
- self.stage_raise_error: bool = str2bool(
168
- env("WORKFLOW_CORE_STAGE_RAISE_ERROR", "false")
169
- )
170
- return self
171
-
172
165
  @property
173
166
  def conf_path(self) -> Path:
174
167
  """Config path that use root_path class argument for this construction.
@@ -213,8 +206,14 @@ class SimLoad:
213
206
  externals: DictData | None = None,
214
207
  ) -> None:
215
208
  self.data: DictData = {}
216
- for file in PathSearch(conf.conf_path).files:
217
- if data := self.filter_suffix(file, name):
209
+ for file in conf.conf_path.rglob("*"):
210
+ if not file.is_file():
211
+ continue
212
+
213
+ if data := self.filter_suffix(
214
+ file,
215
+ name,
216
+ ):
218
217
  self.data = data
219
218
 
220
219
  # VALIDATE: check the data that reading should not empty.
@@ -246,7 +245,10 @@ class SimLoad:
246
245
  :rtype: Iterator[tuple[str, DictData]]
247
246
  """
248
247
  exclude: list[str] = excluded or []
249
- for file in PathSearch(conf.conf_path).files:
248
+ for file in conf.conf_path.rglob("*"):
249
+
250
+ if not file.is_file():
251
+ continue
250
252
 
251
253
  for key, data in cls.filter_suffix(file).items():
252
254
 
@@ -362,7 +364,7 @@ class FileLog(BaseLog):
362
364
  """
363
365
 
364
366
  filename_fmt: ClassVar[str] = (
365
- "./logs/workflow={name}/release={release:%Y%m%d%H%M%S}"
367
+ "workflow={name}/release={release:%Y%m%d%H%M%S}"
366
368
  )
367
369
 
368
370
  def do_before(self) -> None:
@@ -378,18 +380,16 @@ class FileLog(BaseLog):
378
380
 
379
381
  :rtype: Iterator[Self]
380
382
  """
381
- pointer: Path = config.root_path / f"./logs/workflow={name}"
383
+ pointer: Path = config.log_path / f"workflow={name}"
382
384
  if not pointer.exists():
383
- raise FileNotFoundError(
384
- f"Pointer: ./logs/workflow={name} does not found."
385
- )
385
+ raise FileNotFoundError(f"Pointer: {pointer.absolute()}.")
386
386
 
387
387
  for file in pointer.glob("./release=*/*.log"):
388
388
  with file.open(mode="r", encoding="utf-8") as f:
389
389
  yield cls.model_validate(obj=json.load(f))
390
390
 
391
391
  @classmethod
392
- def find_log_latest(
392
+ def find_log_with_release(
393
393
  cls,
394
394
  name: str,
395
395
  release: datetime | None = None,
@@ -410,8 +410,7 @@ class FileLog(BaseLog):
410
410
  raise NotImplementedError("Find latest log does not implement yet.")
411
411
 
412
412
  pointer: Path = (
413
- config.root_path
414
- / f"./logs/workflow={name}/release={release:%Y%m%d%H%M%S}"
413
+ config.log_path / f"workflow={name}/release={release:%Y%m%d%H%M%S}"
415
414
  )
416
415
  if not pointer.exists():
417
416
  raise FileNotFoundError(
@@ -440,7 +439,7 @@ class FileLog(BaseLog):
440
439
  return False
441
440
 
442
441
  # NOTE: create pointer path that use the same logic of pointer method.
443
- pointer: Path = config.root_path / cls.filename_fmt.format(
442
+ pointer: Path = config.log_path / cls.filename_fmt.format(
444
443
  name=name, release=release
445
444
  )
446
445
 
@@ -451,7 +450,7 @@ class FileLog(BaseLog):
451
450
 
452
451
  :rtype: Path
453
452
  """
454
- return config.root_path / self.filename_fmt.format(
453
+ return config.log_path / self.filename_fmt.format(
455
454
  name=self.name, release=self.release
456
455
  )
457
456
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ddeutil-workflow
3
- Version: 0.0.25
3
+ Version: 0.0.26.post0
4
4
  Summary: Lightweight workflow orchestration with less dependencies
5
5
  Author-email: ddeutils <korawich.anu@gmail.com>
6
6
  License: MIT
@@ -26,7 +26,6 @@ Requires-Dist: ddeutil>=0.4.3
26
26
  Requires-Dist: ddeutil-io[toml,yaml]>=0.2.3
27
27
  Requires-Dist: pydantic==2.10.4
28
28
  Requires-Dist: python-dotenv==1.0.1
29
- Requires-Dist: typer==0.15.1
30
29
  Requires-Dist: schedule<2.0.0,==1.2.2
31
30
  Provides-Extra: api
32
31
  Requires-Dist: fastapi<1.0.0,>=0.115.0; extra == "api"
@@ -80,20 +79,10 @@ This project need `ddeutil` and `ddeutil-io` extension namespace packages.
80
79
  If you want to install this package with application add-ons, you should add
81
80
  `app` in installation;
82
81
 
83
- | Usecase | Install Optional | Support |
84
- |-------------------|------------------------------------------|--------------------|
85
- | Python & CLI | `pip install ddeutil-workflow` | :heavy_check_mark: |
86
- | FastAPI Server | `pip install ddeutil-workflow[api]` | :heavy_check_mark: |
87
-
88
- > :egg: **Docker Images** supported:
89
- >
90
- > | Docker Image | Python Version | Support |
91
- > |-----------------------------|----------------|---------|
92
- > | ddeutil-workflow:latest | `3.9` | :x: |
93
- > | ddeutil-workflow:python3.10 | `3.10` | :x: |
94
- > | ddeutil-workflow:python3.11 | `3.11` | :x: |
95
- > | ddeutil-workflow:python3.12 | `3.12` | :x: |
96
- > | ddeutil-workflow:python3.12 | `3.13` | :x: |
82
+ | Usecase | Install Optional | Support |
83
+ |----------------|------------------------------------------|--------------------|
84
+ | Python | `pip install ddeutil-workflow` | :heavy_check_mark: |
85
+ | FastAPI Server | `pip install ddeutil-workflow[api]` | :heavy_check_mark: |
97
86
 
98
87
  ## :beers: Usage
99
88
 
@@ -110,7 +99,7 @@ use-case.
110
99
  run-py-local:
111
100
 
112
101
  # Validate model that use to parsing exists for template file
113
- type: ddeutil.workflow.workflow.Workflow
102
+ type: Workflow
114
103
  on:
115
104
  # If workflow deploy to schedule, it will running every 5 minutes
116
105
  # with Asia/Bangkok timezone.
@@ -161,7 +150,7 @@ So, this package provide the `Schedule` template for this action.
161
150
  schedule-run-local-wf:
162
151
 
163
152
  # Validate model that use to parsing exists for template file
164
- type: ddeutil.workflow.scheduler.Schedule
153
+ type: Schedule
165
154
  workflows:
166
155
 
167
156
  # Map existing workflow that want to deploy with scheduler application.
@@ -179,35 +168,36 @@ The main configuration that use to dynamic changing with your propose of this
179
168
  application. If any configuration values do not set yet, it will use default value
180
169
  and do not raise any error to you.
181
170
 
182
- | Environment | Component | Default | Description | Remark |
183
- |:----------------------------------------|:----------:|:---------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|--------|
184
- | `WORKFLOW_ROOT_PATH` | Core | . | The root path of the workflow application. | |
185
- | `WORKFLOW_CORE_REGISTRY` | Core | src,src.ddeutil.workflow,tests,tests.utils | List of importable string for the hook stage. | |
186
- | `WORKFLOW_CORE_REGISTRY_FILTER` | Core | src.ddeutil.workflow.utils,ddeutil.workflow.utils | List of importable string for the filter template. | |
187
- | `WORKFLOW_CORE_PATH_CONF` | Core | conf | The config path that keep all template `.yaml` files. | |
188
- | `WORKFLOW_CORE_TIMEZONE` | Core | Asia/Bangkok | A Timezone string value that will pass to `ZoneInfo` object. | |
189
- | `WORKFLOW_CORE_STAGE_DEFAULT_ID` | Core | true | A flag that enable default stage ID that use for catch an execution output. | |
190
- | `WORKFLOW_CORE_STAGE_RAISE_ERROR` | Core | false | A flag that all stage raise StageException from stage execution. | |
191
- | `WORKFLOW_CORE_JOB_DEFAULT_ID` | Core | false | A flag that enable default job ID that use for catch an execution output. The ID that use will be sequence number. | |
192
- | `WORKFLOW_CORE_JOB_RAISE_ERROR` | Core | true | A flag that all job raise JobException from job strategy execution. | |
193
- | `WORKFLOW_CORE_MAX_NUM_POKING` | Core | 4 | . | |
194
- | `WORKFLOW_CORE_MAX_JOB_PARALLEL` | Core | 2 | The maximum job number that able to run parallel in workflow executor. | |
195
- | `WORKFLOW_CORE_MAX_JOB_EXEC_TIMEOUT` | Core | 600 | | |
196
- | `WORKFLOW_CORE_MAX_CRON_PER_WORKFLOW` | Core | 5 | | |
197
- | `WORKFLOW_CORE_MAX_QUEUE_COMPLETE_HIST` | Core | 16 | | |
198
- | `WORKFLOW_CORE_GENERATE_ID_SIMPLE_MODE` | Core | true | A flog that enable generating ID with `md5` algorithm. | |
199
- | `WORKFLOW_LOG_DEBUG_MODE` | Log | true | A flag that enable logging with debug level mode. | |
200
- | `WORKFLOW_LOG_ENABLE_WRITE` | Log | true | A flag that enable logging object saving log to its destination. | |
201
- | `WORKFLOW_APP_MAX_PROCESS` | Schedule | 2 | The maximum process worker number that run in scheduler app module. | |
202
- | `WORKFLOW_APP_MAX_SCHEDULE_PER_PROCESS` | Schedule | 100 | A schedule per process that run parallel. | |
203
- | `WORKFLOW_APP_STOP_BOUNDARY_DELTA` | Schedule | '{"minutes": 5, "seconds": 20}' | A time delta value that use to stop scheduler app in json string format. | |
171
+ | Environment | Component | Default | Description | Remark |
172
+ |:-------------------------------------------|:---------:|:-----------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|--------|
173
+ | **WORKFLOW_ROOT_PATH** | Core | `.` | The root path of the workflow application. | |
174
+ | **WORKFLOW_CORE_REGISTRY** | Core | `src,src.ddeutil.workflow,tests,tests.utils` | List of importable string for the hook stage. | |
175
+ | **WORKFLOW_CORE_REGISTRY_FILTER** | Core | `src.ddeutil.workflow.utils,ddeutil.workflow.utils` | List of importable string for the filter template. | |
176
+ | **WORKFLOW_CORE_PATH_CONF** | Core | `conf` | The config path that keep all template `.yaml` files. | |
177
+ | **WORKFLOW_CORE_TIMEZONE** | Core | `Asia/Bangkok` | A Timezone string value that will pass to `ZoneInfo` object. | |
178
+ | **WORKFLOW_CORE_STAGE_DEFAULT_ID** | Core | `true` | A flag that enable default stage ID that use for catch an execution output. | |
179
+ | **WORKFLOW_CORE_STAGE_RAISE_ERROR** | Core | `false` | A flag that all stage raise StageException from stage execution. | |
180
+ | **WORKFLOW_CORE_JOB_DEFAULT_ID** | Core | `false` | A flag that enable default job ID that use for catch an execution output. The ID that use will be sequence number. | |
181
+ | **WORKFLOW_CORE_JOB_RAISE_ERROR** | Core | `true` | A flag that all job raise JobException from job strategy execution. | |
182
+ | **WORKFLOW_CORE_MAX_NUM_POKING** | Core | `4` | . | |
183
+ | **WORKFLOW_CORE_MAX_JOB_PARALLEL** | Core | `2` | The maximum job number that able to run parallel in workflow executor. | |
184
+ | **WORKFLOW_CORE_MAX_JOB_EXEC_TIMEOUT** | Core | `600` | | |
185
+ | **WORKFLOW_CORE_MAX_CRON_PER_WORKFLOW** | Core | `5` | | |
186
+ | **WORKFLOW_CORE_MAX_QUEUE_COMPLETE_HIST** | Core | `16` | | |
187
+ | **WORKFLOW_CORE_GENERATE_ID_SIMPLE_MODE** | Core | `true` | A flog that enable generating ID with `md5` algorithm. | |
188
+ | **WORKFLOW_LOG_PATH** | Log | `./logs` | The log path of the workflow saving log. | |
189
+ | **WORKFLOW_LOG_DEBUG_MODE** | Log | `true` | A flag that enable logging with debug level mode. | |
190
+ | **WORKFLOW_LOG_ENABLE_WRITE** | Log | `true` | A flag that enable logging object saving log to its destination. | |
191
+ | **WORKFLOW_APP_MAX_PROCESS** | Schedule | `2` | The maximum process worker number that run in scheduler app module. | |
192
+ | **WORKFLOW_APP_MAX_SCHEDULE_PER_PROCESS** | Schedule | `100` | A schedule per process that run parallel. | |
193
+ | **WORKFLOW_APP_STOP_BOUNDARY_DELTA** | Schedule | `'{"minutes": 5, "seconds": 20}'` | A time delta value that use to stop scheduler app in json string format. | |
204
194
 
205
195
  **API Application**:
206
196
 
207
- | Environment | Component | Default | Description | Remark |
208
- |:--------------------------------------|:-----------:|---------|------------------------------------------------------------------------------------|--------|
209
- | `WORKFLOW_API_ENABLE_ROUTE_WORKFLOW` | API | true | A flag that enable workflow route to manage execute manually and workflow logging. | |
210
- | `WORKFLOW_API_ENABLE_ROUTE_SCHEDULE` | API | true | A flag that enable run scheduler. | |
197
+ | Environment | Component | Default | Description | Remark |
198
+ |:----------------------------------------|:-----------:|---------|------------------------------------------------------------------------------------|--------|
199
+ | **WORKFLOW_API_ENABLE_ROUTE_WORKFLOW** | API | `true` | A flag that enable workflow route to manage execute manually and workflow logging. | |
200
+ | **WORKFLOW_API_ENABLE_ROUTE_SCHEDULE** | API | `true` | A flag that enable run scheduler. | |
211
201
 
212
202
  ## :rocket: Deployment
213
203
 
@@ -215,12 +205,6 @@ This package able to run as a application service for receive manual trigger
215
205
  from the master node via RestAPI or use to be Scheduler background service
216
206
  like crontab job but via Python API.
217
207
 
218
- ### CLI
219
-
220
- ```shell
221
- (venv) $ ddeutil-workflow schedule
222
- ```
223
-
224
208
  ### API Server
225
209
 
226
210
  ```shell
@@ -5,7 +5,6 @@ src/ddeutil/workflow/__about__.py
5
5
  src/ddeutil/workflow/__cron.py
6
6
  src/ddeutil/workflow/__init__.py
7
7
  src/ddeutil/workflow/__types.py
8
- src/ddeutil/workflow/cli.py
9
8
  src/ddeutil/workflow/conf.py
10
9
  src/ddeutil/workflow/cron.py
11
10
  src/ddeutil/workflow/exceptions.py
@@ -23,12 +22,10 @@ src/ddeutil/workflow/api/route.py
23
22
  src/ddeutil_workflow.egg-info/PKG-INFO
24
23
  src/ddeutil_workflow.egg-info/SOURCES.txt
25
24
  src/ddeutil_workflow.egg-info/dependency_links.txt
26
- src/ddeutil_workflow.egg-info/entry_points.txt
27
25
  src/ddeutil_workflow.egg-info/requires.txt
28
26
  src/ddeutil_workflow.egg-info/top_level.txt
29
27
  tests/test__cron.py
30
28
  tests/test__regex.py
31
- tests/test_cli.py
32
29
  tests/test_conf.py
33
30
  tests/test_conf_log.py
34
31
  tests/test_cron_on.py
@@ -2,7 +2,6 @@ ddeutil>=0.4.3
2
2
  ddeutil-io[toml,yaml]>=0.2.3
3
3
  pydantic==2.10.4
4
4
  python-dotenv==1.0.1
5
- typer==0.15.1
6
5
  schedule<2.0.0,==1.2.2
7
6
 
8
7
  [api]
@@ -43,7 +43,7 @@ def test_conf_log_file_do_first():
43
43
  },
44
44
  )
45
45
  log.save(excluded=None)
46
- log = FileLog.find_log_latest(
46
+ log = FileLog.find_log_with_release(
47
47
  name="wf-demo-logging",
48
48
  release=datetime(2024, 1, 1, 1),
49
49
  )
@@ -79,6 +79,12 @@ def test_conf_log_file_find_logs(root_path):
79
79
 
80
80
  for log in FileLog.find_logs(name="wf-no-release-log"):
81
81
  assert isinstance(log, FileLog)
82
+ log.model_dump(
83
+ by_alias=True,
84
+ exclude_none=True,
85
+ exclude_unset=True,
86
+ exclude_defaults=True,
87
+ )
82
88
 
83
89
 
84
90
  def test_conf_log_file_find_logs_raise():
@@ -86,9 +92,9 @@ def test_conf_log_file_find_logs_raise():
86
92
  next(FileLog.find_logs(name="wf-file-not-found"))
87
93
 
88
94
 
89
- def test_conf_log_file_find_log_latest():
95
+ def test_conf_log_file_find_log_with_release():
90
96
  with pytest.raises(FileNotFoundError):
91
- FileLog.find_log_latest(
97
+ FileLog.find_log_with_release(
92
98
  name="wf-file-not-found",
93
99
  release=datetime(2024, 1, 1, 1),
94
100
  )
@@ -1 +0,0 @@
1
- __version__: str = "0.0.25"
@@ -1,108 +0,0 @@
1
- # ------------------------------------------------------------------------------
2
- # Copyright (c) 2022 Korawich Anuttra. All rights reserved.
3
- # Licensed under the MIT License. See LICENSE in the project root for
4
- # license information.
5
- # ------------------------------------------------------------------------------
6
- from __future__ import annotations
7
-
8
- import json
9
- import sys
10
- from datetime import datetime
11
- from typing import Annotated, Optional
12
-
13
- from ddeutil.core import str2list
14
- from typer import Argument, Typer, echo
15
-
16
- from .conf import config
17
-
18
- cli: Typer = Typer()
19
-
20
-
21
- @cli.command()
22
- def run(
23
- workflow: Annotated[
24
- str,
25
- Argument(help="A workflow name that want to run manually"),
26
- ],
27
- params: Annotated[
28
- str,
29
- Argument(
30
- help="A json string for parameters of this workflow execution.",
31
- ),
32
- ],
33
- ):
34
- """Run workflow workflow manually with an input custom parameters that able
35
- to receive with workflow params config.
36
- """
37
- echo(f"Running workflow name: ({type(workflow)}) {workflow!r}")
38
- echo(f"... with Parameters: ({type(params)}) {params!r}")
39
-
40
- from .result import Result
41
- from .workflow import Workflow
42
-
43
- try:
44
- wf: Workflow = Workflow.from_loader(name=workflow)
45
- rs: Result = wf.execute(params=json.loads(params))
46
- except Exception as err:
47
- echo(str(err))
48
- sys.exit(1)
49
-
50
- echo(f"Result: {rs}")
51
- sys.exit(0)
52
-
53
-
54
- @cli.command()
55
- def schedule(
56
- stop: Annotated[
57
- Optional[datetime],
58
- Argument(
59
- formats=["%Y-%m-%d", "%Y-%m-%d %H:%M:%S"],
60
- help="A stopping datetime that want to stop on schedule app.",
61
- ),
62
- ] = None,
63
- excluded: Annotated[
64
- Optional[str],
65
- Argument(help="A list of exclude workflow name in str."),
66
- ] = None,
67
- externals: Annotated[
68
- Optional[str],
69
- Argument(
70
- help="A json string for parameters of this workflow execution."
71
- ),
72
- ] = None,
73
- ):
74
- """Start workflow scheduler that will call workflow function from scheduler
75
- module.
76
- """
77
- excluded: list[str] = str2list(excluded) if excluded else []
78
- echo(f"... with Excluded Parameters: {excluded!r}")
79
- externals: str = externals or "{}"
80
-
81
- # NOTE: Convert timezone on the stop date.
82
- if stop:
83
- stop: datetime = stop.astimezone(tz=config.tz)
84
-
85
- from .scheduler import schedule_runner
86
-
87
- try:
88
- # NOTE: Start running workflow scheduler application.
89
- workflow_rs: list[str] = schedule_runner(
90
- stop=stop, excluded=excluded, externals=json.loads(externals)
91
- )
92
- echo(f"Schedule with CLI run success with: {workflow_rs}")
93
- except Exception as err:
94
- echo(str(err))
95
- sys.exit(1)
96
-
97
- sys.exit(0)
98
-
99
-
100
- @cli.callback()
101
- def main():
102
- """
103
- Manage workflow with CLI.
104
- """
105
-
106
-
107
- if __name__ == "__main__":
108
- cli()
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- ddeutil-workflow = ddeutil.workflow.cli:cli
@@ -1,44 +0,0 @@
1
- from datetime import datetime, timedelta
2
-
3
- from ddeutil.workflow.cli import cli
4
- from typer.testing import CliRunner, Result
5
-
6
-
7
- def test_cli_workflow():
8
- runner = CliRunner()
9
- result: Result = runner.invoke(
10
- cli,
11
- [
12
- "run",
13
- "wf-scheduling-agent",
14
- '{"name": "Foo", "asat-dt": "2024-01-01"}',
15
- ],
16
- )
17
- assert result.exit_code == 0
18
- assert (
19
- "Running workflow name: (<class 'str'>) " "'wf-scheduling-agent'"
20
- ) in result.stdout
21
-
22
-
23
- def test_cli_schedule():
24
- runner = CliRunner()
25
- stop_date: datetime = datetime.now().replace(
26
- second=0, microsecond=0
27
- ) + timedelta(minutes=2)
28
- result: Result = runner.invoke(
29
- cli,
30
- [
31
- "schedule",
32
- "--stop",
33
- stop_date.strftime("%Y-%m-%d %H:%M:%S"),
34
- "--excluded",
35
- (
36
- '["schedule-common-wf", '
37
- '"schedule-multi-on-wf", '
38
- '"schedule-every-minute-wf", '
39
- '"schedule-every-minute-wf-parallel"]'
40
- ),
41
- ],
42
- )
43
- assert result.exit_code == 0
44
- print(result.stdout)