ddeutil-workflow 0.0.81__py3-none-any.whl → 0.0.83__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 +2 -1
- ddeutil/workflow/__cron.py +1 -1
- ddeutil/workflow/__init__.py +21 -7
- ddeutil/workflow/__main__.py +280 -1
- ddeutil/workflow/__types.py +10 -1
- ddeutil/workflow/api/routes/job.py +2 -2
- ddeutil/workflow/api/routes/logs.py +8 -61
- ddeutil/workflow/audits.py +101 -49
- ddeutil/workflow/conf.py +45 -25
- ddeutil/workflow/errors.py +12 -0
- ddeutil/workflow/event.py +34 -11
- ddeutil/workflow/job.py +75 -31
- ddeutil/workflow/result.py +73 -22
- ddeutil/workflow/stages.py +625 -375
- ddeutil/workflow/traces.py +71 -27
- ddeutil/workflow/utils.py +41 -24
- ddeutil/workflow/workflow.py +97 -124
- {ddeutil_workflow-0.0.81.dist-info → ddeutil_workflow-0.0.83.dist-info}/METADATA +1 -1
- ddeutil_workflow-0.0.83.dist-info/RECORD +35 -0
- ddeutil/workflow/cli.py +0 -284
- ddeutil_workflow-0.0.81.dist-info/RECORD +0 -36
- {ddeutil_workflow-0.0.81.dist-info → ddeutil_workflow-0.0.83.dist-info}/WHEEL +0 -0
- {ddeutil_workflow-0.0.81.dist-info → ddeutil_workflow-0.0.83.dist-info}/entry_points.txt +0 -0
- {ddeutil_workflow-0.0.81.dist-info → ddeutil_workflow-0.0.83.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.81.dist-info → ddeutil_workflow-0.0.83.dist-info}/top_level.txt +0 -0
ddeutil/workflow/workflow.py
CHANGED
@@ -30,19 +30,19 @@ from concurrent.futures import (
|
|
30
30
|
as_completed,
|
31
31
|
)
|
32
32
|
from datetime import datetime
|
33
|
-
from enum import Enum
|
34
33
|
from pathlib import Path
|
35
34
|
from queue import Queue
|
36
35
|
from textwrap import dedent
|
37
36
|
from threading import Event as ThreadEvent
|
38
|
-
from typing import Any, Optional, Union
|
37
|
+
from typing import Any, Literal, Optional, Union
|
39
38
|
|
40
39
|
from pydantic import BaseModel, Field
|
40
|
+
from pydantic.functional_serializers import field_serializer
|
41
41
|
from pydantic.functional_validators import field_validator, model_validator
|
42
42
|
from typing_extensions import Self
|
43
43
|
|
44
44
|
from .__types import DictData
|
45
|
-
from .audits import Audit, get_audit
|
45
|
+
from .audits import NORMAL, RERUN, Audit, ReleaseType, get_audit
|
46
46
|
from .conf import YamlParser, dynamic
|
47
47
|
from .errors import WorkflowCancelError, WorkflowError, WorkflowTimeoutError
|
48
48
|
from .event import Event
|
@@ -61,40 +61,15 @@ from .result import (
|
|
61
61
|
validate_statuses,
|
62
62
|
)
|
63
63
|
from .reusables import has_template, param2template
|
64
|
-
from .traces import
|
64
|
+
from .traces import Trace, get_trace
|
65
65
|
from .utils import (
|
66
|
-
|
66
|
+
extract_id,
|
67
67
|
gen_id,
|
68
68
|
get_dt_now,
|
69
|
-
|
69
|
+
remove_sys_extras,
|
70
70
|
)
|
71
71
|
|
72
72
|
|
73
|
-
class ReleaseType(str, Enum):
|
74
|
-
"""Release type enumeration for workflow execution modes.
|
75
|
-
|
76
|
-
This enum defines the different types of workflow releases that can be
|
77
|
-
triggered, each with specific behavior and use cases.
|
78
|
-
|
79
|
-
Attributes:
|
80
|
-
NORMAL: Standard workflow release execution
|
81
|
-
RERUN: Re-execution of previously failed workflow
|
82
|
-
EVENT: Event-triggered workflow execution
|
83
|
-
FORCE: Forced execution bypassing normal conditions
|
84
|
-
"""
|
85
|
-
|
86
|
-
NORMAL = "normal"
|
87
|
-
RERUN = "rerun"
|
88
|
-
EVENT = "event"
|
89
|
-
FORCE = "force"
|
90
|
-
|
91
|
-
|
92
|
-
NORMAL = ReleaseType.NORMAL
|
93
|
-
RERUN = ReleaseType.RERUN
|
94
|
-
EVENT = ReleaseType.EVENT
|
95
|
-
FORCE = ReleaseType.FORCE
|
96
|
-
|
97
|
-
|
98
73
|
class Workflow(BaseModel):
|
99
74
|
"""Main workflow orchestration model for job and schedule management.
|
100
75
|
|
@@ -113,17 +88,6 @@ class Workflow(BaseModel):
|
|
113
88
|
on (list[Crontab]): Schedule definitions using cron expressions
|
114
89
|
jobs (dict[str, Job]): Collection of jobs within this workflow
|
115
90
|
|
116
|
-
Example:
|
117
|
-
Create and execute a workflow:
|
118
|
-
|
119
|
-
```python
|
120
|
-
workflow = Workflow.from_conf('my-workflow')
|
121
|
-
result = workflow.execute({
|
122
|
-
'param1': 'value1',
|
123
|
-
'param2': 'value2'
|
124
|
-
})
|
125
|
-
```
|
126
|
-
|
127
91
|
Note:
|
128
92
|
Workflows can be executed immediately or scheduled for background
|
129
93
|
execution using the cron-like scheduling system.
|
@@ -134,6 +98,7 @@ class Workflow(BaseModel):
|
|
134
98
|
description="An extra parameters that want to override config values.",
|
135
99
|
)
|
136
100
|
name: str = Field(description="A workflow name.")
|
101
|
+
type: Literal["Workflow"] = Field(default="workflow")
|
137
102
|
desc: Optional[str] = Field(
|
138
103
|
default=None,
|
139
104
|
description=(
|
@@ -198,10 +163,10 @@ class Workflow(BaseModel):
|
|
198
163
|
FileNotFoundError: If workflow configuration file not found
|
199
164
|
|
200
165
|
Example:
|
201
|
-
>>> # Load from default config path
|
166
|
+
>>> # NOTE: Load from default config path
|
202
167
|
>>> workflow = Workflow.from_conf('data-pipeline')
|
203
168
|
|
204
|
-
>>> # Load with custom path and extras
|
169
|
+
>>> # NOTE: Load with custom path and extras
|
205
170
|
>>> workflow = Workflow.from_conf(
|
206
171
|
... 'data-pipeline',
|
207
172
|
... path=Path('./custom-configs'),
|
@@ -211,7 +176,6 @@ class Workflow(BaseModel):
|
|
211
176
|
load: YamlParser = YamlParser(name, path=path, extras=extras, obj=cls)
|
212
177
|
data: DictData = copy.deepcopy(load.data)
|
213
178
|
data["name"] = name
|
214
|
-
|
215
179
|
if extras:
|
216
180
|
data["extras"] = extras
|
217
181
|
|
@@ -280,17 +244,29 @@ class Workflow(BaseModel):
|
|
280
244
|
f"{self.name!r}."
|
281
245
|
)
|
282
246
|
|
247
|
+
# NOTE: Force update internal extras for handler circle execution.
|
248
|
+
self.extras.update({"__sys_break_circle_exec": self.name})
|
249
|
+
|
283
250
|
return self
|
284
251
|
|
252
|
+
@field_serializer("extras")
|
253
|
+
def __serialize_extras(self, extras: DictData) -> DictData:
|
254
|
+
return remove_sys_extras(extras)
|
255
|
+
|
285
256
|
def detail(self) -> DictData: # pragma: no cov
|
286
257
|
"""Return the detail of this workflow for generate markdown."""
|
287
258
|
return self.model_dump(by_alias=True)
|
288
259
|
|
289
260
|
def md(self, author: Optional[str] = None) -> str: # pragma: no cov
|
290
|
-
"""Generate the markdown template.
|
261
|
+
"""Generate the markdown template from this Workflow model data.
|
262
|
+
|
263
|
+
Args:
|
264
|
+
author (str | None, default None): An author name.
|
265
|
+
"""
|
291
266
|
|
292
267
|
def align_newline(value: str) -> str:
|
293
|
-
|
268
|
+
space: str = " " * 16
|
269
|
+
return value.rstrip("\n").replace("\n", f"\n{space}")
|
294
270
|
|
295
271
|
info: str = (
|
296
272
|
f"| Author: {author or 'nobody'} "
|
@@ -317,8 +293,7 @@ class Workflow(BaseModel):
|
|
317
293
|
{align_newline(self.desc)}\n
|
318
294
|
## Parameters\n
|
319
295
|
| name | type | default | description |
|
320
|
-
| --- | --- | --- | : --- :
|
321
|
-
|
296
|
+
| --- | --- | --- | : --- : |\n\n
|
322
297
|
## Jobs\n
|
323
298
|
{align_newline(jobs)}
|
324
299
|
""".lstrip(
|
@@ -347,8 +322,7 @@ class Workflow(BaseModel):
|
|
347
322
|
f"{self.name!r}"
|
348
323
|
)
|
349
324
|
job: Job = self.jobs[name]
|
350
|
-
|
351
|
-
job.extras = self.extras
|
325
|
+
job.extras = self.extras
|
352
326
|
return job
|
353
327
|
|
354
328
|
def parameterize(self, params: DictData) -> DictData:
|
@@ -367,8 +341,8 @@ class Workflow(BaseModel):
|
|
367
341
|
execute method.
|
368
342
|
|
369
343
|
Returns:
|
370
|
-
DictData: The parameter value that validate with its parameter fields
|
371
|
-
adding jobs key to this parameter.
|
344
|
+
DictData: The parameter value that validate with its parameter fields
|
345
|
+
and adding jobs key to this parameter.
|
372
346
|
|
373
347
|
Raises:
|
374
348
|
WorkflowError: If parameter value that want to validate does
|
@@ -399,33 +373,6 @@ class Workflow(BaseModel):
|
|
399
373
|
"jobs": {},
|
400
374
|
}
|
401
375
|
|
402
|
-
def validate_release(self, dt: datetime) -> datetime:
|
403
|
-
"""Validate the release datetime that should was replaced second and
|
404
|
-
millisecond to 0 and replaced timezone to None before checking it match
|
405
|
-
with the set `on` field.
|
406
|
-
|
407
|
-
Args:
|
408
|
-
dt (datetime): A datetime object that want to validate.
|
409
|
-
|
410
|
-
Returns:
|
411
|
-
datetime: The validated release datetime.
|
412
|
-
"""
|
413
|
-
if dt.tzinfo is None:
|
414
|
-
dt = dt.replace(tzinfo=UTC)
|
415
|
-
|
416
|
-
release: datetime = replace_sec(dt.astimezone(UTC))
|
417
|
-
|
418
|
-
# NOTE: Return itself if schedule event does not set.
|
419
|
-
if not self.on.schedule:
|
420
|
-
return release
|
421
|
-
|
422
|
-
for on in self.on.schedule:
|
423
|
-
if release == on.cronjob.schedule(release, tz=UTC).next:
|
424
|
-
return release
|
425
|
-
raise WorkflowError(
|
426
|
-
"Release datetime does not support for this workflow"
|
427
|
-
)
|
428
|
-
|
429
376
|
def release(
|
430
377
|
self,
|
431
378
|
release: datetime,
|
@@ -437,7 +384,7 @@ class Workflow(BaseModel):
|
|
437
384
|
override_log_name: Optional[str] = None,
|
438
385
|
timeout: int = 600,
|
439
386
|
audit_excluded: Optional[list[str]] = None,
|
440
|
-
audit:
|
387
|
+
audit: Audit = None,
|
441
388
|
) -> Result:
|
442
389
|
"""Release the workflow which is executes workflow with writing audit
|
443
390
|
log tracking. The method is overriding parameter with the release
|
@@ -455,11 +402,12 @@ class Workflow(BaseModel):
|
|
455
402
|
|
456
403
|
Args:
|
457
404
|
release (datetime): A release datetime.
|
458
|
-
params: A workflow parameter that pass to execute method.
|
459
|
-
release_type:
|
405
|
+
params (DictData): A workflow parameter that pass to execute method.
|
406
|
+
release_type (ReleaseType): A release type that want to execute.
|
460
407
|
run_id: (str) A workflow running ID.
|
461
408
|
runs_metadata: (DictData)
|
462
|
-
audit: An audit
|
409
|
+
audit (Audit): An audit model that use to manage release log of this
|
410
|
+
execution.
|
463
411
|
override_log_name: (str) An override logging name that use
|
464
412
|
instead the workflow name.
|
465
413
|
timeout: (int) A workflow execution time out in second unit.
|
@@ -471,20 +419,25 @@ class Workflow(BaseModel):
|
|
471
419
|
method.
|
472
420
|
"""
|
473
421
|
name: str = override_log_name or self.name
|
422
|
+
audit: Audit = audit or get_audit(extras=self.extras)
|
474
423
|
|
475
424
|
# NOTE: Generate the parent running ID with not None value.
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
else:
|
480
|
-
run_id: str = gen_id(name, unique=True)
|
481
|
-
parent_run_id: str = run_id
|
482
|
-
|
425
|
+
parent_run_id, run_id = extract_id(
|
426
|
+
name, run_id=run_id, extras=self.extras
|
427
|
+
)
|
483
428
|
context: DictData = {"status": WAIT}
|
484
|
-
|
429
|
+
audit_data: DictData = {
|
430
|
+
"name": name,
|
431
|
+
"release": release,
|
432
|
+
"type": release_type,
|
433
|
+
"run_id": run_id,
|
434
|
+
"parent_run_id": parent_run_id,
|
435
|
+
"extras": self.extras,
|
436
|
+
}
|
437
|
+
trace: Trace = get_trace(
|
485
438
|
run_id, parent_run_id=parent_run_id, extras=self.extras
|
486
439
|
)
|
487
|
-
release: datetime = self.
|
440
|
+
release: datetime = self.on.validate_dt(dt=release)
|
488
441
|
trace.info(f"[RELEASE]: Start {name!r} : {release:%Y-%m-%d %H:%M:%S}")
|
489
442
|
values: DictData = param2template(
|
490
443
|
params,
|
@@ -498,6 +451,25 @@ class Workflow(BaseModel):
|
|
498
451
|
},
|
499
452
|
extras=self.extras,
|
500
453
|
)
|
454
|
+
|
455
|
+
if release_type == NORMAL and audit.is_pointed(data=audit_data):
|
456
|
+
trace.info("[RELEASE]: Skip this release because it already audit.")
|
457
|
+
return Result(
|
458
|
+
run_id=run_id,
|
459
|
+
parent_run_id=parent_run_id,
|
460
|
+
status=SKIP,
|
461
|
+
context=catch(context, status=SKIP),
|
462
|
+
extras=self.extras,
|
463
|
+
)
|
464
|
+
|
465
|
+
if release_type == RERUN:
|
466
|
+
# TODO: It will load previous audit and use this data to run with
|
467
|
+
# the `rerun` method.
|
468
|
+
raise NotImplementedError(
|
469
|
+
"Release does not support for rerun type yet. Please use the "
|
470
|
+
"`rerun` method instead."
|
471
|
+
)
|
472
|
+
|
501
473
|
rs: Result = self.execute(
|
502
474
|
params=values,
|
503
475
|
run_id=parent_run_id,
|
@@ -507,15 +479,10 @@ class Workflow(BaseModel):
|
|
507
479
|
trace.info(f"[RELEASE]: End {name!r} : {release:%Y-%m-%d %H:%M:%S}")
|
508
480
|
trace.debug(f"[RELEASE]: Writing audit: {name!r}.")
|
509
481
|
(
|
510
|
-
|
511
|
-
data=
|
512
|
-
|
513
|
-
"release": release,
|
514
|
-
"type": release_type,
|
482
|
+
audit.save(
|
483
|
+
data=audit_data
|
484
|
+
| {
|
515
485
|
"context": context,
|
516
|
-
"parent_run_id": parent_run_id,
|
517
|
-
"run_id": run_id,
|
518
|
-
"extras": self.extras,
|
519
486
|
"runs_metadata": (
|
520
487
|
(runs_metadata or {})
|
521
488
|
| rs.info
|
@@ -546,7 +513,7 @@ class Workflow(BaseModel):
|
|
546
513
|
**(context["errors"] if "errors" in context else {}),
|
547
514
|
},
|
548
515
|
),
|
549
|
-
extras=self.extras,
|
516
|
+
extras=remove_sys_extras(self.extras),
|
550
517
|
)
|
551
518
|
|
552
519
|
def execute_job(
|
@@ -579,7 +546,7 @@ class Workflow(BaseModel):
|
|
579
546
|
Returns:
|
580
547
|
tuple[Status, DictData]: The pair of status and result context data.
|
581
548
|
"""
|
582
|
-
trace:
|
549
|
+
trace: Trace = get_trace(
|
583
550
|
run_id, parent_run_id=parent_run_id, extras=self.extras
|
584
551
|
)
|
585
552
|
if event and event.is_set():
|
@@ -694,9 +661,10 @@ class Workflow(BaseModel):
|
|
694
661
|
:rtype: Result
|
695
662
|
"""
|
696
663
|
ts: float = time.monotonic()
|
697
|
-
parent_run_id
|
698
|
-
|
699
|
-
|
664
|
+
parent_run_id, run_id = extract_id(
|
665
|
+
self.name, run_id=run_id, extras=self.extras
|
666
|
+
)
|
667
|
+
trace: Trace = get_trace(
|
700
668
|
run_id, parent_run_id=parent_run_id, extras=self.extras
|
701
669
|
)
|
702
670
|
context: DictData = self.parameterize(params)
|
@@ -733,6 +701,11 @@ class Workflow(BaseModel):
|
|
733
701
|
)
|
734
702
|
catch(context, status=WAIT)
|
735
703
|
if event and event.is_set():
|
704
|
+
err_msg: str = (
|
705
|
+
"Execution was canceled from the event was set "
|
706
|
+
"before workflow execution."
|
707
|
+
)
|
708
|
+
trace.error(f"[WORKFLOW]: {err_msg}")
|
736
709
|
return Result(
|
737
710
|
run_id=run_id,
|
738
711
|
parent_run_id=parent_run_id,
|
@@ -740,12 +713,7 @@ class Workflow(BaseModel):
|
|
740
713
|
context=catch(
|
741
714
|
context,
|
742
715
|
status=CANCEL,
|
743
|
-
updated={
|
744
|
-
"errors": WorkflowCancelError(
|
745
|
-
"Execution was canceled from the event was set "
|
746
|
-
"before workflow execution."
|
747
|
-
).to_dict(),
|
748
|
-
},
|
716
|
+
updated={"errors": WorkflowCancelError(err_msg).to_dict()},
|
749
717
|
),
|
750
718
|
info={"execution_time": time.monotonic() - ts},
|
751
719
|
extras=self.extras,
|
@@ -799,7 +767,7 @@ class Workflow(BaseModel):
|
|
799
767
|
)
|
800
768
|
elif check == SKIP: # pragma: no cov
|
801
769
|
trace.info(
|
802
|
-
f"[JOB]: Skip job: {job_id!r} from trigger rule."
|
770
|
+
f"[JOB]: ⏭️ Skip job: {job_id!r} from trigger rule."
|
803
771
|
)
|
804
772
|
job.set_outputs(output={"status": SKIP}, to=context)
|
805
773
|
job_queue.task_done()
|
@@ -923,16 +891,21 @@ class Workflow(BaseModel):
|
|
923
891
|
) -> Result: # pragma: no cov
|
924
892
|
"""Re-Execute workflow with passing the error context data.
|
925
893
|
|
926
|
-
:
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
:
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
execution
|
894
|
+
Warnings:
|
895
|
+
This rerun method allow to rerun job execution level only. That mean
|
896
|
+
it does not support rerun only stage.
|
897
|
+
|
898
|
+
Args:
|
899
|
+
context: A context result that get the failed status.
|
900
|
+
run_id: (Optional[str]) A workflow running ID.
|
901
|
+
event: (Event) An Event manager instance that use to cancel this
|
902
|
+
execution if it forces stopped by parent execution.
|
903
|
+
timeout: (float) A workflow execution time out in second unit
|
904
|
+
that use for limit time of execution and waiting job dependency.
|
905
|
+
This value does not force stop the task that still running more
|
906
|
+
than this limit time. (Default: 60 * 60 seconds)
|
907
|
+
max_job_parallel: (int) The maximum workers that use for job
|
908
|
+
execution in `ThreadPoolExecutor` object. (Default: 2 workers)
|
936
909
|
|
937
910
|
Returns
|
938
911
|
Result: Return Result object that create from execution context with
|
@@ -941,7 +914,7 @@ class Workflow(BaseModel):
|
|
941
914
|
ts: float = time.monotonic()
|
942
915
|
parent_run_id: str = run_id
|
943
916
|
run_id: str = gen_id(self.name, extras=self.extras)
|
944
|
-
trace:
|
917
|
+
trace: Trace = get_trace(
|
945
918
|
run_id, parent_run_id=parent_run_id, extras=self.extras
|
946
919
|
)
|
947
920
|
if context["status"] == SUCCESS:
|
@@ -0,0 +1,35 @@
|
|
1
|
+
ddeutil/workflow/__about__.py,sha256=6n_dCde_BwTTJlP4Yu4HNgiRti7QydfShki703lt6Ro,60
|
2
|
+
ddeutil/workflow/__cron.py,sha256=-1tqZG7GtUmusdl6NTy_Ck7nM_tGYTXYB7TB7tKeO60,29184
|
3
|
+
ddeutil/workflow/__init__.py,sha256=Dvfjs7LpLerGCYGnbqKwznViTw7ire_6LR8obC1I4aM,3456
|
4
|
+
ddeutil/workflow/__main__.py,sha256=Nqk5aO-HsZVKV2BmuJYeJEufJluipvCD9R1k2kMoJ3Y,8581
|
5
|
+
ddeutil/workflow/__types.py,sha256=IOKuJCxTUPHh8Z2JoLu_K7a85oq0VOcKBhpabiJ6qEE,5001
|
6
|
+
ddeutil/workflow/audits.py,sha256=H8yuMzXs_QAAKNox-HXdojk9CcilHYYQtklJYetoZv8,26955
|
7
|
+
ddeutil/workflow/conf.py,sha256=VfPmwaBYEgOj8bu4eim13ayZwJ4Liy7I702aQf7vS8g,17644
|
8
|
+
ddeutil/workflow/errors.py,sha256=J4bEbtI7qtBX7eghod4djLf0y5i1r4mCz_uFU4roLhY,5713
|
9
|
+
ddeutil/workflow/event.py,sha256=OumcZBlOZD0_J53GS4V2XJEqQ9HEcIl3UicQrCyL46M,14684
|
10
|
+
ddeutil/workflow/job.py,sha256=VVTpxVR2iVEkjvP8r0O0LRtAPnrbsguYbKzHpe2TAVo,48146
|
11
|
+
ddeutil/workflow/params.py,sha256=y9f6DEIyae1j4awbj3Kbeq75-U2UPFlKv9K57Hdo_Go,17188
|
12
|
+
ddeutil/workflow/result.py,sha256=0W3z5wAs3Dyr8r2vRMY5hl1MkvdsyXWJmQD4NmsDDOM,10194
|
13
|
+
ddeutil/workflow/reusables.py,sha256=SBLJSxR8ELoWJErBfSMZS3Rr1O_93T-fFBpfn2AvxuA,25007
|
14
|
+
ddeutil/workflow/stages.py,sha256=lWlzvpJ6YyhDf0ks5q_fzHjm4-o6UZfhiYp9CG-ffro,129661
|
15
|
+
ddeutil/workflow/traces.py,sha256=pq1lOg2UMgDiSDmjHxXPoTaBHnfc7uzzlo1u2TCwN2Q,74733
|
16
|
+
ddeutil/workflow/utils.py,sha256=XsH8DkcTiMmWt1e59b4bFQofsBdo7uW1-7gC2rghuW8,12128
|
17
|
+
ddeutil/workflow/workflow.py,sha256=uc71PJh7e-Bjb3Xg7T83wlLrKTPGvmX7Qjsn6SJ1GDI,42544
|
18
|
+
ddeutil/workflow/api/__init__.py,sha256=5DzYL3ngceoRshh5HYCSVWChqNJSiP01E1bEd8XxPi0,4799
|
19
|
+
ddeutil/workflow/api/log_conf.py,sha256=WfS3udDLSyrP-C80lWOvxxmhd_XWKvQPkwDqKblcH3E,1834
|
20
|
+
ddeutil/workflow/api/routes/__init__.py,sha256=JRaJZB0D6mgR17MbZo8yLtdYDtD62AA8MdKlFqhG84M,420
|
21
|
+
ddeutil/workflow/api/routes/job.py,sha256=-lbZ_hS9pEdSy6zeke5qrXEgdNxtQ2w9in7cHuM2Jzs,2536
|
22
|
+
ddeutil/workflow/api/routes/logs.py,sha256=9jiYsw8kepud4n3NyXB7SAr2OoQwRn5uNb9kIZ58XJM,3806
|
23
|
+
ddeutil/workflow/api/routes/workflows.py,sha256=0pEZEsIrscRFBXG9gf6nttKw0aNbcdw7NsAZKLoKWtk,4392
|
24
|
+
ddeutil/workflow/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
+
ddeutil/workflow/plugins/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
|
+
ddeutil/workflow/plugins/providers/aws.py,sha256=61uIFBEWt-_D5Sui24qUPier1Hiqlw_RP_eY-rXBCKc,31551
|
27
|
+
ddeutil/workflow/plugins/providers/az.py,sha256=o3dh011lEtmr7-d7FPZJPgXdT0ytFzKfc5xnVxSyXGU,34867
|
28
|
+
ddeutil/workflow/plugins/providers/container.py,sha256=DSN0RWxMjTJN5ANheeMauDaPa3X6Z2E1eGUcctYkENw,22134
|
29
|
+
ddeutil/workflow/plugins/providers/gcs.py,sha256=KgAOdMBvdbMLTH_z_FwVriBFtZfKEYx8_34jzUOVjTY,27460
|
30
|
+
ddeutil_workflow-0.0.83.dist-info/licenses/LICENSE,sha256=nGFZ1QEhhhWeMHf9n99_fdt4vQaXS29xWKxt-OcLywk,1085
|
31
|
+
ddeutil_workflow-0.0.83.dist-info/METADATA,sha256=pxD6FyTSV4ra5DujoPvWQnb2Z9WWHHqi97HBADqeeAo,16087
|
32
|
+
ddeutil_workflow-0.0.83.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
33
|
+
ddeutil_workflow-0.0.83.dist-info/entry_points.txt,sha256=qDTpPSauL0ciO6T4iSVt8bJeYrVEkkoEEw_RlGx6Kgk,63
|
34
|
+
ddeutil_workflow-0.0.83.dist-info/top_level.txt,sha256=m9M6XeSWDwt_yMsmH6gcOjHZVK5O0-vgtNBuncHjzW4,8
|
35
|
+
ddeutil_workflow-0.0.83.dist-info/RECORD,,
|