ddeutil-workflow 0.0.26.post1__py3-none-any.whl → 0.0.28__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/job.py CHANGED
@@ -38,13 +38,13 @@ from .exceptions import (
38
38
  )
39
39
  from .result import Result
40
40
  from .stage import Stage
41
+ from .templates import has_template
41
42
  from .utils import (
42
43
  cross_product,
43
44
  cut_id,
44
45
  dash2underscore,
45
46
  filter_func,
46
47
  gen_id,
47
- has_template,
48
48
  )
49
49
 
50
50
  logger = get_logger("ddeutil.workflow")
@@ -83,7 +83,7 @@ def make(
83
83
  if len(matrix) == 0:
84
84
  return [{}]
85
85
 
86
- # NOTE: Remove matrix that exists on the exclude.
86
+ # NOTE: Remove matrix that exists on the excluded.
87
87
  final: list[DictStr] = []
88
88
  for r in cross_product(matrix=matrix):
89
89
  if any(
@@ -101,7 +101,7 @@ def make(
101
101
  add: list[DictStr] = []
102
102
  for inc in include:
103
103
  # VALIDATE:
104
- # Validate any key in include list should be a subset of some one
104
+ # Validate any key in include list should be a subset of someone
105
105
  # in matrix.
106
106
  if all(not (set(inc.keys()) <= set(m.keys())) for m in final):
107
107
  raise ValueError(
@@ -128,9 +128,9 @@ class Strategy(BaseModel):
128
128
  special job with combination of matrix data.
129
129
 
130
130
  This model does not be the part of job only because you can use it to
131
- any model object. The propose of this model is generate metrix result that
132
- comming from combination logic with any matrix values for running it with
133
- parallelism.
131
+ any model object. The objective of this model is generating metrix result
132
+ that comming from combination logic with any matrix values for running it
133
+ with parallelism.
134
134
 
135
135
  [1, 2, 3] x [a, b] --> [1a], [1b], [2a], [2b], [3a], [3b]
136
136
 
@@ -180,7 +180,7 @@ class Strategy(BaseModel):
180
180
  """Rename key that use dash to underscore because Python does not
181
181
  support this character exist in any variable name.
182
182
 
183
- :param values: A parsing values to this models
183
+ :param values: A parsing values to these models
184
184
  :rtype: DictData
185
185
  """
186
186
  dash2underscore("max-parallel", values)
@@ -226,7 +226,7 @@ class Job(BaseModel):
226
226
  """Job Pydantic model object (short descripte: a group of stages).
227
227
 
228
228
  This job model allow you to use for-loop that call matrix strategy. If
229
- you pass matrix mapping and it able to generate, you will see it running
229
+ you pass matrix mapping, and it is able to generate, you will see it running
230
230
  with loop of matrix values.
231
231
 
232
232
  Data Validate:
@@ -355,7 +355,7 @@ class Job(BaseModel):
355
355
  return all(need in jobs for need in self.needs)
356
356
 
357
357
  def set_outputs(self, output: DictData, to: DictData) -> DictData:
358
- """Set an outputs from execution process to the receive context. The
358
+ """Set an outputs from execution process to the received context. The
359
359
  result from execution will pass to value of ``strategies`` key.
360
360
 
361
361
  For example of setting output method, If you receive execute output
@@ -420,7 +420,7 @@ class Job(BaseModel):
420
420
  strategy and return with context of this strategy data.
421
421
 
422
422
  The result of this execution will return result with strategy ID
423
- that generated from the `gen_id` function with a input strategy value.
423
+ that generated from the `gen_id` function with an input strategy value.
424
424
 
425
425
  :raise JobException: If it has any error from ``StageException`` or
426
426
  ``UtilException``.
@@ -429,7 +429,7 @@ class Job(BaseModel):
429
429
  This value will pass to the `matrix` key for templating.
430
430
  :param params: A dynamic parameters that will deepcopy to the context.
431
431
  :param run_id: A job running ID for this strategy execution.
432
- :param event: An manger event that pass to the PoolThreadExecutor.
432
+ :param event: An event manager that pass to the PoolThreadExecutor.
433
433
 
434
434
  :rtype: Result
435
435
  """
@@ -496,7 +496,7 @@ class Job(BaseModel):
496
496
  # PARAGRAPH:
497
497
  #
498
498
  # I do not use below syntax because `params` dict be the
499
- # reference memory pointer and it was changed when I action
499
+ # reference memory pointer, and it was changed when I action
500
500
  # anything like update or re-construct this.
501
501
  #
502
502
  # ... params |= stage.execute(params=params)
@@ -513,7 +513,9 @@ class Job(BaseModel):
513
513
  #
514
514
  try:
515
515
  stage.set_outputs(
516
- stage.execute(params=context, run_id=run_id).context,
516
+ stage.handler_execute(
517
+ params=context, run_id=run_id
518
+ ).context,
517
519
  to=context,
518
520
  )
519
521
  except (StageException, UtilException) as err:
@@ -566,7 +568,7 @@ class Job(BaseModel):
566
568
  run_id: str = run_id or gen_id(self.id or "", unique=True)
567
569
  context: DictData = {}
568
570
 
569
- # NOTE: Normal Job execution without parallel strategy matrix. It use
571
+ # NOTE: Normal Job execution without parallel strategy matrix. It uses
570
572
  # for-loop to control strategy execution sequentially.
571
573
  if (not self.strategy.is_set()) or self.strategy.max_parallel == 1:
572
574
  for strategy in self.strategy.make():
@@ -585,8 +587,7 @@ class Job(BaseModel):
585
587
  event: Event = Event()
586
588
 
587
589
  # IMPORTANT: Start running strategy execution by multithreading because
588
- # it will running by strategy values without waiting previous
589
- # execution.
590
+ # it will run by strategy values without waiting previous execution.
590
591
  with ThreadPoolExecutor(
591
592
  max_workers=self.strategy.max_parallel,
592
593
  thread_name_prefix="job_strategy_exec_",
@@ -618,7 +619,7 @@ class Job(BaseModel):
618
619
  timeout: int = 1800,
619
620
  ) -> Result:
620
621
  """Job parallel pool futures catching with fail-fast mode. That will
621
- stop and set event on all not done futures if it receive the first
622
+ stop and set event on all not done futures if it receives the first
622
623
  exception from all running futures.
623
624
 
624
625
  :param event: An event manager instance that able to set stopper on the
@@ -75,7 +75,7 @@ class DatetimeParam(DefaultParam):
75
75
  default: datetime = Field(default_factory=get_dt_now)
76
76
 
77
77
  def receive(self, value: str | datetime | date | None = None) -> datetime:
78
- """Receive value that match with datetime. If a input value pass with
78
+ """Receive value that match with datetime. If an input value pass with
79
79
  None, it will use default value instead.
80
80
 
81
81
  :param value: A value that want to validate with datetime parameter
@@ -98,7 +98,7 @@ class DatetimeParam(DefaultParam):
98
98
  return datetime.fromisoformat(value)
99
99
  except ValueError:
100
100
  raise ParamValueException(
101
- f"Invalid isoformat string: {value!r}"
101
+ f"Invalid the ISO format string: {value!r}"
102
102
  ) from None
103
103
 
104
104
 
@@ -158,7 +158,7 @@ class ChoiceParam(BaseParam):
158
158
  :rtype: str
159
159
  """
160
160
  # NOTE:
161
- # Return the first value in options if does not pass any input value
161
+ # Return the first value in options if it does not pass any input value
162
162
  if value is None:
163
163
  return self.options[0]
164
164
  if value not in self.options:
@@ -37,8 +37,8 @@ class Result:
37
37
 
38
38
  @model_validator(mode="after")
39
39
  def __prepare_run_id(self) -> Self:
40
- """Prepare running ID which use default ID if it initialize at the first
41
- time
40
+ """Prepare running ID which use default ID if it initializes at the
41
+ first time.
42
42
 
43
43
  :rtype: Self
44
44
  """
@@ -84,7 +84,7 @@ class Result:
84
84
 
85
85
  def receive_jobs(self, result: Result) -> Self:
86
86
  """Receive context from another result object that use on the workflow
87
- execution which create a ``jobs`` keys on the context if it do not
87
+ execution which create a ``jobs`` keys on the context if it does not
88
88
  exist.
89
89
 
90
90
  :rtype: Self
@@ -149,7 +149,7 @@ class WorkflowSchedule(BaseModel):
149
149
  @field_validator("on", mode="after")
150
150
  def __on_no_dup__(cls, value: list[On]) -> list[On]:
151
151
  """Validate the on fields should not contain duplicate values and if it
152
- contain every minute value, it should has only one on value.
152
+ contains every minute value, it should have only one on value.
153
153
 
154
154
  :rtype: list[On]
155
155
  """
@@ -195,8 +195,8 @@ class WorkflowSchedule(BaseModel):
195
195
  wf: Workflow = Workflow.from_loader(self.name, externals=extras)
196
196
  wf_queue: WorkflowQueue = queue[self.alias]
197
197
 
198
- # IMPORTANT: Create the default 'on' value if it does not passing
199
- # the on field to the Schedule object.
198
+ # IMPORTANT: Create the default 'on' value if it does not pass the `on`
199
+ # field to the Schedule object.
200
200
  ons: list[On] = self.on or wf.on.copy()
201
201
 
202
202
  for on in ons:
@@ -223,7 +223,7 @@ class WorkflowSchedule(BaseModel):
223
223
  class Schedule(BaseModel):
224
224
  """Schedule Pydantic model that use to run with any scheduler package.
225
225
 
226
- It does not equal the on value in Workflow model but it use same logic
226
+ It does not equal the on value in Workflow model, but it uses same logic
227
227
  to running release date with crontab interval.
228
228
  """
229
229
 
@@ -368,7 +368,7 @@ def schedule_task(
368
368
  :param stop: A stop datetime object that force stop running scheduler.
369
369
  :param queue: A mapping of alias name and WorkflowQueue object.
370
370
  :param threads: A mapping of alias name and Thread object.
371
- :param log: A log class that want to making log object.
371
+ :param log: A log class that want to make log object.
372
372
 
373
373
  :rtype: CancelJob | None
374
374
  """
@@ -449,7 +449,7 @@ def schedule_task(
449
449
 
450
450
 
451
451
  def monitor(threads: ReleaseThreads) -> None: # pragma: no cov
452
- """Monitoring function that running every five minute for track long running
452
+ """Monitoring function that running every five minute for track long-running
453
453
  thread instance from the schedule_control function that run every minute.
454
454
 
455
455
  :param threads: A mapping of Thread object and its name.
@@ -479,7 +479,7 @@ def schedule_control(
479
479
  """Scheduler control function that running every minute.
480
480
 
481
481
  :param schedules: A list of workflow names that want to schedule running.
482
- :param stop: An datetime value that use to stop running schedule.
482
+ :param stop: A datetime value that use to stop running schedule.
483
483
  :param externals: An external parameters that pass to Loader.
484
484
  :param log:
485
485
 
@@ -554,7 +554,7 @@ def schedule_control(
554
554
  scheduler.run_pending()
555
555
  time.sleep(1)
556
556
 
557
- # NOTE: Break the scheduler when the control job does not exists.
557
+ # NOTE: Break the scheduler when the control job does not exist.
558
558
  if not scheduler.get_jobs("control"):
559
559
  scheduler.clear("monitor")
560
560
 
@@ -585,7 +585,7 @@ def schedule_runner(
585
585
 
586
586
  :param stop: A stop datetime object that force stop running scheduler.
587
587
  :param externals:
588
- :param excluded: A list of schedule name that want to excluded from finding.
588
+ :param excluded: A list of schedule name that want to exclude from finding.
589
589
 
590
590
  :rtype: list[str]
591
591
 
ddeutil/workflow/stage.py CHANGED
@@ -5,12 +5,12 @@
5
5
  # ------------------------------------------------------------------------------
6
6
  """Stage Model that use for getting stage data template from the Job Model.
7
7
  The stage handle the minimize task that run in some thread (same thread at
8
- its job owner) that mean it is the lowest executor of a workflow workflow that
9
- can tracking logs.
8
+ its job owner) that mean it is the lowest executor of a workflow that can
9
+ tracking logs.
10
10
 
11
11
  The output of stage execution only return 0 status because I do not want to
12
12
  handle stage error on this stage model. I think stage model should have a lot of
13
- usecase and it does not worry when I want to create a new one.
13
+ use-case, and it does not worry when I want to create a new one.
14
14
 
15
15
  Execution --> Ok --> Result with 0
16
16
 
@@ -31,41 +31,28 @@ import time
31
31
  import uuid
32
32
  from abc import ABC, abstractmethod
33
33
  from collections.abc import Iterator
34
- from dataclasses import dataclass
35
- from functools import wraps
36
34
  from inspect import Parameter
37
35
  from pathlib import Path
38
36
  from subprocess import CompletedProcess
39
37
  from textwrap import dedent
40
- from typing import Callable, Optional, Union
41
-
42
- try:
43
- from typing import ParamSpec
44
- except ImportError:
45
- from typing_extensions import ParamSpec
38
+ from typing import Optional, Union
46
39
 
47
40
  from pydantic import BaseModel, Field
48
41
  from pydantic.functional_validators import model_validator
49
42
  from typing_extensions import Self
50
43
 
51
- from .__types import DictData, DictStr, Re, TupleStr
44
+ from .__types import DictData, DictStr, TupleStr
52
45
  from .conf import config, get_logger
53
46
  from .exceptions import StageException
47
+ from .hook import TagFunc, extract_hook
54
48
  from .result import Result
49
+ from .templates import not_in_template, param2template
55
50
  from .utils import (
56
- Registry,
57
- TagFunc,
58
51
  cut_id,
59
52
  gen_id,
60
53
  make_exec,
61
- make_registry,
62
- not_in_template,
63
- param2template,
64
54
  )
65
55
 
66
- P = ParamSpec("P")
67
- ReturnResult = Callable[P, Result]
68
- DecoratorResult = Callable[[ReturnResult], ReturnResult]
69
56
  logger = get_logger("ddeutil.workflow")
70
57
 
71
58
 
@@ -76,94 +63,9 @@ __all__: TupleStr = (
76
63
  "HookStage",
77
64
  "TriggerStage",
78
65
  "Stage",
79
- "extract_hook",
80
66
  )
81
67
 
82
68
 
83
- def handler_result(message: str | None = None) -> DecoratorResult:
84
- """Decorator function for handler result from the stage execution. This
85
- function should to use with execution method only.
86
-
87
- This stage exception handler still use ok-error concept but it allow
88
- you force catching an output result with error message by specific
89
- environment variable,`WORKFLOW_CORE_STAGE_RAISE_ERROR`.
90
-
91
- Execution --> Ok --> Result
92
- |-status: 0
93
- |-context:
94
- |-outputs: ...
95
-
96
- --> Error --> Result (if env var was set)
97
- |-status: 1
98
- |-context:
99
- |-error: ...
100
- |-error_message: ...
101
-
102
- --> Error --> Raise StageException(...)
103
-
104
- On the last step, it will set the running ID on a return result object
105
- from current stage ID before release the final result.
106
-
107
- :param message: A message that want to add at prefix of exception statement.
108
- :type message: str | None (Default=None)
109
- :rtype: Callable[P, Result]
110
- """
111
- # NOTE: The prefix message string that want to add on the first exception
112
- # message dialog.
113
- #
114
- # >>> ValueError: {message}
115
- # ... raise value error from the stage execution process.
116
- #
117
- message: str = message or ""
118
-
119
- def decorator(func: ReturnResult) -> ReturnResult:
120
-
121
- @wraps(func)
122
- def wrapped(self: Stage, *args, **kwargs):
123
-
124
- if not (run_id := kwargs.get("run_id")):
125
- run_id: str = gen_id(self.name + (self.id or ""), unique=True)
126
- kwargs["run_id"] = run_id
127
-
128
- rs_raise: Result = Result(status=1, run_id=run_id)
129
-
130
- try:
131
- # NOTE: Start calling origin function with a passing args.
132
- return func(self, *args, **kwargs)
133
- except Exception as err:
134
- # NOTE: Start catching error from the stage execution.
135
- logger.error(
136
- f"({cut_id(run_id)}) [STAGE]: {err.__class__.__name__}: "
137
- f"{err}"
138
- )
139
- if config.stage_raise_error:
140
- # NOTE: If error that raise from stage execution course by
141
- # itself, it will return that error with previous
142
- # dependency.
143
- if isinstance(err, StageException):
144
- raise StageException(
145
- f"{self.__class__.__name__}: {message}\n\t{err}"
146
- ) from err
147
- raise StageException(
148
- f"{self.__class__.__name__}: {message}\n\t"
149
- f"{err.__class__.__name__}: {err}"
150
- ) from None
151
-
152
- # NOTE: Catching exception error object to result with
153
- # error_message and error keys.
154
- return rs_raise.catch(
155
- status=1,
156
- context={
157
- "error": err,
158
- "error_message": f"{err.__class__.__name__}: {err}",
159
- },
160
- )
161
-
162
- return wrapped
163
-
164
- return decorator
165
-
166
-
167
69
  class BaseStage(BaseModel, ABC):
168
70
  """Base Stage Model that keep only id and name fields for the stage
169
71
  metadata. If you want to implement any custom stage, you can use this class
@@ -230,8 +132,74 @@ class BaseStage(BaseModel, ABC):
230
132
  """
231
133
  raise NotImplementedError("Stage should implement ``execute`` method.")
232
134
 
135
+ def handler_execute(
136
+ self, params: DictData, *, run_id: str | None = None
137
+ ) -> Result:
138
+ """Handler result from the stage execution.
139
+
140
+ This stage exception handler still use ok-error concept, but it
141
+ allows you force catching an output result with error message by
142
+ specific environment variable,`WORKFLOW_CORE_STAGE_RAISE_ERROR`.
143
+
144
+ Execution --> Ok --> Result
145
+ |-status: 0
146
+ |-context:
147
+ |-outputs: ...
148
+
149
+ --> Error --> Result (if env var was set)
150
+ |-status: 1
151
+ |-context:
152
+ |-error: ...
153
+ |-error_message: ...
154
+
155
+ --> Error --> Raise StageException(...)
156
+
157
+ On the last step, it will set the running ID on a return result object
158
+ from current stage ID before release the final result.
159
+
160
+ :param params: A parameter data that want to use in this execution.
161
+ :param run_id: A running stage ID for this execution.
162
+
163
+ :rtype: Result
164
+ """
165
+ if not run_id:
166
+ run_id: str = gen_id(self.name + (self.id or ""), unique=True)
167
+
168
+ rs_raise: Result = Result(status=1, run_id=run_id)
169
+ try:
170
+ # NOTE: Start calling origin function with a passing args.
171
+ return self.execute(params, run_id=run_id)
172
+ except Exception as err:
173
+ # NOTE: Start catching error from the stage execution.
174
+ logger.error(
175
+ f"({cut_id(run_id)}) [STAGE]: {err.__class__.__name__}: "
176
+ f"{err}"
177
+ )
178
+ if config.stage_raise_error:
179
+ # NOTE: If error that raise from stage execution course by
180
+ # itself, it will return that error with previous
181
+ # dependency.
182
+ if isinstance(err, StageException):
183
+ raise StageException(
184
+ f"{self.__class__.__name__}: \n\t{err}"
185
+ ) from err
186
+ raise StageException(
187
+ f"{self.__class__.__name__}: \n\t"
188
+ f"{err.__class__.__name__}: {err}"
189
+ ) from None
190
+
191
+ # NOTE: Catching exception error object to result with
192
+ # error_message and error keys.
193
+ return rs_raise.catch(
194
+ status=1,
195
+ context={
196
+ "error": err,
197
+ "error_message": f"{err.__class__.__name__}: {err}",
198
+ },
199
+ )
200
+
233
201
  def set_outputs(self, output: DictData, to: DictData) -> DictData:
234
- """Set an outputs from execution process to the receive context. The
202
+ """Set an outputs from execution process to the received context. The
235
203
  result from execution will pass to value of ``outputs`` key.
236
204
 
237
205
  For example of setting output method, If you receive execute output
@@ -248,7 +216,7 @@ class BaseStage(BaseModel, ABC):
248
216
  }
249
217
  }
250
218
 
251
- :param output: A output data that want to extract to an output key.
219
+ :param output: An output data that want to extract to an output key.
252
220
  :param to: A context data that want to add output result.
253
221
  :rtype: DictData
254
222
  """
@@ -293,8 +261,9 @@ class BaseStage(BaseModel, ABC):
293
261
  params: DictData = {} if params is None else params
294
262
 
295
263
  try:
296
- # WARNING: The eval build-in function is vary dangerous. So, it
297
- # should us the re module to validate eval-string before running.
264
+ # WARNING: The eval build-in function is very dangerous. So, it
265
+ # should use the `re` module to validate eval-string before
266
+ # running.
298
267
  rs: bool = eval(
299
268
  param2template(self.condition, params), globals() | params, {}
300
269
  )
@@ -326,7 +295,6 @@ class EmptyStage(BaseStage):
326
295
  ge=0,
327
296
  )
328
297
 
329
- @handler_result()
330
298
  def execute(self, params: DictData, *, run_id: str | None = None) -> Result:
331
299
  """Execution method for the Empty stage that do only logging out to
332
300
  stdout. This method does not use the `handler_result` decorator because
@@ -357,7 +325,7 @@ class EmptyStage(BaseStage):
357
325
 
358
326
  class BashStage(BaseStage):
359
327
  """Bash execution stage that execute bash script on the current OS.
360
- That mean if your current OS is Windows, it will running bash in the WSL.
328
+ If your current OS is Windows, it will run on the bash in the WSL.
361
329
 
362
330
  I get some limitation when I run shell statement with the built-in
363
331
  supprocess package. It does not good enough to use multiline statement.
@@ -423,7 +391,6 @@ class BashStage(BaseStage):
423
391
  # Note: Remove .sh file that use to run bash.
424
392
  Path(f"./{f_name}").unlink()
425
393
 
426
- @handler_result()
427
394
  def execute(self, params: DictData, *, run_id: str | None = None) -> Result:
428
395
  """Execute the Bash statement with the Python build-in ``subprocess``
429
396
  package.
@@ -504,7 +471,7 @@ class PyStage(BaseStage):
504
471
  """Override set an outputs method for the Python execution process that
505
472
  extract output from all the locals values.
506
473
 
507
- :param output: A output data that want to extract to an output key.
474
+ :param output: An output data that want to extract to an output key.
508
475
  :param to: A context data that want to add output result.
509
476
 
510
477
  :rtype: DictData
@@ -525,7 +492,6 @@ class PyStage(BaseStage):
525
492
  to.update({k: gb[k] for k in to if k in gb})
526
493
  return to
527
494
 
528
- @handler_result()
529
495
  def execute(self, params: DictData, *, run_id: str | None = None) -> Result:
530
496
  """Execute the Python statement that pass all globals and input params
531
497
  to globals argument on ``exec`` build-in function.
@@ -547,8 +513,8 @@ class PyStage(BaseStage):
547
513
  # NOTE: Start exec the run statement.
548
514
  logger.info(f"({cut_id(run_id)}) [STAGE]: Py-Execute: {self.name}")
549
515
 
550
- # WARNING: The exec build-in function is vary dangerous. So, it
551
- # should us the re module to validate exec-string before running.
516
+ # WARNING: The exec build-in function is very dangerous. So, it
517
+ # should use the re module to validate exec-string before running.
552
518
  exec(run, _globals, lc)
553
519
 
554
520
  return Result(
@@ -558,53 +524,6 @@ class PyStage(BaseStage):
558
524
  )
559
525
 
560
526
 
561
- @dataclass(frozen=True)
562
- class HookSearchData:
563
- """Hook Search dataclass that use for receive regular expression grouping
564
- dict from searching hook string value.
565
- """
566
-
567
- path: str
568
- func: str
569
- tag: str
570
-
571
-
572
- def extract_hook(hook: str) -> Callable[[], TagFunc]:
573
- """Extract Hook function from string value to hook partial function that
574
- does run it at runtime.
575
-
576
- :raise NotImplementedError: When the searching hook's function result does
577
- not exist in the registry.
578
- :raise NotImplementedError: When the searching hook's tag result does not
579
- exists in the registry with its function key.
580
-
581
- :param hook: A hook value that able to match with Task regex.
582
- :rtype: Callable[[], TagFunc]
583
- """
584
- if not (found := Re.RE_TASK_FMT.search(hook)):
585
- raise ValueError(
586
- f"Hook {hook!r} does not match with hook format regex."
587
- )
588
-
589
- # NOTE: Pass the searching hook string to `path`, `func`, and `tag`.
590
- hook: HookSearchData = HookSearchData(**found.groupdict())
591
-
592
- # NOTE: Registry object should implement on this package only.
593
- rgt: dict[str, Registry] = make_registry(f"{hook.path}")
594
- if hook.func not in rgt:
595
- raise NotImplementedError(
596
- f"``REGISTER-MODULES.{hook.path}.registries`` does not "
597
- f"implement registry: {hook.func!r}."
598
- )
599
-
600
- if hook.tag not in rgt[hook.func]:
601
- raise NotImplementedError(
602
- f"tag: {hook.tag!r} does not found on registry func: "
603
- f"``REGISTER-MODULES.{hook.path}.registries.{hook.func}``"
604
- )
605
- return rgt[hook.func][hook.tag]
606
-
607
-
608
527
  class HookStage(BaseStage):
609
528
  """Hook executor that hook the Python function from registry with tag
610
529
  decorator function in ``utils`` module and run it with input arguments.
@@ -612,7 +531,7 @@ class HookStage(BaseStage):
612
531
  This stage is different with PyStage because the PyStage is just calling
613
532
  a Python statement with the ``eval`` and pass that locale before eval that
614
533
  statement. So, you can create your function complexly that you can for your
615
- propose to invoked by this stage object.
534
+ objective to invoked by this stage object.
616
535
 
617
536
  Data Validate:
618
537
  >>> stage = {
@@ -633,7 +552,6 @@ class HookStage(BaseStage):
633
552
  alias="with",
634
553
  )
635
554
 
636
- @handler_result()
637
555
  def execute(self, params: DictData, *, run_id: str | None = None) -> Result:
638
556
  """Execute the Hook function that already in the hook registry.
639
557
 
@@ -664,7 +582,7 @@ class HookStage(BaseStage):
664
582
  f"Necessary params, ({', '.join(ips.parameters.keys())}, ), "
665
583
  f"does not set to args"
666
584
  )
667
- # NOTE: add '_' prefix if it want to use.
585
+ # NOTE: add '_' prefix if it wants to use.
668
586
  for k in ips.parameters:
669
587
  if k.removeprefix("_") in args:
670
588
  args[k] = args.pop(k.removeprefix("_"))
@@ -686,7 +604,7 @@ class HookStage(BaseStage):
686
604
 
687
605
 
688
606
  class TriggerStage(BaseStage):
689
- """Trigger Workflow execution stage that execute another workflow. This this
607
+ """Trigger Workflow execution stage that execute another workflow. This
690
608
  the core stage that allow you to create the reusable workflow object or
691
609
  dynamic parameters workflow for common usecase.
692
610
 
@@ -708,9 +626,8 @@ class TriggerStage(BaseStage):
708
626
  description="A parameter that want to pass to workflow execution.",
709
627
  )
710
628
 
711
- @handler_result("Raise from TriggerStage")
712
629
  def execute(self, params: DictData, *, run_id: str | None = None) -> Result:
713
- """Trigger another workflow execution. It will waiting the trigger
630
+ """Trigger another workflow execution. It will wait the trigger
714
631
  workflow running complete before catching its result.
715
632
 
716
633
  :param params: A parameter data that want to use in this execution.
@@ -739,7 +656,7 @@ class TriggerStage(BaseStage):
739
656
  # NOTE:
740
657
  # An order of parsing stage model on the Job model with ``stages`` field.
741
658
  # From the current build-in stages, they do not have stage that have the same
742
- # fields that be cause of parsing on the Job's stages key.
659
+ # fields that because of parsing on the Job's stages key.
743
660
  #
744
661
  Stage = Union[
745
662
  PyStage,