ddeutil-workflow 0.0.57__py3-none-any.whl → 0.0.59__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.
@@ -141,8 +141,8 @@ class BaseStage(BaseModel, ABC):
141
141
  self,
142
142
  params: DictData,
143
143
  *,
144
- result: Result | None = None,
145
- event: Event | None = None,
144
+ result: Optional[Result] = None,
145
+ event: Optional[Event] = None,
146
146
  ) -> Result:
147
147
  """Execute abstraction method that action something by sub-model class.
148
148
  This is important method that make this class is able to be the stage.
@@ -162,12 +162,12 @@ class BaseStage(BaseModel, ABC):
162
162
  self,
163
163
  params: DictData,
164
164
  *,
165
- run_id: str | None = None,
166
- parent_run_id: str | None = None,
167
- result: Result | None = None,
168
- event: Event | None = None,
169
- raise_error: bool | None = None,
170
- ) -> Result | DictData:
165
+ run_id: Optional[str] = None,
166
+ parent_run_id: Optional[str] = None,
167
+ result: Optional[Result] = None,
168
+ event: Optional[Event] = None,
169
+ raise_error: Optional[bool] = None,
170
+ ) -> Union[Result, DictData]:
171
171
  """Handler stage execution result from the stage `execute` method.
172
172
 
173
173
  This stage exception handler still use ok-error concept, but it
@@ -376,8 +376,8 @@ class BaseAsyncStage(BaseStage):
376
376
  self,
377
377
  params: DictData,
378
378
  *,
379
- result: Result | None = None,
380
- event: Event | None = None,
379
+ result: Optional[Result] = None,
380
+ event: Optional[Event] = None,
381
381
  ) -> Result:
382
382
  raise NotImplementedError(
383
383
  "Async Stage should implement `execute` method."
@@ -388,8 +388,8 @@ class BaseAsyncStage(BaseStage):
388
388
  self,
389
389
  params: DictData,
390
390
  *,
391
- result: Result | None = None,
392
- event: Event | None = None,
391
+ result: Optional[Result] = None,
392
+ event: Optional[Event] = None,
393
393
  ) -> Result:
394
394
  """Async execution method for this Empty stage that only logging out to
395
395
  stdout.
@@ -411,11 +411,11 @@ class BaseAsyncStage(BaseStage):
411
411
  self,
412
412
  params: DictData,
413
413
  *,
414
- run_id: str | None = None,
415
- parent_run_id: str | None = None,
416
- result: Result | None = None,
417
- event: Event | None = None,
418
- raise_error: bool | None = None,
414
+ run_id: Optional[str] = None,
415
+ parent_run_id: Optional[str] = None,
416
+ result: Optional[Result] = None,
417
+ event: Optional[Event] = None,
418
+ raise_error: Optional[bool] = None,
419
419
  ) -> Result:
420
420
  """Async Handler stage execution result from the stage `execute` method.
421
421
 
@@ -487,8 +487,8 @@ class EmptyStage(BaseAsyncStage):
487
487
  self,
488
488
  params: DictData,
489
489
  *,
490
- result: Result | None = None,
491
- event: Event | None = None,
490
+ result: Optional[Result] = None,
491
+ event: Optional[Event] = None,
492
492
  ) -> Result:
493
493
  """Execution method for the Empty stage that do only logging out to
494
494
  stdout.
@@ -507,13 +507,13 @@ class EmptyStage(BaseAsyncStage):
507
507
  run_id=gen_id(self.name + (self.id or ""), unique=True),
508
508
  extras=self.extras,
509
509
  )
510
-
511
- if not self.echo:
512
- message: str = "..."
513
- else:
514
- message: str = param2template(
510
+ message: str = (
511
+ param2template(
515
512
  dedent(self.echo.strip("\n")), params, extras=self.extras
516
513
  )
514
+ if self.echo
515
+ else "..."
516
+ )
517
517
 
518
518
  result.trace.info(
519
519
  f"[STAGE]: Execute Empty-Stage: {self.name!r}: ( {message} )"
@@ -528,8 +528,8 @@ class EmptyStage(BaseAsyncStage):
528
528
  self,
529
529
  params: DictData,
530
530
  *,
531
- result: Result | None = None,
532
- event: Event | None = None,
531
+ result: Optional[Result] = None,
532
+ event: Optional[Event] = None,
533
533
  ) -> Result:
534
534
  """Async execution method for this Empty stage that only logging out to
