ddeutil-workflow 0.0.54__py3-none-any.whl → 0.0.56__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.
@@ -34,7 +34,7 @@ from heapq import heappop, heappush
34
34
  from pathlib import Path
35
35
  from textwrap import dedent
36
36
  from threading import Thread
37
- from typing import Callable, Optional, TypedDict, Union
37
+ from typing import Any, Callable, Optional, TypedDict, Union
38
38
 
39
39
  from pydantic import BaseModel, Field, ValidationInfo
40
40
  from pydantic.functional_validators import field_validator, model_validator
@@ -52,8 +52,8 @@ except ImportError: # pragma: no cov
52
52
 
53
53
  from .__cron import CronRunner
54
54
  from .__types import DictData, TupleStr
55
- from .conf import Loader, SimLoad, dynamic
56
- from .cron import On
55
+ from .conf import FileLoad, Loader, dynamic
56
+ from .event import On
57
57
  from .exceptions import ScheduleException, WorkflowException
58
58
  from .logs import Audit, get_audit
59
59
  from .result import SUCCESS, Result
@@ -113,21 +113,15 @@ class ScheduleWorkflow(BaseModel):
113
113
  )
114
114
 
115
115
  @model_validator(mode="before")
116
- def __prepare_before__(cls, values: DictData) -> DictData:
117
- """Prepare incoming values before validating with model fields.
118
-
119
- :rtype: DictData
120
- """
121
- # VALIDATE: Prepare a workflow name that should not include space.
122
- if name := values.get("name"):
123
- values["name"] = name.replace(" ", "_")
124
-
125
- # VALIDATE: Add default the alias field with the name.
126
- if not values.get("alias"):
127
- values["alias"] = values.get("name")
128
-
129
- cls.__bypass_on(values, extras=values.get("extras"))
130
- return values
116
+ def __prepare_before__(cls, data: Any) -> Any:
117
+ """Prepare incoming values before validating with model fields."""
118
+ if isinstance(data, dict):
119
+ # VALIDATE: Add default the alias field with the name.
120
+ if "alias" not in data:
121
+ data["alias"] = data.get("name")
122
+
123
+ cls.__bypass_on(data, extras=data.get("extras"))
124
+ return data
131
125
 
132
126
  @classmethod
133
127
  def __bypass_on(
@@ -135,8 +129,10 @@ class ScheduleWorkflow(BaseModel):
135
129
  ) -> DictData:
136
130
  """Bypass and prepare the on data to loaded config data.
137
131
 
138
- :param data: A data that want to validate for model initialization.
139
- :param extras: An extra parameter that want to override core config.
132
+ :param data: (DictData) A data that want to validate for the model
133
+ initialization.
134
+ :param extras: (DictData) An extra parameter that want to override core
135
+ config values.
140
136
 
141
137
  :rtype: DictData
142
138
  """
@@ -151,7 +147,7 @@ class ScheduleWorkflow(BaseModel):
151
147
  # NOTE: Pass on value to Loader and keep on model object to on
152
148
  # field.
153
149
  data["on"] = [
154
- Loader(n, externals=extras).data if isinstance(n, str) else n
150
+ FileLoad(n, externals=extras).data if isinstance(n, str) else n
155
151
  for n in on
156
152
  ]
157
153
 
@@ -162,6 +158,10 @@ class ScheduleWorkflow(BaseModel):
162
158
  """Validate the on fields should not contain duplicate values and if it
163
159
  contains every minute value, it should have only one on value.
164
160
 
161
+ :param value: (list[On]) A list of `On` object.
162
+ :param info: (ValidationInfo) An validation info object for getting an
163
+ extra parameter.
164
+
165
165
  :rtype: list[On]
166
166
  """
167
167
  set_ons: set[str] = {str(on.cronjob) for on in value}
@@ -191,23 +191,22 @@ class ScheduleWorkflow(BaseModel):
191
191
  This task creation need queue to tracking release date already
192
192
  mapped or not.
193
193
 
194
- :param start_date: A start date that get from the workflow schedule.
195
- :param queue: A mapping of name and list of datetime for queue.
194
+ :param start_date: (datetime) A start datetime that get from the
195
+ workflow schedule.
196
+ :param queue: (dict[str, ReleaseQueue]) A mapping of name and list of
197
+ datetime for queue.
196
198
 
197
199
  :rtype: list[WorkflowTask]
198
200
  :return: Return the list of WorkflowTask object from the specific
199
201
  input datetime that mapping with the on field.
