ddeutil-workflow 0.0.22__py3-none-any.whl → 0.0.24__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.
@@ -33,7 +33,7 @@ from functools import total_ordering
33
33
  from heapq import heappop, heappush
34
34
  from queue import Queue
35
35
  from textwrap import dedent
36
- from typing import Optional
36
+ from typing import Any, Optional
37
37
 
38
38
  from pydantic import BaseModel, ConfigDict, Field
39
39
  from pydantic.dataclasses import dataclass
@@ -43,16 +43,15 @@ from typing_extensions import Self
43
43
  from .__cron import CronJob, CronRunner
44
44
  from .__types import DictData, TupleStr
45
45
  from .conf import FileLog, Loader, Log, config, get_logger
46
+ from .cron import On
46
47
  from .exceptions import JobException, WorkflowException
47
48
  from .job import Job
48
- from .on import On
49
+ from .params import Param
50
+ from .result import Result
49
51
  from .utils import (
50
- Param,
51
- Result,
52
52
  cut_id,
53
53
  delay,
54
54
  gen_id,
55
- get_diff_sec,
56
55
  get_dt_now,
57
56
  has_template,
58
57
  param2template,
@@ -64,7 +63,7 @@ __all__: TupleStr = (
64
63
  "Workflow",
65
64
  "WorkflowRelease",
66
65
  "WorkflowQueue",
67
- "WorkflowTaskData",
66
+ "WorkflowTask",
68
67
  )
69
68
 
70
69
 
@@ -86,13 +85,16 @@ class WorkflowRelease:
86
85
  return f"{self.date:%Y-%m-%d %H:%M:%S}"
87
86
 
88
87
  @classmethod
89
- def from_dt(cls, dt: datetime) -> Self:
88
+ def from_dt(cls, dt: datetime | str) -> Self:
90
89
  """Construct WorkflowRelease via datetime object only.
91
90
 
92
91
  :param dt: A datetime object.
93
92
 
94
93
  :rtype: Self
95
94
  """
95
+ if isinstance(dt, str):
96
+ dt: datetime = datetime.fromisoformat(dt)
97
+
96
98
  return cls(
97
99
  date=dt,
98
100
  offset=0,
@@ -132,7 +134,7 @@ class WorkflowQueue:
132
134
 
133
135
  @classmethod
134
136
  def from_list(
135
- cls, queue: list[datetime] | list[WorkflowRelease] | None
137
+ cls, queue: list[datetime] | list[WorkflowRelease] | None = None
136
138
  ) -> Self:
137
139
  """Construct WorkflowQueue object from an input queue value that passing
138
140
  with list of datetime or list of WorkflowRelease.
@@ -143,12 +145,13 @@ class WorkflowQueue:
143
145
  """
144
146
  if queue is None:
145
147
  return cls()
146
- elif isinstance(queue, list):
148
+
149
+ if isinstance(queue, list):
147
150
 
148
151
  if all(isinstance(q, datetime) for q in queue):
149
152
  return cls(queue=[WorkflowRelease.from_dt(q) for q in queue])
150
153
 
151
- elif all(isinstance(q, WorkflowRelease) for q in queue):
154
+ if all(isinstance(q, WorkflowRelease) for q in queue):
152
155
  return cls(queue=queue)
153
156
 
154
157
  raise TypeError(
@@ -164,7 +167,23 @@ class WorkflowQueue:
164
167
  """
165
168
  return len(self.queue) > 0
166
169
 
167
- def check_queue(self, value: WorkflowRelease) -> bool:
170
+ @property
171
+ def first_queue(self) -> WorkflowRelease:
172
+ """Check an input WorkflowRelease object is the first value of the
173
+ waiting queue.
174
+
175
+ :rtype: bool
176
+ """
177
+ # NOTE: Old logic to peeking the first release from waiting queue.
178
+ #
179
+ # first_value: WorkflowRelease = heappop(self.queue)
180
+ # heappush(self.queue, first_value)
181
+ #
182
+ # return first_value
183
+ #
184
+ return self.queue[0]
185
+
186
+ def check_queue(self, value: WorkflowRelease | datetime) -> bool:
168
187
  """Check a WorkflowRelease value already exists in list of tracking
169
188
  queues.
170
189
 
@@ -173,6 +192,9 @@ class WorkflowQueue:
173
192
 
174
193
  :rtype: bool
175
194
  """
195
+ if isinstance(value, datetime):
196
+ value = WorkflowRelease.from_dt(value)
197
+
176
198
  return (
177
199
  (value in self.queue)
178
200
  or (value in self.running)
@@ -180,20 +202,37 @@ class WorkflowQueue:
180
202
  )
181
203
 
182
204
  def push_queue(self, value: WorkflowRelease) -> Self:
183
- """Push data to the queue."""
205
+ """Push data to the waiting queue."""
184
206
  heappush(self.queue, value)
185
207
  return self
186
208
 
187
209
  def push_running(self, value: WorkflowRelease) -> Self:
188
- """Push data to the running."""
210
+ """Push WorkflowRelease to the running queue."""
189
211
  heappush(self.running, value)
190
212
  return self
191
213
 
192
214
  def remove_running(self, value: WorkflowRelease) -> Self:
193
- """Remove data on the running if it exists."""
215
+ """Remove WorkflowRelease in the running queue if it exists."""
194
216
  if value in self.running:
195
217
  self.running.remove(value)
196
218
 
219
+ def push_complete(self, value: WorkflowRelease) -> Self:
220
+ """Push WorkflowRelease to the complete queue."""
221
+ heappush(self.complete, value)
222
+
223
+ # NOTE: Remove complete queue on workflow that keep more than the
224
+ # maximum config.
225
+ num_complete_delete: int = (
226
+ len(self.complete) - config.max_queue_complete_hist
227
+ )
228
+
229
+ if num_complete_delete > 0:
230
+ print(num_complete_delete)
231
+ for _ in range(num_complete_delete):
232
+ heappop(self.complete)
233
+
234
+ return self
235
+
197
236
 
198
237
  class Workflow(BaseModel):
199
238
  """Workflow Pydantic model.
@@ -444,6 +483,7 @@ class Workflow(BaseModel):
444
483
  queue: (
445
484
  WorkflowQueue | list[datetime] | list[WorkflowRelease] | None
446
485
  ) = None,
486
+ override_log_name: str | None = None,
447
487
  ) -> Result:
448
488
  """Release the workflow execution with overriding parameter with the
449
489
  release templating that include logical date (release date), execution
@@ -458,11 +498,14 @@ class Workflow(BaseModel):
458
498
  :param run_id: A workflow running ID for this release.
459
499
  :param log: A log class that want to save the execution result.
460
500
  :param queue: A WorkflowQueue object.
501
+ :param override_log_name: An override logging name that use instead
502
+ the workflow name.
461
503
 
462
504
  :rtype: Result
463
505
  """
464
506
  log: type[Log] = log or FileLog
465
- run_id: str = run_id or gen_id(self.name, unique=True)
507
+ name: str = override_log_name or self.name
508
+ run_id: str = run_id or gen_id(name, unique=True)
466
509
  rs_release: Result = Result(run_id=run_id)
467
510
 
468
511
  # VALIDATE: Change queue value to WorkflowQueue object.
@@ -474,7 +517,7 @@ class Workflow(BaseModel):
474
517
  release: WorkflowRelease = WorkflowRelease.from_dt(release)
475
518
 
476
519
  logger.debug(
477
- f"({cut_id(run_id)}) [RELEASE]: {self.name!r} : Start release - "
520
+ f"({cut_id(run_id)}) [RELEASE]: Start release - {name!r} : "
478
521
  f"{release.date:%Y-%m-%d %H:%M:%S}"
479
522
  )
480
523
 
@@ -495,14 +538,14 @@ class Workflow(BaseModel):
495
538
  run_id=run_id,
496
539
  )
497
540
  logger.debug(
498
- f"({cut_id(run_id)}) [RELEASE]: {self.name!r} : End release - "
541
+ f"({cut_id(run_id)}) [RELEASE]: End release - {name!r} : "
499
542
  f"{release.date:%Y-%m-%d %H:%M:%S}"
500
543
  )
501
544
 
502
545
  rs.set_parent_run_id(run_id)
503
546
  rs_log: Log = log.model_validate(
504
547
  {
505
- "name": self.name,
548
+ "name": name,
506
549
  "release": release.date,
507
550
  "type": release.type,
508
551
  "context": rs.context,
@@ -516,18 +559,21 @@ class Workflow(BaseModel):
516
559
 
517
560
  # NOTE: Remove this release from running.
518
561
  queue.remove_running(release)
519
- heappush(queue.complete, release)
562
+ queue.push_complete(release)
563
+
564
+ context: dict[str, Any] = rs.context
565
+ context.pop("params")
520
566
 
521
567
  return rs_release.catch(
522
568
  status=0,
523
569
  context={
524
570
  "params": params,
525
571
  "release": {"status": "success", "logical_date": release.date},
526
- "outputs": rs.context,
572
+ "outputs": context,
527
573
  },
528
574
  )
529
575
 
530
- def queue_poking(
576
+ def queue(
531
577
  self,
532
578
  offset: float,
533
579
  end_date: datetime,
@@ -654,12 +700,13 @@ class Workflow(BaseModel):
654
700
  )
655
701
 
656
702
  params: DictData = {} if params is None else params
657
- wf_queue: WorkflowQueue = WorkflowQueue()
658
703
  results: list[Result] = []
659
- futures: list[Future] = []
704
+
705
+ # NOTE: Create empty WorkflowQueue object.
706
+ wf_queue: WorkflowQueue = WorkflowQueue()
660
707
 
661
708
  # NOTE: Make queue to the workflow queue object.
662
- self.queue_poking(
709
+ self.queue(
663
710
  offset,
664
711
  end_date=end_date,
665
712
  queue=wf_queue,
@@ -680,6 +727,8 @@ class Workflow(BaseModel):
680
727
  thread_name_prefix="wf_poking_",
681
728
  ) as executor:
682
729
 
730
+ futures: list[Future] = []
731
+
683
732
  while wf_queue.is_queued:
684
733
 
685
734
  # NOTE: Pop the latest WorkflowRelease object from queue.
@@ -697,7 +746,7 @@ class Workflow(BaseModel):
697
746
 
698
747
  # WARNING: I already call queue poking again because issue
699
748
  # about the every minute crontab.
700
- self.queue_poking(
749
+ self.queue(
701
750
  offset,
702
751
  end_date,
703
752
  queue=wf_queue,
@@ -719,7 +768,7 @@ class Workflow(BaseModel):
719
768
  )
720
769
  )
721
770
 
722
- self.queue_poking(
771
+ self.queue(
723
772
  offset,
724
773
  end_date,
725
774
  queue=wf_queue,
@@ -1017,7 +1066,7 @@ class Workflow(BaseModel):
1017
1066
  not_timeout_flag: bool = True
1018
1067
  timeout: int = timeout or config.max_job_exec_timeout
1019
1068
  logger.debug(
1020
- f"({cut_id(run_id)}) [WORKFLOW]: Run {self.name} with "
1069
+ f"({cut_id(run_id)}) [WORKFLOW]: Run {self.name!r} with "
1021
1070
  f"non-threading."
1022
1071
  )
1023
1072
 
@@ -1064,7 +1113,7 @@ class Workflow(BaseModel):
1064
1113
 
1065
1114
 
1066
1115
  @dataclass(config=ConfigDict(arbitrary_types_allowed=True))
1067
- class WorkflowTaskData:
1116
+ class WorkflowTask:
1068
1117
  """Workflow task Pydantic dataclass object that use to keep mapping data and
1069
1118
  workflow model for passing to the multithreading task.
1070
1119
 
@@ -1075,132 +1124,95 @@ class WorkflowTaskData:
1075
1124
  alias: str
1076
1125
  workflow: Workflow
1077
1126
  runner: CronRunner
1078
- params: DictData
1127
+ values: DictData = field(default_factory=dict)
1079
1128
 
1080
1129
  def release(
1081
1130
  self,
1082
- queue: dict[str, list[datetime]],
1083
- log: Log | None = None,
1131
+ release: datetime | WorkflowRelease | None = None,
1084
1132
  run_id: str | None = None,
1085
- *,
1086
- waiting_sec: int = 60,
1087
- sleep_interval: int = 15,
1088
- ) -> None: # pragma: no cov
1089
- """Workflow task release that use the same logic of `workflow.release`
1090
- method.
1091
-
1092
- :param queue:
1093
- :param log: A log object for saving result logging from workflow
1094
- execution process.
1095
- :param run_id: A workflow running ID for this release.
1096
- :param waiting_sec: A second period value that allow workflow execute.
1097
- :param sleep_interval: A second value that want to waiting until time
1098
- to execute.
1099
- """
1100
- log: Log = log or FileLog
1101
- run_id: str = run_id or gen_id(self.workflow.name, unique=True)
1102
- runner: CronRunner = self.runner
1103
-
1104
- # NOTE: get next schedule time that generate from now.
1105
- next_time: datetime = runner.date
1133
+ log: type[Log] = None,
1134
+ queue: (
1135
+ WorkflowQueue | list[datetime] | list[WorkflowRelease] | None
1136
+ ) = None,
1137
+ ) -> Result:
1138
+ """Release the workflow task data.
1106
1139
 
1107
- # NOTE: get next utils it does not running.
1108
- while log.is_pointed(self.workflow.name, next_time) or (
1109
- next_time in queue[self.alias]
1110
- ):
1111
- next_time: datetime = runner.next
1140
+ :param release: A release datetime or WorkflowRelease object.
1141
+ :param run_id: A workflow running ID for this release.
1142
+ :param log: A log class that want to save the execution result.
1143
+ :param queue: A WorkflowQueue object.
1112
1144
 
1113
- logger.debug(
1114
- f"({cut_id(run_id)}) [CORE]: {self.workflow.name!r} : "
1115
- f"{runner.cron} : {next_time:%Y-%m-%d %H:%M:%S}"
1145
+ :rtype: Result
1146
+ """
1147
+ log: type[Log] = log or FileLog
1148
+ return self.workflow.release(
1149
+ release=release or self.runner.next,
1150
+ params=self.values,
1151
+ run_id=run_id,
1152
+ log=log,
1153
+ queue=queue,
1154
+ override_log_name=self.alias,
1116
1155
  )
1117
- heappush(queue[self.alias], next_time)
1118
- start_sec: float = time.monotonic()
1119
-
1120
- if get_diff_sec(next_time, tz=runner.tz) > waiting_sec:
1121
- logger.debug(
1122
- f"({cut_id(run_id)}) [WORKFLOW]: {self.workflow.name!r} : "
1123
- f"{runner.cron} "
1124
- f": Does not closely >> {next_time:%Y-%m-%d %H:%M:%S}"
1125
- )
1126
1156
 
1127
- # NOTE: Add this next running datetime that not in period to queue
1128
- # and remove it to running.
1129
- queue[self.alias].remove(next_time)
1157
+ def queue(
1158
+ self,
1159
+ end_date: datetime,
1160
+ queue: WorkflowQueue,
1161
+ log: type[Log],
1162
+ *,
1163
+ force_run: bool = False,
1164
+ ):
1165
+ """Generate WorkflowRelease to WorkflowQueue object.
1166
+
1167
+ :param end_date: An end datetime object.
1168
+ :param queue: A workflow queue object.
1169
+ :param log: A log class that want to making log object.
1170
+ :param force_run: A flag that allow to release workflow if the log with
1171
+ that release was pointed.
1130
1172
 
1131
- time.sleep(0.2)
1132
- return
1173
+ :rtype: WorkflowQueue
1174
+ """
1175
+ if self.runner.date > end_date:
1176
+ return queue
1133
1177
 
1134
- logger.debug(
1135
- f"({cut_id(run_id)}) [CORE]: {self.workflow.name!r} : "
1136
- f"{runner.cron} : Closely to run >> {next_time:%Y-%m-%d %H:%M:%S}"
1178
+ workflow_release = WorkflowRelease(
1179
+ date=self.runner.date,
1180
+ offset=0,
1181
+ end_date=end_date,
1182
+ runner=self.runner,
1183
+ type="task",
1137
1184
  )
1138
1185
 
1139
- # NOTE: Release when the time is nearly to schedule time.
1140
- while (duration := get_diff_sec(next_time, tz=config.tz)) > (
1141
- sleep_interval + 5
1186
+ while queue.check_queue(workflow_release) or (
1187
+ log.is_pointed(name=self.alias, release=workflow_release.date)
1188
+ and not force_run
1142
1189
  ):
1143
- logger.debug(
1144
- f"({cut_id(run_id)}) [CORE]: {self.workflow.name!r} : "
1145
- f"{runner.cron} : Sleep until: {duration}"
1190
+ workflow_release = WorkflowRelease(
1191
+ date=self.runner.next,
1192
+ offset=0,
1193
+ end_date=end_date,
1194
+ runner=self.runner,
1195
+ type="task",
1146
1196
  )
1147
- time.sleep(15)
1148
-
1149
- time.sleep(0.5)
1150
1197
 
1151
- # NOTE: Release parameter that use to change if params has
1152
- # templating.
1153
- release_params: DictData = {
1154
- "release": {
1155
- "logical_date": next_time,
1156
- },
1157
- }
1198
+ if self.runner.date > end_date:
1199
+ return queue
1158
1200
 
1159
- # WARNING: Re-create workflow object that use new running workflow ID.
1160
- rs: Result = self.workflow.execute(
1161
- params=param2template(self.params, release_params),
1162
- )
1163
- logger.debug(
1164
- f"({cut_id(run_id)}) [CORE]: {self.workflow.name!r} : "
1165
- f"{runner.cron} : End release - {next_time:%Y-%m-%d %H:%M:%S}"
1166
- )
1201
+ # NOTE: Push the WorkflowRelease object to queue.
1202
+ queue.push_queue(workflow_release)
1167
1203
 
1168
- # NOTE: Set parent ID on this result.
1169
- rs.set_parent_run_id(run_id)
1204
+ return queue
1170
1205
 
1171
- # NOTE: Save result to log object saving.
1172
- rs_log: Log = log.model_validate(
1173
- {
1174
- "name": self.workflow.name,
1175
- "type": "schedule",
1176
- "release": next_time,
1177
- "context": rs.context,
1178
- "parent_run_id": rs.run_id,
1179
- "run_id": rs.run_id,
1180
- }
1206
+ def __repr__(self) -> str:
1207
+ return (
1208
+ f"{self.__class__.__name__}(alias={self.alias!r}, "
1209
+ f"workflow={self.workflow.name!r}, runner={self.runner!r}, "
1210
+ f"values={self.values})"
1181
1211
  )
1182
- rs_log.save(excluded=None)
1183
-
1184
- # NOTE: Remove the current release date from the running.
1185
- queue[self.alias].remove(next_time)
1186
- total_sec: float = time.monotonic() - start_sec
1187
-
1188
- # IMPORTANT:
1189
- # Add the next running datetime to workflow task queue.
1190
- future_running_time: datetime = runner.next
1191
-
1192
- while (
1193
- future_running_time in queue[self.alias]
1194
- or (future_running_time - next_time).total_seconds() < total_sec
1195
- ): # pragma: no cov
1196
- future_running_time: datetime = runner.next
1197
-
1198
- # NOTE: Queue next release date.
1199
- logger.debug(f"[CORE]: {'-' * 100}")
1200
1212
 
1201
- def __eq__(self, other: WorkflowTaskData) -> bool:
1213
+ def __eq__(self, other: WorkflowTask) -> bool:
1202
1214
  """Override equal property that will compare only the same type."""
1203
- if isinstance(other, WorkflowTaskData):
1215
+ if isinstance(other, WorkflowTask):
1204
1216
  return (
1205
1217
  self.workflow.name == other.workflow.name
1206
1218
  and self.runner.cron == other.runner.cron
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ddeutil-workflow
3
- Version: 0.0.22
3
+ Version: 0.0.24
4
4
  Summary: Lightweight workflow orchestration with less dependencies
5
5
  Author-email: ddeutils <korawich.anu@gmail.com>
6
6
  License: MIT
@@ -24,7 +24,7 @@ Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
25
  Requires-Dist: ddeutil>=0.4.3
26
26
  Requires-Dist: ddeutil-io[toml,yaml]>=0.2.3
27
- Requires-Dist: pydantic==2.10.2
27
+ Requires-Dist: pydantic==2.10.4
28
28
  Requires-Dist: python-dotenv==1.0.1
29
29
  Requires-Dist: typer==0.15.1
30
30
  Requires-Dist: schedule<2.0.0,==1.2.2
@@ -196,7 +196,8 @@ and do not raise any error to you.
196
196
  | `WORKFLOW_CORE_MAX_NUM_POKING` | Core | 4 | . | |
197
197
  | `WORKFLOW_CORE_MAX_JOB_PARALLEL` | Core | 2 | The maximum job number that able to run parallel in workflow executor. | |
198
198
  | `WORKFLOW_CORE_MAX_JOB_EXEC_TIMEOUT` | Core | 600 | | |
199
- | `WORKFLOW_CORE_MAX_ON_PER_WORKFLOW` | Core | 5 | | |
199
+ | `WORKFLOW_CORE_MAX_CRON_PER_WORKFLOW` | Core | 5 | | |
200
+ | `WORKFLOW_CORE_MAX_QUEUE_COMPLETE_HIST` | Core | 16 | | |
200
201
  | `WORKFLOW_CORE_GENERATE_ID_SIMPLE_MODE` | Core | true | A flog that enable generating ID with `md5` algorithm. | |
201
202
  | `WORKFLOW_LOG_DEBUG_MODE` | Log | true | A flag that enable logging with debug level mode. | |
202
203
  | `WORKFLOW_LOG_ENABLE_WRITE` | Log | true | A flag that enable logging object saving log to its destination. | |
@@ -0,0 +1,24 @@
1
+ ddeutil/workflow/__about__.py,sha256=LbAkk7O3dezpuJ-KPhsDQuHdrO9T0qmhBd-oDJzBhq4,28
2
+ ddeutil/workflow/__cron.py,sha256=uA8XcbY_GwA9rJSHaHUaXaJyGDObJN0ZeYlJSinL8y8,26880
3
+ ddeutil/workflow/__init__.py,sha256=49eGrCuchPVZKMybRouAviNhbulK_F6VwCmLm76hIss,1478
4
+ ddeutil/workflow/__types.py,sha256=Ia7f38kvL3NibwmRKi0wQ1ud_45Z-SojYGhNJwIqcu8,3713
5
+ ddeutil/workflow/api.py,sha256=cdRxqwVyGm_Ni_OmflIP35vUkkq8lHpF3xHh_BvVrKs,4692
6
+ ddeutil/workflow/cli.py,sha256=8C5Xri1_82B-sxQcKMPRjDJcuYJG3FZ2bJehvs_xZ4s,3278
7
+ ddeutil/workflow/conf.py,sha256=Al-00Uru2fCJaW2C_vt4IFuBDpI8Y5C4oAuLJ0Vdvbk,16110
8
+ ddeutil/workflow/cron.py,sha256=0SxC3SH-8V1idgAEFOY-gYFEQPjK_zymmc5XqPoX_0I,7504
9
+ ddeutil/workflow/exceptions.py,sha256=NqnQJP52S59XIYMeXbTDbr4xH2UZ5EA3ejpU5Z4g6cQ,894
10
+ ddeutil/workflow/job.py,sha256=cvSLMdc1sMl1MeU7so7Oe2SdRYxQwt6hm55mLV1iP-Y,24219
11
+ ddeutil/workflow/params.py,sha256=uPGkZx18E-iZ8BteqQ2ONgg0frhF3ZmP5cOyfK2j59U,5280
12
+ ddeutil/workflow/repeat.py,sha256=s0azh-f5JQeow7kpxM8GKlqgAmKL7oU6St3L4Ggx4cY,4925
13
+ ddeutil/workflow/result.py,sha256=WIC8MsnfLiWNpZomT6jS4YCdYhlbIVVBjtGGe2dkoKk,3404
14
+ ddeutil/workflow/route.py,sha256=bH5IT90JVjCDe9A0gIefpQQBEfcd-o1uCHE9AvNglvU,6754
15
+ ddeutil/workflow/scheduler.py,sha256=UI8wK2xBYmM3Bh_hel0TMzuJWyezM83Yn4xoiYqTSSQ,20238
16
+ ddeutil/workflow/stage.py,sha256=a2sngzs9DkP6GU2pgAD3QvGoijyBQTR_pOhyJUIuWAo,26692
17
+ ddeutil/workflow/utils.py,sha256=PhNJ54oKnZfq4nVOeP3tDjFN43ArUsMOnpcbSu7bo4I,18450
18
+ ddeutil/workflow/workflow.py,sha256=JyT65Tql7CueQn2z4ZGhp6r44jgYDMcCOpxhiwI19uM,41403
19
+ ddeutil_workflow-0.0.24.dist-info/LICENSE,sha256=nGFZ1QEhhhWeMHf9n99_fdt4vQaXS29xWKxt-OcLywk,1085
20
+ ddeutil_workflow-0.0.24.dist-info/METADATA,sha256=0yh6zKsIu1COnhl-25rOxBGEqLQbrJZzA0IhriO3XwA,14234
21
+ ddeutil_workflow-0.0.24.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
22
+ ddeutil_workflow-0.0.24.dist-info/entry_points.txt,sha256=0BVOgO3LdUdXVZ-CiHHDKxzEk2c8J30jEwHeKn2YCWI,62
23
+ ddeutil_workflow-0.0.24.dist-info/top_level.txt,sha256=m9M6XeSWDwt_yMsmH6gcOjHZVK5O0-vgtNBuncHjzW4,8
24
+ ddeutil_workflow-0.0.24.dist-info/RECORD,,
@@ -1,22 +0,0 @@
1
- ddeutil/workflow/__about__.py,sha256=hJavfsPLTnuXMwKFo9HZgsq6b7tJpWgyfttwaxzMujE,28
2
- ddeutil/workflow/__cron.py,sha256=_2P9nmGOwGdv5bLgf9TpML2HBgqLv_qRgiO1Rulo1PA,26693
3
- ddeutil/workflow/__init__.py,sha256=DCSN0foPFlFLN_Q4uoWa_EBBlKeMHXGpOdr-lWHISrQ,1422
4
- ddeutil/workflow/__types.py,sha256=Ia7f38kvL3NibwmRKi0wQ1ud_45Z-SojYGhNJwIqcu8,3713
5
- ddeutil/workflow/api.py,sha256=vUT2RVS9sF3hvY-IrzAEnahxwq4ZFYP0G3xfctHbNsw,4701
6
- ddeutil/workflow/cli.py,sha256=baHhvtI8snbHYHeThoX401Cd6SMB2boyyCbCtTrIl3E,3278
7
- ddeutil/workflow/conf.py,sha256=GsbuJDQfQoAGiR4keUEoB4lKfZxdkaiZ4N4FfIHc0xY,15814
8
- ddeutil/workflow/exceptions.py,sha256=NqnQJP52S59XIYMeXbTDbr4xH2UZ5EA3ejpU5Z4g6cQ,894
9
- ddeutil/workflow/job.py,sha256=liu8M_pUhAGHZ_Ez922jI94LCC3yioI-Tw5o71Zy88w,24216
10
- ddeutil/workflow/on.py,sha256=wxKfL2u-bBhPbDtZbhqE2lZoPVukHA1zq-qrg0ldic0,7469
11
- ddeutil/workflow/repeat.py,sha256=s0azh-f5JQeow7kpxM8GKlqgAmKL7oU6St3L4Ggx4cY,4925
12
- ddeutil/workflow/route.py,sha256=JALwOH6xKu5rnII7DgA1Lbp_E5ehCoBbOW_eKqB_Olk,6753
13
- ddeutil/workflow/scheduler.py,sha256=B2uXsqzmp32nIbya8EDePYyRhpwcxCMeoibPABCuMOA,18750
14
- ddeutil/workflow/stage.py,sha256=ADFqExFmD8Y00A86TSS05HpabvsLV7_dbLrzD31TkK8,26490
15
- ddeutil/workflow/utils.py,sha256=0GaHpRL1HuyES1NS7r56DFgloOVftYVAvAdVgIbPA_k,26001
16
- ddeutil/workflow/workflow.py,sha256=fzhKJx9s-RF95FQ0tAvAQ1nsL8dsp_py2Ea5TGnjsOk,41542
17
- ddeutil_workflow-0.0.22.dist-info/LICENSE,sha256=nGFZ1QEhhhWeMHf9n99_fdt4vQaXS29xWKxt-OcLywk,1085
18
- ddeutil_workflow-0.0.22.dist-info/METADATA,sha256=J_VrfU8ZBPAa7OrhMV_c4sLbQ0g3Nc0MQSdYUgmxF6I,14017
19
- ddeutil_workflow-0.0.22.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
20
- ddeutil_workflow-0.0.22.dist-info/entry_points.txt,sha256=0BVOgO3LdUdXVZ-CiHHDKxzEk2c8J30jEwHeKn2YCWI,62
21
- ddeutil_workflow-0.0.22.dist-info/top_level.txt,sha256=m9M6XeSWDwt_yMsmH6gcOjHZVK5O0-vgtNBuncHjzW4,8
22
- ddeutil_workflow-0.0.22.dist-info/RECORD,,