ddeutil-workflow 0.0.29__tar.gz → 0.0.31__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.29/src/ddeutil_workflow.egg-info → ddeutil_workflow-0.0.31}/PKG-INFO +17 -12
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/README.md +16 -11
- ddeutil_workflow-0.0.31/src/ddeutil/workflow/__about__.py +1 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/__cron.py +1 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/__init__.py +5 -1
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/api/api.py +2 -2
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/conf.py +4 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/cron.py +77 -21
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/exceptions.py +3 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/hook.py +3 -1
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/params.py +18 -1
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/result.py +1 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/scheduler.py +101 -67
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/stage.py +13 -1
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/utils.py +36 -10
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/workflow.py +179 -141
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31/src/ddeutil_workflow.egg-info}/PKG-INFO +17 -12
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil_workflow.egg-info/SOURCES.txt +5 -5
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_cron_on.py +9 -0
- ddeutil_workflow-0.0.31/tests/test_release.py +62 -0
- ddeutil_workflow-0.0.31/tests/test_release_queue.py +66 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_schedule_control.py +6 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_schedule_tasks.py +4 -4
- ddeutil_workflow-0.0.29/tests/test_workflow_schedule.py → ddeutil_workflow-0.0.31/tests/test_schedule_workflow.py +31 -31
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_stage_handler_exec.py +63 -36
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_utils.py +15 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_workflow_exec.py +126 -0
- ddeutil_workflow-0.0.29/tests/test_workflow_poke.py → ddeutil_workflow-0.0.31/tests/test_workflow_exec_poke.py +14 -7
- ddeutil_workflow-0.0.29/tests/test_workflow_release.py → ddeutil_workflow-0.0.31/tests/test_workflow_exec_release.py +25 -9
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_workflow_task.py +15 -6
- ddeutil_workflow-0.0.29/src/ddeutil/workflow/__about__.py +0 -1
- ddeutil_workflow-0.0.29/tests/test_workflow_exec_hook.py +0 -91
- ddeutil_workflow-0.0.29/tests/test_workflow_release_and_queue.py +0 -77
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/LICENSE +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/pyproject.toml +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/setup.cfg +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/__types.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/api/__init__.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/api/repeat.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/api/route.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/job.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil/workflow/templates.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil_workflow.egg-info/dependency_links.txt +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil_workflow.egg-info/requires.txt +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/src/ddeutil_workflow.egg-info/top_level.txt +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test__cron.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test__regex.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_conf.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_conf_log.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_hook_tag.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_job.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_job_exec_py.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_job_exec_strategy.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_job_strategy.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_params.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_result.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_schedule.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_stage.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_templates.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_templates_filter.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_workflow.py +0 -0
- {ddeutil_workflow-0.0.29 → ddeutil_workflow-0.0.31}/tests/test_workflow_job_exec.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: ddeutil-workflow
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.31
|
4
4
|
Summary: Lightweight workflow orchestration
|
5
5
|
Author-email: ddeutils <korawich.anu@gmail.com>
|
6
6
|
License: MIT
|
@@ -192,6 +192,15 @@ The above workflow template is main executor pipeline that you want to do. If yo
|
|
192
192
|
want to schedule this workflow, you want to dynamic its parameters change base on
|
193
193
|
execution time such as `run-date` should change base on that workflow running date.
|
194
194
|
|
195
|
+
```python
|
196
|
+
from ddeutil.workflow import Workflow, Result
|
197
|
+
|
198
|
+
workflow: Workflow = Workflow.from_loader('run-py-local')
|
199
|
+
result: Result = workflow.execute(
|
200
|
+
params={"source-extract": "USD-THB", "asat-dt": "2024-01-01"}
|
201
|
+
)
|
202
|
+
```
|
203
|
+
|
195
204
|
So, this package provide the `Schedule` template for this action.
|
196
205
|
|
197
206
|
```yaml
|
@@ -212,9 +221,9 @@ schedule-run-local-wf:
|
|
212
221
|
|
213
222
|
## :cookie: Configuration
|
214
223
|
|
215
|
-
The main configuration that use to dynamic changing
|
216
|
-
|
217
|
-
and do not raise any error to you.
|
224
|
+
The main configuration that use to dynamic changing this workflow engine for your
|
225
|
+
objective use environment variable only. If any configuration values do not set yet,
|
226
|
+
it will use default value and do not raise any error to you.
|
218
227
|
|
219
228
|
> [!IMPORTANT]
|
220
229
|
> The config value that you will set on the environment should combine with
|
@@ -246,6 +255,9 @@ and do not raise any error to you.
|
|
246
255
|
|
247
256
|
**API Application**:
|
248
257
|
|
258
|
+
This config part use for the workflow application that build from the FastAPI
|
259
|
+
only.
|
260
|
+
|
249
261
|
| Environment | Component | Default | Description |
|
250
262
|
|:---------------------------|:-----------:|---------|------------------------------------------------------------------------------------|
|
251
263
|
| **ENABLE_ROUTE_WORKFLOW** | API | `true` | A flag that enable workflow route to manage execute manually and workflow logging. |
|
@@ -272,16 +284,9 @@ like crontab job but via Python API.
|
|
272
284
|
|
273
285
|
### Docker Container
|
274
286
|
|
275
|
-
Create Docker image;
|
276
|
-
|
277
287
|
```shell
|
278
288
|
$ docker build -t ddeutil-workflow:latest -f .container/Dockerfile .
|
279
|
-
|
280
|
-
|
281
|
-
Run the above Docker image;
|
282
|
-
|
283
|
-
```shell
|
284
|
-
$ docker run -i ddeutil-workflow:latest
|
289
|
+
$ docker run -i ddeutil-workflow:latest ddeutil-workflow
|
285
290
|
```
|
286
291
|
|
287
292
|
## :speech_balloon: Contribute
|
@@ -160,6 +160,15 @@ The above workflow template is main executor pipeline that you want to do. If yo
|
|
160
160
|
want to schedule this workflow, you want to dynamic its parameters change base on
|
161
161
|
execution time such as `run-date` should change base on that workflow running date.
|
162
162
|
|
163
|
+
```python
|
164
|
+
from ddeutil.workflow import Workflow, Result
|
165
|
+
|
166
|
+
workflow: Workflow = Workflow.from_loader('run-py-local')
|
167
|
+
result: Result = workflow.execute(
|
168
|
+
params={"source-extract": "USD-THB", "asat-dt": "2024-01-01"}
|
169
|
+
)
|
170
|
+
```
|
171
|
+
|
163
172
|
So, this package provide the `Schedule` template for this action.
|
164
173
|
|
165
174
|
```yaml
|
@@ -180,9 +189,9 @@ schedule-run-local-wf:
|
|
180
189
|
|
181
190
|
## :cookie: Configuration
|
182
191
|
|
183
|
-
The main configuration that use to dynamic changing
|
184
|
-
|
185
|
-
and do not raise any error to you.
|
192
|
+
The main configuration that use to dynamic changing this workflow engine for your
|
193
|
+
objective use environment variable only. If any configuration values do not set yet,
|
194
|
+
it will use default value and do not raise any error to you.
|
186
195
|
|
187
196
|
> [!IMPORTANT]
|
188
197
|
> The config value that you will set on the environment should combine with
|
@@ -214,6 +223,9 @@ and do not raise any error to you.
|
|
214
223
|
|
215
224
|
**API Application**:
|
216
225
|
|
226
|
+
This config part use for the workflow application that build from the FastAPI
|
227
|
+
only.
|
228
|
+
|
217
229
|
| Environment | Component | Default | Description |
|
218
230
|
|:---------------------------|:-----------:|---------|------------------------------------------------------------------------------------|
|
219
231
|
| **ENABLE_ROUTE_WORKFLOW** | API | `true` | A flag that enable workflow route to manage execute manually and workflow logging. |
|
@@ -240,16 +252,9 @@ like crontab job but via Python API.
|
|
240
252
|
|
241
253
|
### Docker Container
|
242
254
|
|
243
|
-
Create Docker image;
|
244
|
-
|
245
255
|
```shell
|
246
256
|
$ docker build -t ddeutil-workflow:latest -f .container/Dockerfile .
|
247
|
-
|
248
|
-
|
249
|
-
Run the above Docker image;
|
250
|
-
|
251
|
-
```shell
|
252
|
-
$ docker run -i ddeutil-workflow:latest
|
257
|
+
$ docker run -i ddeutil-workflow:latest ddeutil-workflow
|
253
258
|
```
|
254
259
|
|
255
260
|
## :speech_balloon: Contribute
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__: str = "0.0.31"
|
@@ -47,8 +47,10 @@ from .params import (
|
|
47
47
|
from .result import Result
|
48
48
|
from .scheduler import (
|
49
49
|
Schedule,
|
50
|
-
|
50
|
+
ScheduleWorkflow,
|
51
|
+
schedule_control,
|
51
52
|
schedule_runner,
|
53
|
+
schedule_task,
|
52
54
|
)
|
53
55
|
from .stage import (
|
54
56
|
BashStage,
|
@@ -83,6 +85,8 @@ from .utils import (
|
|
83
85
|
make_exec,
|
84
86
|
)
|
85
87
|
from .workflow import (
|
88
|
+
Release,
|
89
|
+
ReleaseQueue,
|
86
90
|
Workflow,
|
87
91
|
WorkflowTask,
|
88
92
|
)
|
@@ -18,7 +18,7 @@ from fastapi.responses import UJSONResponse
|
|
18
18
|
from ..__about__ import __version__
|
19
19
|
from ..conf import config, get_logger
|
20
20
|
from ..scheduler import ReleaseThread, ReleaseThreads
|
21
|
-
from ..workflow import
|
21
|
+
from ..workflow import ReleaseQueue, WorkflowTask
|
22
22
|
from .repeat import repeat_at
|
23
23
|
|
24
24
|
load_dotenv()
|
@@ -31,7 +31,7 @@ class State(TypedDict):
|
|
31
31
|
scheduler: list[str]
|
32
32
|
workflow_threads: ReleaseThreads
|
33
33
|
workflow_tasks: list[WorkflowTask]
|
34
|
-
workflow_queue: dict[str,
|
34
|
+
workflow_queue: dict[str, ReleaseQueue]
|
35
35
|
|
36
36
|
|
37
37
|
@contextlib.asynccontextmanager
|
@@ -582,6 +582,10 @@ Log = Union[
|
|
582
582
|
|
583
583
|
|
584
584
|
def get_log() -> type[Log]: # pragma: no cov
|
585
|
+
"""Get logging class that dynamic base on the config log path value.
|
586
|
+
|
587
|
+
:rtype: type[Log]
|
588
|
+
"""
|
585
589
|
if config.log_path.is_file():
|
586
590
|
return SQLiteLog
|
587
591
|
return FileLog
|
@@ -5,16 +5,17 @@
|
|
5
5
|
# ------------------------------------------------------------------------------
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
|
+
from dataclasses import fields
|
8
9
|
from datetime import datetime
|
9
|
-
from typing import Annotated, Literal
|
10
|
+
from typing import Annotated, Literal, Union
|
10
11
|
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
11
12
|
|
12
|
-
from pydantic import BaseModel, ConfigDict, Field
|
13
|
+
from pydantic import BaseModel, ConfigDict, Field, ValidationInfo
|
13
14
|
from pydantic.functional_serializers import field_serializer
|
14
15
|
from pydantic.functional_validators import field_validator, model_validator
|
15
16
|
from typing_extensions import Self
|
16
17
|
|
17
|
-
from .__cron import WEEKDAYS, CronJob, CronJobYear, CronRunner
|
18
|
+
from .__cron import WEEKDAYS, CronJob, CronJobYear, CronRunner, Options
|
18
19
|
from .__types import DictData, DictStr, TupleStr
|
19
20
|
from .conf import Loader
|
20
21
|
|
@@ -47,6 +48,8 @@ def interval2crontab(
|
|
47
48
|
'0 0 1 * *'
|
48
49
|
>>> interval2crontab(interval='monthly', day='tuesday', time='12:00')
|
49
50
|
'12 0 1 * 2'
|
51
|
+
|
52
|
+
:rtype: str
|
50
53
|
"""
|
51
54
|
d: str = "*"
|
52
55
|
if interval == "weekly":
|
@@ -64,12 +67,19 @@ class On(BaseModel):
|
|
64
67
|
"""On Pydantic model (Warped crontab object by model).
|
65
68
|
|
66
69
|
See Also:
|
67
|
-
* ``generate()`` is the main
|
70
|
+
* ``generate()`` is the main use-case of this schedule object.
|
68
71
|
"""
|
69
72
|
|
70
73
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
71
74
|
|
72
75
|
# NOTE: This is fields of the base schedule.
|
76
|
+
extras: Annotated[
|
77
|
+
DictData,
|
78
|
+
Field(
|
79
|
+
default_factory=dict,
|
80
|
+
description="An extras mapping parameters",
|
81
|
+
),
|
82
|
+
]
|
73
83
|
cronjob: Annotated[
|
74
84
|
CronJob,
|
75
85
|
Field(description="Cron job of this schedule"),
|
@@ -81,13 +91,6 @@ class On(BaseModel):
|
|
81
91
|
alias="timezone",
|
82
92
|
),
|
83
93
|
] = "Etc/UTC"
|
84
|
-
extras: Annotated[
|
85
|
-
DictData,
|
86
|
-
Field(
|
87
|
-
default_factory=dict,
|
88
|
-
description="An extras mapping parameters",
|
89
|
-
),
|
90
|
-
]
|
91
94
|
|
92
95
|
@classmethod
|
93
96
|
def from_value(cls, value: DictStr, externals: DictData) -> Self:
|
@@ -153,6 +156,7 @@ class On(BaseModel):
|
|
153
156
|
|
154
157
|
@model_validator(mode="before")
|
155
158
|
def __prepare_values(cls, values: DictData) -> DictData:
|
159
|
+
"""Extract tz key from value and change name to timezone key."""
|
156
160
|
if tz := values.pop("tz", None):
|
157
161
|
values["timezone"] = tz
|
158
162
|
return values
|
@@ -160,24 +164,55 @@ class On(BaseModel):
|
|
160
164
|
@field_validator("tz")
|
161
165
|
def __validate_tz(cls, value: str) -> str:
|
162
166
|
"""Validate timezone value that able to initialize with ZoneInfo after
|
163
|
-
it passing to this model in before mode.
|
167
|
+
it passing to this model in before mode.
|
168
|
+
|
169
|
+
:rtype: str
|
170
|
+
"""
|
164
171
|
try:
|
165
172
|
_ = ZoneInfo(value)
|
166
173
|
return value
|
167
174
|
except ZoneInfoNotFoundError as err:
|
168
175
|
raise ValueError(f"Invalid timezone: {value}") from err
|
169
176
|
|
170
|
-
@field_validator(
|
171
|
-
|
172
|
-
|
173
|
-
|
177
|
+
@field_validator(
|
178
|
+
"cronjob", mode="before", json_schema_input_type=Union[CronJob, str]
|
179
|
+
)
|
180
|
+
def __prepare_cronjob(
|
181
|
+
cls, value: str | CronJob, info: ValidationInfo
|
182
|
+
) -> CronJob:
|
183
|
+
"""Prepare crontab value that able to receive with string type.
|
184
|
+
This step will get options kwargs from extras and pass to the
|
185
|
+
CronJob object.
|
186
|
+
|
187
|
+
:rtype: CronJob
|
188
|
+
"""
|
189
|
+
extras: DictData = info.data.get("extras", {})
|
190
|
+
return (
|
191
|
+
CronJob(
|
192
|
+
value,
|
193
|
+
option={
|
194
|
+
name: extras[name]
|
195
|
+
for name in (f.name for f in fields(Options))
|
196
|
+
if name in extras
|
197
|
+
},
|
198
|
+
)
|
199
|
+
if isinstance(value, str)
|
200
|
+
else value
|
201
|
+
)
|
174
202
|
|
175
203
|
@field_serializer("cronjob")
|
176
204
|
def __serialize_cronjob(self, value: CronJob) -> str:
|
205
|
+
"""Serialize the cronjob field that store with CronJob object.
|
206
|
+
|
207
|
+
:rtype: str
|
208
|
+
"""
|
177
209
|
return str(value)
|
178
210
|
|
179
211
|
def generate(self, start: str | datetime) -> CronRunner:
|
180
|
-
"""Return Cron runner object.
|
212
|
+
"""Return Cron runner object.
|
213
|
+
|
214
|
+
:rtype: CronRunner
|
215
|
+
"""
|
181
216
|
if isinstance(start, str):
|
182
217
|
start: datetime = datetime.fromisoformat(start)
|
183
218
|
elif not isinstance(start, datetime):
|
@@ -187,6 +222,8 @@ class On(BaseModel):
|
|
187
222
|
def next(self, start: str | datetime) -> CronRunner:
|
188
223
|
"""Return a next datetime from Cron runner object that start with any
|
189
224
|
date that given from input.
|
225
|
+
|
226
|
+
:rtype: CronRunner
|
190
227
|
"""
|
191
228
|
runner: CronRunner = self.generate(start=start)
|
192
229
|
|
@@ -209,7 +246,26 @@ class YearOn(On):
|
|
209
246
|
Field(description="Cron job of this schedule"),
|
210
247
|
]
|
211
248
|
|
212
|
-
@field_validator(
|
213
|
-
|
214
|
-
|
215
|
-
|
249
|
+
@field_validator(
|
250
|
+
"cronjob", mode="before", json_schema_input_type=Union[CronJob, str]
|
251
|
+
)
|
252
|
+
def __prepare_cronjob(
|
253
|
+
cls, value: str | CronJobYear, info: ValidationInfo
|
254
|
+
) -> CronJobYear:
|
255
|
+
"""Prepare crontab value that able to receive with string type.
|
256
|
+
|
257
|
+
:rtype: CronJobYear
|
258
|
+
"""
|
259
|
+
extras: DictData = info.data.get("extras", {})
|
260
|
+
return (
|
261
|
+
CronJobYear(
|
262
|
+
value,
|
263
|
+
option={
|
264
|
+
name: extras[name]
|
265
|
+
for name in (f.name for f in fields(Options))
|
266
|
+
if name in extras
|
267
|
+
},
|
268
|
+
)
|
269
|
+
if isinstance(value, str)
|
270
|
+
else value
|
271
|
+
)
|
@@ -79,7 +79,9 @@ def make_registry(submodule: str) -> dict[str, Registry]:
|
|
79
79
|
:rtype: dict[str, Registry]
|
80
80
|
"""
|
81
81
|
rs: dict[str, Registry] = {}
|
82
|
-
|
82
|
+
regis_hooks: list[str] = config.regis_hook
|
83
|
+
regis_hooks.extend(["ddeutil.vendors"])
|
84
|
+
for module in regis_hooks:
|
83
85
|
# NOTE: try to sequential import task functions
|
84
86
|
try:
|
85
87
|
importer = import_module(f"{module}.{submodule}")
|
@@ -5,6 +5,7 @@
|
|
5
5
|
# ------------------------------------------------------------------------------
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
|
+
import decimal
|
8
9
|
import logging
|
9
10
|
from abc import ABC, abstractmethod
|
10
11
|
from datetime import date, datetime
|
@@ -49,7 +50,7 @@ class BaseParam(BaseModel, ABC):
|
|
49
50
|
|
50
51
|
class DefaultParam(BaseParam):
|
51
52
|
"""Default Parameter that will check default if it required. This model do
|
52
|
-
not implement the receive method.
|
53
|
+
not implement the `receive` method.
|
53
54
|
"""
|
54
55
|
|
55
56
|
required: bool = Field(
|
@@ -68,6 +69,15 @@ class DefaultParam(BaseParam):
|
|
68
69
|
)
|
69
70
|
|
70
71
|
|
72
|
+
# TODO: Not implement this parameter yet
|
73
|
+
class DateParam(DefaultParam):
|
74
|
+
"""Date parameter."""
|
75
|
+
|
76
|
+
type: Literal["date"] = "date"
|
77
|
+
|
78
|
+
def receive(self, value: Optional[str | date] = None) -> date: ...
|
79
|
+
|
80
|
+
|
71
81
|
class DatetimeParam(DefaultParam):
|
72
82
|
"""Datetime parameter."""
|
73
83
|
|
@@ -145,6 +155,13 @@ class IntParam(DefaultParam):
|
|
145
155
|
return value
|
146
156
|
|
147
157
|
|
158
|
+
# TODO: Not implement this parameter yet
|
159
|
+
class DecimalParam(DefaultParam):
|
160
|
+
type: Literal["decimal"] = "decimal"
|
161
|
+
|
162
|
+
def receive(self, value: float | None = None) -> decimal.Decimal: ...
|
163
|
+
|
164
|
+
|
148
165
|
class ChoiceParam(BaseParam):
|
149
166
|
"""Choice parameter."""
|
150
167
|
|
@@ -94,6 +94,7 @@ class Result:
|
|
94
94
|
# NOTE: Check the context has jobs key.
|
95
95
|
if "jobs" not in self.__dict__["context"]:
|
96
96
|
self.__dict__["context"]["jobs"] = {}
|
97
|
+
|
97
98
|
self.__dict__["context"]["jobs"].update(result.context)
|
98
99
|
|
99
100
|
# NOTE: Update running ID from an incoming result.
|