200
202
  """
201
- workflow_tasks: list[WorkflowTask] = []
202
-
203
- # NOTE: Loading workflow model from the name of workflow.
204
203
  wf: Workflow = Workflow.from_conf(self.name, extras=self.extras)
205
204
  wf_queue: ReleaseQueue = queue[self.alias]
206
205
 
207
206
  # IMPORTANT: Create the default 'on' value if it does not pass the `on`
208
207
  # field to the Schedule object.
209
208
  ons: list[On] = self.on or wf.on.copy()
210
-
209
+ workflow_tasks: list[WorkflowTask] = []
211
210
  for on in ons:
212
211
 
213
212
  # NOTE: Create CronRunner instance from the start_date param.
@@ -250,7 +249,7 @@ class Schedule(BaseModel):
250
249
  )
251
250
  workflows: list[ScheduleWorkflow] = Field(
252
251
  default_factory=list,
253
- description="A list of ScheduleWorkflow models.",
252
+ description="A list of ScheduleWorkflow model.",
254
253
  )
255
254
 
256
255
  @field_validator("desc", mode="after")
@@ -267,6 +266,8 @@ class Schedule(BaseModel):
267
266
  def from_conf(
268
267
  cls,
269
268
  name: str,
269
+ *,
270
+ path: Optional[Path] = None,
270
271
  extras: DictData | None = None,
271
272
  ) -> Self:
272
273
  """Create Schedule instance from the Loader object that only receive
@@ -274,6 +275,7 @@ class Schedule(BaseModel):
274
275
  searching configuration data of this schedule model in conf path.
275
276
 
276
277
  :param name: (str) A schedule name that want to pass to Loader object.
278
+ :param path: (Path) An override config path.
277
279
  :param extras: An extra parameters that want to pass to Loader
278
280
  object.
279
281
 
@@ -281,55 +283,14 @@ class Schedule(BaseModel):
281
283
 
282
284
  :rtype: Self
283
285
  """
284
- loader: Loader = Loader(name, externals=(extras or {}))
286
+ loader: Loader = FileLoad(name, path=path, extras=extras)
285
287
 
286
288
  # NOTE: Validate the config type match with current connection model
287
289
  if loader.type != cls.__name__:
288
290
  raise ValueError(f"Type {loader.type} does not match with {cls}")
289
291
 
290
292
  loader_data: DictData = copy.deepcopy(loader.data)
291
-
292
- # NOTE: Add name to loader data
293
- loader_data["name"] = name.replace(" ", "_")
294
-
295
- if extras:
296
- loader_data["extras"] = extras
297
-
298
- return cls.model_validate(obj=loader_data)
299
-
300
- @classmethod
301
- def from_path(
302
- cls,
303
- name: str,
304
- path: Path,
305
- extras: DictData | None = None,
306
- ) -> Self:
307
- """Create Schedule instance from the SimLoad object that receive an
308
- input schedule name and conf path. The loader object will use this
309
- schedule name to searching configuration data of this schedule model
310
- in conf path.
311
-
312
- :param name: (str) A schedule name that want to pass to Loader object.
313
- :param path: (Path) A config path that want to search.
314
- :param extras: An external parameters that want to pass to Loader
315
- object.
316
-
317
- :raise ValueError: If the type does not match with current object.
318
-
319
- :rtype: Self
320
- """
321
- loader: SimLoad = SimLoad(
322
- name, conf_path=path, externals=(extras or {})
323
- )
324
-
325
- # NOTE: Validate the config type match with current connection model
326
- if loader.type != cls.__name__:
327
- raise ValueError(f"Type {loader.type} does not match with {cls}")
328
-
329
- loader_data: DictData = copy.deepcopy(loader.data)
330
-
331
- # NOTE: Add name to loader data
332
- loader_data["name"] = name.replace(" ", "_")
293
+ loader_data["name"] = name
333
294
 
334
295
  if extras:
335
296
  loader_data["extras"] = extras
@@ -535,9 +496,7 @@ def schedule_task(
535
496
  current_release: datetime = current_date.replace(
536
497
  second=0, microsecond=0
537
498
  )
538
- if (
539
- first_date := q.first_queue.date
540
- ) > current_release: # pragma: no cov
499
+ if (first_date := q.queue[0].date) > current_release: # pragma: no cov
541
500
  result.trace.debug(
542
501
  f"[WORKFLOW]: Skip schedule "
543
502
  f"{first_date:%Y-%m-%d %H:%M:%S} for : {task.alias!r}"