535
535
  stdout.
@@ -546,12 +546,13 @@ class EmptyStage(BaseAsyncStage):
546
546
  extras=self.extras,
547
547
  )
548
548
 
549
- if not self.echo:
550
- message: str = "..."
551
- else:
552
- message: str = param2template(
549
+ message: str = (
550
+ param2template(
553
551
  dedent(self.echo.strip("\n")), params, extras=self.extras
554
552
  )
553
+ if self.echo
554
+ else "..."
555
+ )
555
556
 
556
557
  result.trace.info(f"[STAGE]: Empty-Stage: {self.name!r}: ( {message} )")
557
558
  if self.sleep > 0:
@@ -598,13 +599,13 @@ class BashStage(BaseAsyncStage):
598
599
 
599
600
  @contextlib.asynccontextmanager
600
601
  async def acreate_sh_file(
601
- self, bash: str, env: DictStr, run_id: str | None = None
602
+ self, bash: str, env: DictStr, run_id: Optional[str] = None
602
603
  ) -> AsyncIterator[TupleStr]:
603
604
  """Async create and write `.sh` file with the `aiofiles` package.
604
605
 
605
606
  :param bash: (str) A bash statement.
606
607
  :param env: (DictStr) An environment variable that set before run bash.
607
- :param run_id: (str | None) A running stage ID that use for writing sh
608
+ :param run_id: (Optional[str]) A running stage ID that use for writing sh
608
609
  file instead generate by UUID4.
609
610
 
610
611
  :rtype: AsyncIterator[TupleStr]
@@ -634,14 +635,14 @@ class BashStage(BaseAsyncStage):
634
635
 
635
636
  @contextlib.contextmanager
636
637
  def create_sh_file(
637
- self, bash: str, env: DictStr, run_id: str | None = None
638
+ self, bash: str, env: DictStr, run_id: Optional[str] = None
638
639
  ) -> Iterator[TupleStr]:
639
640
  """Create and write the `.sh` file before giving this file name to
640
641
  context. After that, it will auto delete this file automatic.
641
642
 
642
643
  :param bash: (str) A bash statement.
643
644
  :param env: (DictStr) An environment variable that set before run bash.
644
- :param run_id: (str | None) A running stage ID that use for writing sh
645
+ :param run_id: (Optional[str]) A running stage ID that use for writing sh
645
646
  file instead generate by UUID4.
646
647
 
647
648
  :rtype: Iterator[TupleStr]
@@ -672,8 +673,8 @@ class BashStage(BaseAsyncStage):
672
673
  self,
673
674
  params: DictData,
674
675
  *,
675
- result: Result | None = None,
676
- event: Event | None = None,
676
+ result: Optional[Result] = None,
677
+ event: Optional[Event] = None,
677
678
  ) -> Result:
678
679
  """Execute bash statement with the Python build-in `subprocess` package.
679
680
  It will catch result from the `subprocess.run` returning output like
@@ -729,8 +730,8 @@ class BashStage(BaseAsyncStage):
729
730
  self,
730
731
  params: DictData,
731
732
  *,
732
- result: Result | None = None,
733
- event: Event | None = None,
733
+ result: Optional[Result] = None,
734
+ event: Optional[Event] = None,
734
735
  ) -> Result:
735
736
  """Async execution method for this Bash stage that only logging out to
736
737
  stdout.
@@ -857,8 +858,8 @@ class PyStage(BaseAsyncStage):
857
858
  self,
858
859
  params: DictData,
859
860
  *,
860
- result: Result | None = None,
861
- event: Event | None = None,
861
+ result: Optional[Result] = None,
862
+ event: Optional[Event] = None,
862
863
  ) -> Result:
863
864
  """Execute the Python statement that pass all globals and input params
864
865
  to globals argument on `exec` build-in function.
@@ -915,8 +916,8 @@ class PyStage(BaseAsyncStage):
915
916
  self,
916
917
  params: DictData,
917
918
  *,
918
- result: Result | None = None,
919
- event: Event | None = None,
919
+ result: Optional[Result] = None,
920
+ event: Optional[Event] = None,
920
921
  ) -> Result:
921
922
  """Async execution method for this Bash stage that only logging out to
922
923
  stdout.
@@ -1017,8 +1018,8 @@ class CallStage(BaseAsyncStage):
1017
1018
  self,
1018
1019
  params: DictData,
1019
1020
  *,
1020
- result: Result | None = None,
1021
- event: Event | None = None,
1021
+ result: Optional[Result] = None,
1022
+ event: Optional[Event] = None,
1022
1023
  ) -> Result:
1023
1024
  """Execute this caller function with its argument parameter.
1024
1025
 
@@ -1107,8 +1108,8 @@ class CallStage(BaseAsyncStage):
1107
1108
  self,
1108
1109
  params: DictData,
1109
1110
  *,
1110
- result: Result | None = None,
1111
- event: Event | None = None,
1111
+ result: Optional[Result] = None,
1112
+ event: Optional[Event] = None,
1112
1113
  ) -> Result:
1113
1114
  """Async execution method for this Bash stage that only logging out to
1114
1115
  stdout.
@@ -1265,8 +1266,8 @@ class TriggerStage(BaseStage):
1265
1266
  self,
1266
1267
  params: DictData,
1267
1268
  *,
1268
- result: Result | None = None,
1269
- event: Event | None = None,
1269
+ result: Optional[Result] = None,
1270
+ event: Optional[Event] = None,
1270
1271
  ) -> Result:
1271
1272
  """Trigger another workflow execution. It will wait the trigger
1272
1273
  workflow running complete before catching its result.
@@ -1297,18 +1298,49 @@ class TriggerStage(BaseStage):
1297
1298
  event=event,
1298
1299
  )
1299
1300
  if rs.status == FAILED:
1300
- err_msg: str | None = (
1301
+ err_msg: Optional[str] = (
1301
1302
  f" with:\n{msg}"
1302
1303
  if (msg := rs.context.get("errors", {}).get("message"))
1303
1304
  else "."
1304
1305
  )
1305
1306
  raise StageException(
1306
- f"Trigger workflow return failed status{err_msg}"
1307
+ f"Trigger workflow return `FAILED` status{err_msg}"
1307
1308
  )
1308
1309
  return rs
1309
1310
 
1310
1311
 
1311
- class ParallelStage(BaseStage):
1312
+ class BaseNestedStage(BaseStage):
1313
+ """Base Nested Stage model. This model is use for checking the child stage
1314
+ is the nested stage or not.
1315
+ """
1316
+
1317
+ @abstractmethod
1318
+ def execute(
1319
+ self,
1320
+ params: DictData,
1321
+ *,
1322
+ result: Optional[Result] = None,
1323
+ event: Optional[Event] = None,
1324
+ ) -> Result:
1325
+ """Execute abstraction method that action something by sub-model class.
1326
+ This is important method that make this class is able to be the nested
1327
+ stage.
1328
+
1329
+ :param params: (DictData) A parameter data that want to use in this
1330
+ execution.
1331
+ :param result: (Result) A result object for keeping context and status
1332
+ data.
1333
+ :param event: (Event) An event manager that use to track parent execute
1334
+ was not force stopped.
1335
+
1336
+ :rtype: Result
1337
+ """
1338
+ raise NotImplementedError(
1339
+ "Nested-Stage should implement `execute` method."
1340
+ )
1341
+
1342
+
1343
+ class ParallelStage(BaseNestedStage):
1312
1344
  """Parallel stage executor that execute branch stages with multithreading.
1313
1345
  This stage let you set the fix branches for running child stage inside it on
1314
1346
  multithread pool.
@@ -1358,7 +1390,7 @@ class ParallelStage(BaseStage):
1358
1390
  params: DictData,
1359
1391
  result: Result,
1360
1392
  *,
1361
- event: Event | None = None,
1393
+ event: Optional[Event] = None,
1362
1394
  ) -> Result:
1363
1395
  """Execute all stage with specific branch ID.
1364
1396
 
@@ -1455,8 +1487,8 @@ class ParallelStage(BaseStage):
1455
1487
  self,
1456
1488
  params: DictData,
1457
1489
  *,
1458
- result: Result | None = None,
1459
- event: Event | None = None,
1490
+ result: Optional[Result] = None,
1491
+ event: Optional[Event] = None,
1460
1492
  ) -> Result:
1461
1493
  """Execute parallel each branch via multi-threading pool.
1462
1494
 
@@ -1494,7 +1526,7 @@ class ParallelStage(BaseStage):
1494
1526
  context: DictData = {}
1495
1527
  status: Status = SUCCESS
1496
1528
 
1497
- futures: list[Future] = (
1529
+ futures: list[Future] = [
1498
1530
  executor.submit(
1499
1531
  self.execute_branch,
1500
1532
  branch=branch,
@@ -1503,26 +1535,21 @@ class ParallelStage(BaseStage):
1503
1535
  event=event,
1504
1536
  )
1505
1537
  for branch in self.parallel
1506
- )
1538
+ ]
1507
1539
 
1508
1540
  for future in as_completed(futures):
1509
1541
  try:
1510
1542
  future.result()
1511
1543
  except StageException as e:
1512
1544
  status = FAILED
1513
- result.trace.error(
1514
- f"[STAGE]: Error Handler:||{e.__class__.__name__}:||{e}"
1515
- )
1516
1545
  if "errors" in context:
1517
1546
  context["errors"][e.refs] = e.to_dict()
1518
1547
  else:
1519
1548
  context["errors"] = e.to_dict(with_refs=True)
1520
- except CancelledError:
1521
- pass
1522
1549
  return result.catch(status=status, context=context)
1523
1550
 
1524
1551
 
1525
- class ForEachStage(BaseStage):
1552
+ class ForEachStage(BaseNestedStage):
1526
1553
  """For-Each stage executor that execute all stages with each item in the
1527
1554
  foreach list.
1528
1555
 
@@ -1563,18 +1590,27 @@ class ForEachStage(BaseStage):
1563
1590
  "will be sequential mode if this value equal 1."
1564
1591
  ),
1565
1592
  )
1593
+ use_index_as_key: bool = Field(
1594
+ default=False,
1595
+ description=(
1596
+ "A flag for using the loop index as a key instead item value. "
1597
+ "This flag allow to skip checking duplicate item step."
1598
+ ),
1599
+ )
1566
1600
 
1567
1601
  def execute_item(
1568
1602
  self,
1603
+ index: int,
1569
1604
  item: StrOrInt,
1570
1605
  params: DictData,
1571
1606
  result: Result,
1572
1607
  *,
1573
- event: Event | None = None,
1608
+ event: Optional[Event] = None,
1574
1609
  ) -> Result:
1575
1610
  """Execute all nested stage that set on this stage with specific foreach
1576
1611
  item parameter.
1577
1612
 
1613
+ :param index: (int) An index value of foreach loop.
1578
1614
  :param item: (str | int) An item that want to execution.
1579
1615
  :param params: (DictData) A parameter data.
1580
1616
  :param result: (Result) A Result instance for return context and status.
@@ -1588,8 +1624,9 @@ class ForEachStage(BaseStage):
1588
1624
  :rtype: Result
