ddeutil-workflow 0.0.50__py3-none-any.whl → 0.0.51__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ddeutil/workflow/__about__.py +1 -1
- ddeutil/workflow/__init__.py +4 -26
- ddeutil/workflow/conf.py +2 -2
- ddeutil/workflow/cron.py +46 -20
- ddeutil/workflow/job.py +166 -93
- ddeutil/workflow/logs.py +22 -18
- ddeutil/workflow/params.py +56 -16
- ddeutil/workflow/reusables.py +4 -2
- ddeutil/workflow/scheduler.py +5 -1
- ddeutil/workflow/stages.py +309 -146
- ddeutil/workflow/workflow.py +76 -72
- {ddeutil_workflow-0.0.50.dist-info → ddeutil_workflow-0.0.51.dist-info}/METADATA +69 -13
- {ddeutil_workflow-0.0.50.dist-info → ddeutil_workflow-0.0.51.dist-info}/RECORD +16 -16
- {ddeutil_workflow-0.0.50.dist-info → ddeutil_workflow-0.0.51.dist-info}/WHEEL +0 -0
- {ddeutil_workflow-0.0.50.dist-info → ddeutil_workflow-0.0.51.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.50.dist-info → ddeutil_workflow-0.0.51.dist-info}/top_level.txt +0 -0
ddeutil/workflow/workflow.py
CHANGED
@@ -6,6 +6,9 @@
|
|
6
6
|
# [x] Use dynamic config
|
7
7
|
"""A Workflow module that is the core module of this package. It keeps Release
|
8
8
|
and Workflow Pydantic models.
|
9
|
+
|
10
|
+
I will implement timeout on the workflow execution layer only because the
|
11
|
+
main propose of this package in Workflow model.
|
9
12
|
"""
|
10
13
|
from __future__ import annotations
|
11
14
|
|
@@ -36,7 +39,7 @@ from .__cron import CronJob, CronRunner
|
|
36
39
|
from .__types import DictData, TupleStr
|
37
40
|
from .conf import Loader, SimLoad, dynamic
|
38
41
|
from .cron import On
|
39
|
-
from .exceptions import JobException, WorkflowException
|
42
|
+
from .exceptions import JobException, UtilException, WorkflowException
|
40
43
|
from .job import Job
|
41
44
|
from .logs import Audit, get_audit
|
42
45
|
from .params import Param
|
@@ -636,20 +639,20 @@ class Workflow(BaseModel):
|
|
636
639
|
run_id: str | None = None,
|
637
640
|
parent_run_id: str | None = None,
|
638
641
|
audit: type[Audit] = None,
|
639
|
-
queue: ReleaseQueue
|
642
|
+
queue: Optional[ReleaseQueue] = None,
|
640
643
|
override_log_name: str | None = None,
|
641
|
-
result: Result
|
644
|
+
result: Optional[Result] = None,
|
645
|
+
timeout: int = 600,
|
642
646
|
) -> Result:
|
643
647
|
"""Release the workflow execution with overriding parameter with the
|
644
648
|
release templating that include logical date (release date), execution
|
645
649
|
date, or running id to the params.
|
646
650
|
|
647
651
|
This method allow workflow use audit object to save the execution
|
648
|
-
result to audit destination like file audit to the local
|
649
|
-
directory.
|
652
|
+
result to audit destination like file audit to the local `./logs` path.
|
650
653
|
|
651
654
|
Steps:
|
652
|
-
- Initialize
|
655
|
+
- Initialize Release and validate ReleaseQueue.
|
653
656
|
- Create release data for pass to parameter templating function.
|
654
657
|
- Execute this workflow with mapping release data to its parameters.
|
655
658
|
- Writing result audit
|
@@ -658,15 +661,15 @@ class Workflow(BaseModel):
|
|
658
661
|
|
659
662
|
:param release: A release datetime or Release object.
|
660
663
|
:param params: A workflow parameter that pass to execute method.
|
661
|
-
:param
|
662
|
-
:param
|
663
|
-
:param parent_run_id: A parent workflow running ID for this release.
|
664
|
+
:param run_id: (str) A workflow running ID.
|
665
|
+
:param parent_run_id: (str) A parent workflow running ID.
|
664
666
|
:param audit: An audit class that want to save the execution result.
|
665
|
-
:param queue: A ReleaseQueue object.
|
666
|
-
:param override_log_name: An override logging name that use
|
667
|
-
the workflow name.
|
667
|
+
:param queue: (ReleaseQueue) A ReleaseQueue object.
|
668
|
+
:param override_log_name: (str) An override logging name that use
|
669
|
+
instead the workflow name.
|
668
670
|
:param result: (Result) A result object for keeping context and status
|
669
671
|
data.
|
672
|
+
:param timeout: (int) A workflow execution time out in second unit.
|
670
673
|
|
671
674
|
:raise TypeError: If a queue parameter does not match with ReleaseQueue
|
672
675
|
type.
|
@@ -683,7 +686,8 @@ class Workflow(BaseModel):
|
|
683
686
|
extras=self.extras,
|
684
687
|
)
|
685
688
|
|
686
|
-
|
689
|
+
# VALIDATE: check type of queue that valid with ReleaseQueue.
|
690
|
+
if queue and not isinstance(queue, ReleaseQueue):
|
687
691
|
raise TypeError(
|
688
692
|
"The queue argument should be ReleaseQueue object only."
|
689
693
|
)
|
@@ -693,36 +697,29 @@ class Workflow(BaseModel):
|
|
693
697
|
release: Release = Release.from_dt(release, extras=self.extras)
|
694
698
|
|
695
699
|
result.trace.debug(
|
696
|
-
f"[RELEASE]: Start
|
697
|
-
f"{release.date:%Y-%m-%d %H:%M:%S}"
|
700
|
+
f"[RELEASE]: Start {name!r} : {release.date:%Y-%m-%d %H:%M:%S}"
|
698
701
|
)
|
699
|
-
|
700
|
-
# NOTE: Release parameters that use to templating on the schedule
|
701
|
-
# config data.
|
702
|
-
release_params: DictData = {
|
703
|
-
"release": {
|
704
|
-
"logical_date": release.date,
|
705
|
-
"execute_date": datetime.now(
|
706
|
-
tz=dynamic("tz", extras=self.extras)
|
707
|
-
),
|
708
|
-
"run_id": result.run_id,
|
709
|
-
"timezone": dynamic("tz", extras=self.extras),
|
710
|
-
}
|
711
|
-
}
|
712
|
-
|
713
|
-
# NOTE: Execute workflow with templating params from release mapping.
|
714
|
-
# The result context that return from execution method is:
|
715
|
-
#
|
716
|
-
# ... {"params": ..., "jobs": ...}
|
717
|
-
#
|
718
702
|
self.execute(
|
719
|
-
params=param2template(
|
703
|
+
params=param2template(
|
704
|
+
params,
|
705
|
+
params={
|
706
|
+
"release": {
|
707
|
+
"logical_date": release.date,
|
708
|
+
"execute_date": datetime.now(
|
709
|
+
tz=dynamic("tz", extras=self.extras)
|
710
|
+
),
|
711
|
+
"run_id": result.run_id,
|
712
|
+
"timezone": dynamic("tz", extras=self.extras),
|
713
|
+
}
|
714
|
+
},
|
715
|
+
extras=self.extras,
|
716
|
+
),
|
720
717
|
result=result,
|
721
718
|
parent_run_id=result.parent_run_id,
|
719
|
+
timeout=timeout,
|
722
720
|
)
|
723
721
|
result.trace.debug(
|
724
|
-
f"[RELEASE]: End
|
725
|
-
f"{release.date:%Y-%m-%d %H:%M:%S}"
|
722
|
+
f"[RELEASE]: End {name!r} : {release.date:%Y-%m-%d %H:%M:%S}"
|
726
723
|
)
|
727
724
|
|
728
725
|
# NOTE: Saving execution result to destination of the input audit
|
@@ -741,19 +738,10 @@ class Workflow(BaseModel):
|
|
741
738
|
).save(excluded=None)
|
742
739
|
)
|
743
740
|
|
744
|
-
|
745
|
-
if queue is not None:
|
741
|
+
if queue:
|
746
742
|
queue.remove_running(release)
|
747
743
|
queue.mark_complete(release)
|
748
744
|
|
749
|
-
# NOTE: Remove the params key from the result context for deduplicate.
|
750
|
-
# This step is prepare result context for this release method.
|
751
|
-
context: DictData = result.context
|
752
|
-
jobs: DictData = context.pop("jobs", {})
|
753
|
-
errors: DictData = (
|
754
|
-
{"errors": context.pop("errors", {})} if "errors" in context else {}
|
755
|
-
)
|
756
|
-
|
757
745
|
return result.catch(
|
758
746
|
status=SUCCESS,
|
759
747
|
context={
|
@@ -763,8 +751,7 @@ class Workflow(BaseModel):
|
|
763
751
|
"logical_date": release.date,
|
764
752
|
"release": release,
|
765
753
|
},
|
766
|
-
"outputs": {"jobs": jobs},
|
767
|
-
**errors,
|
754
|
+
"outputs": {"jobs": result.context.pop("jobs", {})},
|
768
755
|
},
|
769
756
|
)
|
770
757
|
|
@@ -1004,6 +991,12 @@ class Workflow(BaseModel):
|
|
1004
991
|
f"workflow."
|
1005
992
|
)
|
1006
993
|
|
994
|
+
job: Job = self.job(name=job_id)
|
995
|
+
if job.is_skipped(params=params):
|
996
|
+
result.trace.info(f"[WORKFLOW]: Skip job: {job_id!r}")
|
997
|
+
job.set_outputs(output={"skipped": True}, to=params)
|
998
|
+
return result.catch(status=SKIP, context=params)
|
999
|
+
|
1007
1000
|
if event and event.is_set(): # pragma: no cov
|
1008
1001
|
raise WorkflowException(
|
1009
1002
|
"Workflow job was canceled from event that had set before "
|
@@ -1011,27 +1004,31 @@ class Workflow(BaseModel):
|
|
1011
1004
|
)
|
1012
1005
|
|
1013
1006
|
try:
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
run_id=result.run_id,
|
1024
|
-
parent_run_id=result.parent_run_id,
|
1025
|
-
event=event,
|
1026
|
-
).context,
|
1027
|
-
to=params,
|
1028
|
-
)
|
1029
|
-
except JobException as e:
|
1007
|
+
result.trace.info(f"[WORKFLOW]: Execute Job: {job_id!r}")
|
1008
|
+
rs: Result = job.execute(
|
1009
|
+
params=params,
|
1010
|
+
run_id=result.run_id,
|
1011
|
+
parent_run_id=result.parent_run_id,
|
1012
|
+
event=event,
|
1013
|
+
)
|
1014
|
+
job.set_outputs(rs.context, to=params)
|
1015
|
+
except (JobException, UtilException) as e:
|
1030
1016
|
result.trace.error(f"[WORKFLOW]: {e.__class__.__name__}: {e}")
|
1031
1017
|
raise WorkflowException(
|
1032
1018
|
f"Get job execution error {job_id}: JobException: {e}"
|
1033
1019
|
) from None
|
1034
1020
|
|
1021
|
+
if rs.status == FAILED:
|
1022
|
+
error_msg: str = (
|
1023
|
+
f"Workflow job, {job.id}, failed without raise error."
|
1024
|
+
)
|
1025
|
+
return result.catch(
|
1026
|
+
status=FAILED,
|
1027
|
+
context={
|
1028
|
+
"errors": WorkflowException(error_msg).to_dict(),
|
1029
|
+
**params,
|
1030
|
+
},
|
1031
|
+
)
|
1035
1032
|
return result.catch(status=SUCCESS, context=params)
|
1036
1033
|
|
1037
1034
|
def execute(
|
@@ -1083,7 +1080,7 @@ class Workflow(BaseModel):
|
|
1083
1080
|
extras=self.extras,
|
1084
1081
|
)
|
1085
1082
|
|
1086
|
-
result.trace.info(f"[WORKFLOW]:
|
1083
|
+
result.trace.info(f"[WORKFLOW]: Execute: {self.name!r} ...")
|
1087
1084
|
if not self.jobs:
|
1088
1085
|
result.trace.warning(
|
1089
1086
|
f"[WORKFLOW]: {self.name!r} does not have any jobs"
|
@@ -1128,7 +1125,7 @@ class Workflow(BaseModel):
|
|
1128
1125
|
timeout=timeout,
|
1129
1126
|
event=event,
|
1130
1127
|
)
|
1131
|
-
except WorkflowException as e:
|
1128
|
+
except (WorkflowException, JobException) as e:
|
1132
1129
|
status: Status = FAILED
|
1133
1130
|
context.update({"errors": e.to_dict()})
|
1134
1131
|
|
@@ -1167,7 +1164,7 @@ class Workflow(BaseModel):
|
|
1167
1164
|
"max_job_exec_timeout", f=timeout, extras=self.extras
|
1168
1165
|
)
|
1169
1166
|
event: Event = event or Event()
|
1170
|
-
result.trace.debug(f"
|
1167
|
+
result.trace.debug(f"... Run {self.name!r} with threading.")
|
1171
1168
|
with ThreadPoolExecutor(
|
1172
1169
|
max_workers=dynamic("max_job_parallel", extras=self.extras),
|
1173
1170
|
thread_name_prefix="wf_exec_threading_",
|
@@ -1192,7 +1189,7 @@ class Workflow(BaseModel):
|
|
1192
1189
|
)
|
1193
1190
|
elif check == SKIP: # pragma: no cov
|
1194
1191
|
result.trace.info(f"[JOB]: Skip job: {job_id!r}")
|
1195
|
-
job.set_outputs({"
|
1192
|
+
job.set_outputs(output={"skipped": True}, to=context)
|
1196
1193
|
job_queue.task_done()
|
1197
1194
|
continue
|
1198
1195
|
|
@@ -1259,7 +1256,7 @@ class Workflow(BaseModel):
|
|
1259
1256
|
"max_job_exec_timeout", f=timeout, extras=self.extras
|
1260
1257
|
)
|
1261
1258
|
event: Event = event or Event()
|
1262
|
-
result.trace.debug(f"
|
1259
|
+
result.trace.debug(f"... Run {self.name!r} with non-threading.")
|
1263
1260
|
with ThreadPoolExecutor(
|
1264
1261
|
max_workers=1,
|
1265
1262
|
thread_name_prefix="wf_exec_non_threading_",
|
@@ -1284,7 +1281,7 @@ class Workflow(BaseModel):
|
|
1284
1281
|
)
|
1285
1282
|
elif check == SKIP: # pragma: no cov
|
1286
1283
|
result.trace.info(f"[JOB]: Skip job: {job_id!r}")
|
1287
|
-
job.set_outputs({"
|
1284
|
+
job.set_outputs(output={"skipped": True}, to=context)
|
1288
1285
|
job_queue.task_done()
|
1289
1286
|
continue
|
1290
1287
|
|
@@ -1297,7 +1294,7 @@ class Workflow(BaseModel):
|
|
1297
1294
|
event=event,
|
1298
1295
|
)
|
1299
1296
|
time.sleep(0.025)
|
1300
|
-
elif future.done():
|
1297
|
+
elif future.done() or future.cancelled():
|
1301
1298
|
if e := future.exception():
|
1302
1299
|
result.trace.error(f"[WORKFLOW]: {e}")
|
1303
1300
|
raise WorkflowException(str(e))
|
@@ -1317,6 +1314,13 @@ class Workflow(BaseModel):
|
|
1317
1314
|
|
1318
1315
|
if not_timeout_flag:
|
1319
1316
|
job_queue.join()
|
1317
|
+
if future: # pragma: no cov
|
1318
|
+
if e := future.exception():
|
1319
|
+
result.trace.error(f"[WORKFLOW]: {e}")
|
1320
|
+
raise WorkflowException(str(e))
|
1321
|
+
|
1322
|
+
future.result()
|
1323
|
+
|
1320
1324
|
return context
|
1321
1325
|
|
1322
1326
|
result.trace.error(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ddeutil-workflow
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.51
|
4
4
|
Summary: Lightweight workflow orchestration
|
5
5
|
Author-email: ddeutils <korawich.anu@gmail.com>
|
6
6
|
License: MIT
|
@@ -22,8 +22,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
22
22
|
Requires-Python: >=3.9.13
|
23
23
|
Description-Content-Type: text/markdown
|
24
24
|
License-File: LICENSE
|
25
|
-
Requires-Dist: ddeutil[checksum]>=0.4.
|
26
|
-
Requires-Dist: ddeutil-io[toml,yaml]>=0.2.
|
25
|
+
Requires-Dist: ddeutil[checksum]>=0.4.7
|
26
|
+
Requires-Dist: ddeutil-io[toml,yaml]>=0.2.11
|
27
27
|
Requires-Dist: pydantic==2.11.1
|
28
28
|
Requires-Dist: python-dotenv==1.1.0
|
29
29
|
Requires-Dist: schedule<2.0.0,==1.2.2
|
@@ -139,7 +139,8 @@ flowchart LR
|
|
139
139
|
|
140
140
|
## 📦 Installation
|
141
141
|
|
142
|
-
This project need `ddeutil` and `ddeutil-io` extension namespace packages
|
142
|
+
This project need `ddeutil` and `ddeutil-io` extension namespace packages to be
|
143
|
+
the base deps.
|
143
144
|
If you want to install this package with application add-ons, you should add
|
144
145
|
`app` in installation;
|
145
146
|
|
@@ -148,7 +149,7 @@ If you want to install this package with application add-ons, you should add
|
|
148
149
|
| Python | `ddeutil-workflow` | :heavy_check_mark: |
|
149
150
|
| FastAPI Server | `ddeutil-workflow[api]` | :heavy_check_mark: |
|
150
151
|
|
151
|
-
##
|
152
|
+
## 🎯 Usage
|
152
153
|
|
153
154
|
This is examples that use workflow file for running common Data Engineering
|
154
155
|
use-case.
|
@@ -198,12 +199,54 @@ run-py-local:
|
|
198
199
|
|
199
200
|
# Arguments of target data that want to land.
|
200
201
|
writing_mode: flatten
|
201
|
-
|
202
|
+
aws:
|
203
|
+
path: my-data/open-data/${{ params.source-extract }}
|
202
204
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
205
|
+
# This Authentication code should implement with your custom call
|
206
|
+
# function. The template allow you to use environment variable.
|
207
|
+
access_client_id: ${AWS_ACCESS_CLIENT_ID}
|
208
|
+
access_client_secret: ${AWS_ACCESS_CLIENT_SECRET}
|
209
|
+
```
|
210
|
+
|
211
|
+
Before execute this workflow, you should implement caller function first.
|
212
|
+
|
213
|
+
```text
|
214
|
+
registry-caller/
|
215
|
+
╰─ tasks.py
|
216
|
+
```
|
217
|
+
|
218
|
+
This function will store as module that will import from `WORKFLOW_CORE_REGISTRY_CALLER`
|
219
|
+
value (This config can override by extra parameters with `registry_caller` key).
|
220
|
+
|
221
|
+
```python
|
222
|
+
from ddeutil.workflow import Result, tag
|
223
|
+
from ddeutil.workflow.exceptions import StageException
|
224
|
+
from pydantic import BaseModel, SecretStr
|
225
|
+
|
226
|
+
class AwsCredential(BaseModel):
|
227
|
+
path: str
|
228
|
+
access_client_id: str
|
229
|
+
access_client_secret: SecretStr
|
230
|
+
|
231
|
+
class RestAuth(BaseModel):
|
232
|
+
type: str
|
233
|
+
keys: SecretStr
|
234
|
+
|
235
|
+
@tag("requests", alias="get-api-with-oauth-to-s3")
|
236
|
+
def get_api_with_oauth_to_s3(
|
237
|
+
method: str,
|
238
|
+
url: str,
|
239
|
+
body: dict[str, str],
|
240
|
+
auth: RestAuth,
|
241
|
+
writing_node: str,
|
242
|
+
aws: AwsCredential,
|
243
|
+
result: Result,
|
244
|
+
) -> dict[str, int]:
|
245
|
+
result.trace.info("[CALLER]: Start get data via RestAPI to S3.")
|
246
|
+
result.trace.info(f"... {method}: {url}")
|
247
|
+
if method != "post":
|
248
|
+
raise StageException(f"RestAPI does not support for {method} action.")
|
249
|
+
return {"records": 1000}
|
207
250
|
```
|
208
251
|
|
209
252
|
The above workflow template is main executor pipeline that you want to do. If you
|
@@ -298,13 +341,15 @@ only.
|
|
298
341
|
## :rocket: Deployment
|
299
342
|
|
300
343
|
This package able to run as an application service for receive manual trigger
|
301
|
-
from
|
302
|
-
like crontab job but via Python API.
|
344
|
+
from any node via RestAPI or use to be Scheduler background application
|
345
|
+
like crontab job but via Python API or FastAPI app.
|
303
346
|
|
304
347
|
### API Server
|
305
348
|
|
349
|
+
This server use FastAPI package to be the base application.
|
350
|
+
|
306
351
|
```shell
|
307
|
-
(venv) $ uvicorn ddeutil.workflow.api:app \
|
352
|
+
(.venv) $ uvicorn ddeutil.workflow.api:app \
|
308
353
|
--host 127.0.0.1 \
|
309
354
|
--port 80 \
|
310
355
|
--no-access-log
|
@@ -314,8 +359,19 @@ like crontab job but via Python API.
|
|
314
359
|
> If this package already deploy, it is able to use multiprocess;
|
315
360
|
> `uvicorn ddeutil.workflow.api:app --host 127.0.0.1 --port 80 --workers 4`
|
316
361
|
|
362
|
+
### Local Schedule
|
363
|
+
|
364
|
+
> [!WARNING]
|
365
|
+
> This CLI does not implement yet.
|
366
|
+
|
367
|
+
```shell
|
368
|
+
(.venv) $ ddeutil-workflow schedule
|
369
|
+
```
|
370
|
+
|
317
371
|
### Docker Container
|
318
372
|
|
373
|
+
Build a Docker container from this package.
|
374
|
+
|
319
375
|
```shell
|
320
376
|
$ docker build -t ddeutil-workflow:latest -f .container/Dockerfile .
|
321
377
|
$ docker run -i ddeutil-workflow:latest ddeutil-workflow
|
@@ -1,20 +1,20 @@
|
|
1
|
-
ddeutil/workflow/__about__.py,sha256=
|
1
|
+
ddeutil/workflow/__about__.py,sha256=lV_4ewekJpV5o1pQoqnMK3g475fbmyO855YKAFNFKF8,28
|
2
2
|
ddeutil/workflow/__cron.py,sha256=h8rLeIUAAEB2SdZ4Jhch7LU1Yl3bbJ-iNNJ3tQ0eYVM,28095
|
3
|
-
ddeutil/workflow/__init__.py,sha256=
|
3
|
+
ddeutil/workflow/__init__.py,sha256=AMmM7Cq_jrO_MzIZjzQyFvcFkVj9ad7V1f3PtLrI030,1736
|
4
4
|
ddeutil/workflow/__main__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
ddeutil/workflow/__types.py,sha256=8jBdbfb3aZSetjz0mvNrpGHwwxJff7mK8_4v41cLqlc,4316
|
6
|
-
ddeutil/workflow/conf.py,sha256=
|
7
|
-
ddeutil/workflow/cron.py,sha256=
|
6
|
+
ddeutil/workflow/conf.py,sha256=80rgmJKFU7BlH5xTLnghGzGhE8C6LFAQykd9mjHSjo8,12528
|
7
|
+
ddeutil/workflow/cron.py,sha256=WS2MInn0Sp5DKlZDZH5VFZ5AA0Q3_AnBnYEU4lZSv4I,9779
|
8
8
|
ddeutil/workflow/exceptions.py,sha256=r4Jrf9qtVPALU4wh4bnb_OYqC-StqSQJEmFC-_QK934,1408
|
9
|
-
ddeutil/workflow/job.py,sha256
|
10
|
-
ddeutil/workflow/logs.py,sha256=
|
11
|
-
ddeutil/workflow/params.py,sha256=
|
9
|
+
ddeutil/workflow/job.py,sha256=LydncguMUTTdcG_fImjoPFZBulmZT_PD3jYmnmcYskk,35041
|
10
|
+
ddeutil/workflow/logs.py,sha256=rsoBrUGQrooou18fg2yvPsB8NOaXnUA5ThQpBr_WVMg,26598
|
11
|
+
ddeutil/workflow/params.py,sha256=FKY4Oo1Ze4QZKRfAk7rqKsi44YaJQAbqAtXM6vlO2hI,11392
|
12
12
|
ddeutil/workflow/result.py,sha256=27nPQq9CETLCVczv4vvFEF9w2TllHZ_ROfyDoLFxRWM,5647
|
13
|
-
ddeutil/workflow/reusables.py,sha256=
|
14
|
-
ddeutil/workflow/scheduler.py,sha256=
|
15
|
-
ddeutil/workflow/stages.py,sha256=
|
13
|
+
ddeutil/workflow/reusables.py,sha256=iXcS7Gg-71qVX4ln0ILTDx03cTtUnj_rNoXHTVdVrxc,17636
|
14
|
+
ddeutil/workflow/scheduler.py,sha256=4G5AogkmnsTKe7jKYSfU35qjubR82WQ8CLtEe9kqPTE,28304
|
15
|
+
ddeutil/workflow/stages.py,sha256=Ywwky6rJJ5cMvridG-1Y4rv-wJJ_WMbXysViR3WxQrY,69108
|
16
16
|
ddeutil/workflow/utils.py,sha256=zbVttaMFMRLuuBJdSJf7D9qtz8bOnQIBq-rHI3Eqy4M,7821
|
17
|
-
ddeutil/workflow/workflow.py,sha256=
|
17
|
+
ddeutil/workflow/workflow.py,sha256=v_O3Gm4J6SCN_1NfGd3_ClpJkatFCyoqXR3nAIMAoF4,50575
|
18
18
|
ddeutil/workflow/api/__init__.py,sha256=F53NMBWtb9IKaDWkPU5KvybGGfKAcbehgn6TLBwHuuM,21
|
19
19
|
ddeutil/workflow/api/api.py,sha256=CWtPLgOv2Jus9E7nzG5mG2Z32ZEkUK3JWQ2htZyMRpA,5244
|
20
20
|
ddeutil/workflow/api/log.py,sha256=NMTnOnsBrDB5129329xF2myLdrb-z9k1MQrmrP7qXJw,1818
|
@@ -24,8 +24,8 @@ ddeutil/workflow/api/routes/job.py,sha256=oPwBVP0Mxwxv-bGPlfmxQQ9PcVl0ev9HoPzndp
|
|
24
24
|
ddeutil/workflow/api/routes/logs.py,sha256=U6vOni3wd-ZTOwd3yVdSOpgyRmNdcgfngU5KlLM3Cww,5383
|
25
25
|
ddeutil/workflow/api/routes/schedules.py,sha256=EgUjyRGhsm6UNaMj5luh6TcY6l571sCHcla-BL1iOfY,4829
|
26
26
|
ddeutil/workflow/api/routes/workflows.py,sha256=JcDOrn1deK8ztFRcMTNATQejG6KMA7JxZLVc4QeBsP4,4527
|
27
|
-
ddeutil_workflow-0.0.
|
28
|
-
ddeutil_workflow-0.0.
|
29
|
-
ddeutil_workflow-0.0.
|
30
|
-
ddeutil_workflow-0.0.
|
31
|
-
ddeutil_workflow-0.0.
|
27
|
+
ddeutil_workflow-0.0.51.dist-info/licenses/LICENSE,sha256=nGFZ1QEhhhWeMHf9n99_fdt4vQaXS29xWKxt-OcLywk,1085
|
28
|
+
ddeutil_workflow-0.0.51.dist-info/METADATA,sha256=xlAbUVZ9djYf1GImH9v0N-mR7XpxcQIkvwGuX5XmSrs,19425
|
29
|
+
ddeutil_workflow-0.0.51.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
30
|
+
ddeutil_workflow-0.0.51.dist-info/top_level.txt,sha256=m9M6XeSWDwt_yMsmH6gcOjHZVK5O0-vgtNBuncHjzW4,8
|
31
|
+
ddeutil_workflow-0.0.51.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|