1589
1625
  """
1590
1626
  result.trace.debug(f"[STAGE]: Execute Item: {item!r}")
1627
+ key: StrOrInt = index if self.use_index_as_key else item
1591
1628
  context: DictData = copy.deepcopy(params)
1592
- context.update({"item": item})
1629
+ context.update({"item": item, "loop": index})
1593
1630
  output: DictData = {"item": item, "stages": {}}
1594
1631
  for stage in self.stages:
1595
1632
 
@@ -1608,14 +1645,14 @@ class ForEachStage(BaseStage):
1608
1645
  result.catch(
1609
1646
  status=CANCEL,
1610
1647
  foreach={
1611
- item: {
1648
+ key: {
1612
1649
  "item": item,
1613
1650
  "stages": filter_func(output.pop("stages", {})),
1614
1651
  "errors": StageException(error_msg).to_dict(),
1615
1652
  }
1616
1653
  },
1617
1654
  )
1618
- raise StageException(error_msg, refs=item)
1655
+ raise StageException(error_msg, refs=key)
1619
1656
 
1620
1657
  try:
1621
1658
  rs: Result = stage.handler_execute(
@@ -1631,14 +1668,14 @@ class ForEachStage(BaseStage):
1631
1668
  result.catch(
1632
1669
  status=FAILED,
1633
1670
  foreach={
1634
- item: {
1671
+ key: {
1635
1672
  "item": item,
1636
1673
  "stages": filter_func(output.pop("stages", {})),
1637
1674
  "errors": e.to_dict(),
1638
1675
  },
1639
1676
  },
1640
1677
  )
1641
- raise StageException(str(e), refs=item) from e
1678
+ raise StageException(str(e), refs=key) from e
1642
1679
 
1643
1680
  if rs.status == FAILED:
1644
1681
  error_msg: str = (
@@ -1649,19 +1686,19 @@ class ForEachStage(BaseStage):
1649
1686
  result.catch(
1650
1687
  status=FAILED,
1651
1688
  foreach={
1652
- item: {
1689
+ key: {
1653
1690
  "item": item,
1654
1691
  "stages": filter_func(output.pop("stages", {})),
1655
1692
  "errors": StageException(error_msg).to_dict(),
1656
1693
  },
1657
1694
  },
1658
1695
  )
1659
- raise StageException(error_msg, refs=item)
1696
+ raise StageException(error_msg, refs=key)
1660
1697
 
1661
1698
  return result.catch(
1662
1699
  status=SUCCESS,
1663
1700
  foreach={
1664
- item: {
1701
+ key: {
1665
1702
  "item": item,
1666
1703
  "stages": filter_func(output.pop("stages", {})),
1667
1704
  },
@@ -1672,8 +1709,8 @@ class ForEachStage(BaseStage):
1672
1709
  self,
1673
1710
  params: DictData,
1674
1711
  *,
1675
- result: Result | None = None,
1676
- event: Event | None = None,
1712
+ result: Optional[Result] = None,
1713
+ event: Optional[Event] = None,
1677
1714
  ) -> Result:
1678
1715
  """Execute the stages that pass each item form the foreach field.
1679
1716
 
@@ -1700,6 +1737,11 @@ class ForEachStage(BaseStage):
1700
1737
  # [VALIDATE]: Type of the foreach should be `list` type.
1701
1738
  if not isinstance(foreach, list):
1702
1739
  raise TypeError(f"Does not support foreach: {foreach!r}")
1740
+ elif len(set(foreach)) != len(foreach) and not self.use_index_as_key:
1741
+ raise ValueError(
1742
+ "Foreach item should not duplicate. If this stage must to pass "
1743
+ "duplicate item, it should set `use_index_as_key: true`."
1744
+ )
1703
1745
 
1704
1746
  result.trace.info(f"[STAGE]: Execute Foreach-Stage: {foreach!r}.")
1705
1747
  result.catch(status=WAIT, context={"items": foreach, "foreach": {}})
@@ -1721,18 +1763,19 @@ class ForEachStage(BaseStage):
1721
1763
  futures: list[Future] = [
1722
1764
  executor.submit(
1723
1765
  self.execute_item,
1766
+ index=i,
1724
1767
  item=item,
1725
1768
  params=params,
1726
1769
  result=result,
1727
1770
  event=event,
1728
1771
  )
1729
- for item in foreach
1772
+ for i, item in enumerate(foreach, start=0)
1730
1773
  ]
1731
1774
  context: DictData = {}
1732
1775
  status: Status = SUCCESS
1733
1776
 
1734
1777
  done, not_done = wait(futures, return_when=FIRST_EXCEPTION)
1735
- if len(done) != len(futures):
1778
+ if len(list(done)) != len(futures):
1736
1779
  result.trace.warning(
1737
1780
  "[STAGE]: Set event for stop pending for-each stage."
1738
1781
  )
@@ -1741,20 +1784,24 @@ class ForEachStage(BaseStage):
1741
1784
  future.cancel()
1742
1785
  time.sleep(0.075)
1743
1786
 
1744
- nd: str = f", item not run: {not_done}" if not_done else ""
1787
+ nd: str = (
1788
+ (
1789
+ f", {len(not_done)} item"
1790
+ f"{'s' if len(not_done) > 1 else ''} not run!!!"
1791
+ )
1792
+ if not_done
1793
+ else ""
1794
+ )
1745
1795
  result.trace.debug(
1746
1796
  f"[STAGE]: ... Foreach-Stage set failed event{nd}"
1747
1797
  )
1748
- done: list[Future] = as_completed(futures)
1798
+ done: Iterator[Future] = as_completed(futures)
1749
1799
 
1750
1800
  for future in done:
1751
1801
  try:
1752
1802
  future.result()
1753
1803
  except StageException as e:
1754
1804
  status = FAILED
1755
- result.trace.error(
1756
- f"[STAGE]: Error Handler:||{e.__class__.__name__}:||{e}"
1757
- )
1758
1805
  if "errors" in context:
1759
1806
  context["errors"][e.refs] = e.to_dict()
1760
1807
  else:
@@ -1764,7 +1811,7 @@ class ForEachStage(BaseStage):
1764
1811
  return result.catch(status=status, context=context)
1765
1812
 
1766
1813
 
1767
- class UntilStage(BaseStage):
1814
+ class UntilStage(BaseNestedStage):
1768
1815
  """Until stage executor that will run stages in each loop until it valid
1769
1816
  with stop loop condition.
1770
1817
 
@@ -1815,7 +1862,7 @@ class UntilStage(BaseStage):
1815
1862
  loop: int,
1816
1863
  params: DictData,
1817
1864
  result: Result,
1818
- event: Event | None = None,
1865
+ event: Optional[Event] = None,
1819
1866
  ) -> tuple[Result, T]:
1820
1867
  """Execute all stage with specific loop and item.
1821
1868
 
@@ -1928,8 +1975,8 @@ class UntilStage(BaseStage):
1928
1975
  self,
1929
1976
  params: DictData,
1930
1977
  *,
1931
- result: Result | None = None,
1932
- event: Event | None = None,
1978
+ result: Optional[Result] = None,
1979
+ event: Optional[Event] = None,
1933
1980
  ) -> Result:
1934
1981
  """Execute until loop with checking until condition.
1935
1982
 
@@ -2015,7 +2062,7 @@ class Match(BaseModel):
2015
2062
  )
2016
2063
 
2017
2064
 
2018
- class CaseStage(BaseStage):
2065
+ class CaseStage(BaseNestedStage):
2019
2066
  """Case stage executor that execute all stages if the condition was matched.
2020
2067
 
2021
2068
  Data Validate:
@@ -2066,7 +2113,7 @@ class CaseStage(BaseStage):
2066
2113
  params: DictData,
2067
2114
  result: Result,
2068
2115
  *,
2069
- event: Event | None = None,
2116
+ event: Optional[Event] = None,
2070
2117
  ) -> Result:
2071
2118
  """Execute case.
2072
2119
 
@@ -2151,8 +2198,8 @@ class CaseStage(BaseStage):
2151
2198
  self,
2152
2199
  params: DictData,
2153
2200
  *,
2154
- result: Result | None = None,
2155
- event: Event | None = None,
2201
+ result: Optional[Result] = None,
2202
+ event: Optional[Event] = None,
2156
2203
  ) -> Result:
2157
2204
  """Execute case-match condition that pass to the case field.
2158
2205
 
@@ -2244,8 +2291,8 @@ class RaiseStage(BaseAsyncStage):
2244
2291
  self,
2245
2292
  params: DictData,
2246
2293
  *,
2247
- result: Result | None = None,
2248
- event: Event | None = None,
2294
+ result: Optional[Result] = None,
2295
+ event: Optional[Event] = None,
2249
2296
  ) -> Result:
2250
2297
  """Raise the StageException object with the message field execution.
2251
2298
 
@@ -2259,15 +2306,15 @@ class RaiseStage(BaseAsyncStage):
2259
2306
  extras=self.extras,
2260
2307
  )
2261
2308
  message: str = param2template(self.message, params, extras=self.extras)
2262
- result.trace.info(f"[STAGE]: Execute Raise-Stage: {message!r}.")
2309
+ result.trace.info(f"[STAGE]: Execute Raise-Stage: ( {message} )")
2263
2310
  raise StageException(message)
2264
2311
 
2265
2312
  async def axecute(
2266
2313
  self,
2267
2314
  params: DictData,
2268
2315
  *,
2269
- result: Result | None = None,
2270
- event: Event | None = None,
2316
+ result: Optional[Result] = None,
2317
+ event: Optional[Event] = None,
2271
2318
  ) -> Result:
2272
2319
  """Async execution method for this Empty stage that only logging out to
2273
2320
  stdout.
@@ -2286,7 +2333,7 @@ class RaiseStage(BaseAsyncStage):
2286
2333
  extras=self.extras,
2287
2334
  )
2288
2335
  message: str = param2template(self.message, params, extras=self.extras)
2289
- await result.trace.ainfo(f"[STAGE]: Execute Raise-Stage: {message!r}.")
2336
+ await result.trace.ainfo(f"[STAGE]: Execute Raise-Stage: ( {message} )")
2290
2337
  raise StageException(message)
2291
2338
 
2292
2339
 
@@ -2320,7 +2367,7 @@ class DockerStage(BaseStage): # pragma: no cov
2320
2367
  env: DictData = Field(
2321
2368
  default_factory=dict,
2322
2369
  description=(
2323
- "An environment variable that want pass to Docker container.",
2370
+ "An environment variable that want pass to Docker container."
2324
2371
  ),
2325
2372
  )
2326
2373
  volume: DictData = Field(
@@ -2338,7 +2385,7 @@ class DockerStage(BaseStage): # pragma: no cov
2338
2385
  self,
2339
2386
  params: DictData,
2340
2387
  result: Result,
2341
- event: Event | None = None,
2388
+ event: Optional[Event] = None,
2342
2389
  ) -> Result:
2343
2390
  """Execute Docker container task.
2344
2391
 
@@ -2426,8 +2473,8 @@ class DockerStage(BaseStage): # pragma: no cov
2426
2473
  self,
2427
2474
  params: DictData,
2428
2475
  *,
2429
- result: Result | None = None,
2430
- event: Event | None = None,
2476
+ result: Optional[Result] = None,
2477
+ event: Optional[Event] = None,
2431
2478
  ) -> Result:
2432
2479
  """Execute the Docker image via Python API.
2433
2480
 
@@ -2471,7 +2518,7 @@ class VirtualPyStage(PyStage): # pragma: no cov
2471
2518
  py: str,
2472
2519
  values: DictData,
2473
2520
  deps: list[str],
2474
- run_id: str | None = None,
2521
+ run_id: Optional[str] = None,
2475
2522
  ) -> Iterator[str]:
2476
2523
  """Create the .py file with an input Python string statement.
2477
2524
 
@@ -2479,7 +2526,7 @@ class VirtualPyStage(PyStage): # pragma: no cov
2479
2526
  :param values: A variable that want to set before running this
2480
2527
  :param deps: An additional Python dependencies that want install before
2481
2528
  run this python stage.
2482
- :param run_id: (str | None) A running ID of this stage execution.
2529
+ :param run_id: (Optional[str]) A running ID of this stage execution.
2483
2530
  """
2484
2531
  run_id: str = run_id or uuid.uuid4()
2485
2532
  f_name: str = f"{run_id}.py"
@@ -2518,8 +2565,8 @@ class VirtualPyStage(PyStage): # pragma: no cov
2518
2565
  self,
2519
2566
  params: DictData,
2520
2567
  *,
2521
- result: Result | None = None,
2522
- event: Event | None = None,
2568
+ result: Optional[Result] = None,
2569
+ event: Optional[Event] = None,
2523
2570
  ) -> Result:
2524
2571
  """Execute the Python statement via Python virtual environment.
2525
2572