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.
@@ -194,9 +194,8 @@ class BaseStage(BaseModel, ABC):
194
194
  object from the current stage ID before release the final result.
195
195
 
196
196
  :param params: (DictData) A parameter data.
197
- :param run_id: (str) A running stage ID for this execution.
198
- :param parent_run_id: (str) A parent workflow running ID for this
199
- execution.
197
+ :param run_id: (str) A running stage ID.
198
+ :param parent_run_id: (str) A parent running ID.
200
199
  :param result: (Result) A result object for keeping context and status
201
200
  data before execution.
202
201
  :param event: (Event) An event manager that pass to the stage execution.
@@ -213,19 +212,16 @@ class BaseStage(BaseModel, ABC):
213
212
  )
214
213
 
215
214
  try:
216
- rs: Result = self.execute(params, result=result, event=event)
217
- return rs
215
+ return self.execute(params, result=result, event=event)
218
216
  except Exception as e:
219
- result.trace.error(
220
- f"[STAGE]: Handler:{NEWLINE}{e.__class__.__name__}: {e}"
221
- )
217
+ e_name: str = e.__class__.__name__
218
+ result.trace.error(f"[STAGE]: Handler:{NEWLINE}{e_name}: {e}")
222
219
  if dynamic("stage_raise_error", f=raise_error, extras=self.extras):
223
220
  if isinstance(e, StageException):
224
221
  raise
225
222
 
226
223
  raise StageException(
227
- f"{self.__class__.__name__}: \n\t"
228
- f"{e.__class__.__name__}: {e}"
224
+ f"{self.__class__.__name__}: {NEWLINE}{e_name}: {e}"
229
225
  ) from e
230
226
 
231
227
  return result.catch(status=FAILED, context={"errors": to_dict(e)})
@@ -252,6 +248,11 @@ class BaseStage(BaseModel, ABC):
252
248
  }
253
249
  }
254
250
 
251
+ The keys that will set to the received context is `outputs`,
252
+ `errors`, and `skipped` keys. The `errors` and `skipped` keys will
253
+ extract from the result context if it exists. If it does not found, it
254
+ will not set on the received context.
255
+
255
256
  Important:
256
257
 
257
258
  This method is use for reconstruct the result context and transfer
@@ -431,17 +432,14 @@ class BaseAsyncStage(BaseStage):
431
432
  rs: Result = await self.axecute(params, result=result, event=event)
432
433
  return rs
433
434
  except Exception as e: # pragma: no cov
434
- await result.trace.aerror(
435
- f"[STAGE]: Handler {e.__class__.__name__}: {e}"
436
- )
437
-
435
+ e_name: str = e.__class__.__name__
436
+ await result.trace.aerror(f"[STAGE]: Handler {e_name}: {e}")
438
437
  if dynamic("stage_raise_error", f=raise_error, extras=self.extras):
439
438
  if isinstance(e, StageException):
440
439
  raise
441
440
 
442
441
  raise StageException(
443
- f"{self.__class__.__name__}: \n\t"
444
- f"{e.__class__.__name__}: {e}"
442
+ f"{self.__class__.__name__}: {NEWLINE}{e_name}: {e}"
445
443
  ) from None
446
444
 
447
445
  return result.catch(status=FAILED, context={"errors": to_dict(e)})
@@ -537,11 +535,10 @@ class EmptyStage(BaseAsyncStage):
537
535
 
538
536
  :rtype: Result
539
537
  """
540
- if result is None:
541
- result: Result = Result(
542
- run_id=gen_id(self.name + (self.id or ""), unique=True),
543
- extras=self.extras,
544
- )
538
+ result: Result = result or Result(
539
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
540
+ extras=self.extras,
541
+ )
545
542
 
546
543
  if not self.echo:
547
544
  message: str = "..."
@@ -678,11 +675,10 @@ class BashStage(BaseStage):
678
675
 
679
676
  :rtype: Result
680
677
  """
681
- if result is None: # pragma: no cov
682
- result: Result = Result(
683
- run_id=gen_id(self.name + (self.id or ""), unique=True),
684
- extras=self.extras,
685
- )
678
+ result: Result = result or Result(
679
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
680
+ extras=self.extras,
681
+ )
686
682
 
687
683
  result.trace.info(f"[STAGE]: Shell-Execute: {self.name}")
688
684
 
@@ -811,11 +807,10 @@ class PyStage(BaseStage):
811
807
 
812
808
  :rtype: Result
813
809
  """
814
- if result is None: # pragma: no cov
815
- result: Result = Result(
816
- run_id=gen_id(self.name + (self.id or ""), unique=True),
817
- extras=self.extras,
818
- )
810
+ result: Result = result or Result(
811
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
812
+ extras=self.extras,
813
+ )
819
814
 
820
815
  lc: DictData = {}
821
816
  gb: DictData = (
@@ -927,11 +922,10 @@ class CallStage(BaseStage):
927
922
 
928
923
  :rtype: Result
929
924
  """
930
- if result is None: # pragma: no cov
931
- result: Result = Result(
932
- run_id=gen_id(self.name + (self.id or ""), unique=True),
933
- extras=self.extras,
934
- )
925
+ result: Result = result or Result(
926
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
927
+ extras=self.extras,
928
+ )
935
929
 
936
930
  call_func: TagFunc = extract_call(
937
931
  param2template(self.uses, params, extras=self.extras),
@@ -1087,11 +1081,10 @@ class TriggerStage(BaseStage):
1087
1081
  from .exceptions import WorkflowException
1088
1082
  from .workflow import Workflow
1089
1083
 
1090
- if result is None:
1091
- result: Result = Result(
1092
- run_id=gen_id(self.name + (self.id or ""), unique=True),
1093
- extras=self.extras,
1094
- )
1084
+ result: Result = result or Result(
1085
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
1086
+ extras=self.extras,
1087
+ )
1095
1088
 
1096
1089
  _trigger: str = param2template(self.trigger, params, extras=self.extras)
1097
1090
  result.trace.info(f"[STAGE]: Trigger-Execute: {_trigger!r}")
@@ -1121,10 +1114,10 @@ class TriggerStage(BaseStage):
1121
1114
 
1122
1115
  class ParallelStage(BaseStage): # pragma: no cov
1123
1116
  """Parallel stage executor that execute branch stages with multithreading.
1124
- This stage let you set the fix branches for running substage inside it on
1117
+ This stage let you set the fix branches for running child stage inside it on
1125
1118
  multithread pool.
1126
1119
 
1127
- This stage is not the low-level stage model because it runs muti-stages
1120
+ This stage is not the low-level stage model because it runs multi-stages
1128
1121
  in this stage execution.
1129
1122
 
1130
1123
  Data Validate:
@@ -1170,9 +1163,8 @@ class ParallelStage(BaseStage): # pragma: no cov
1170
1163
  result: Result,
1171
1164
  *,
1172
1165
  event: Event | None = None,
1173
- ) -> DictData:
1174
- """Branch execution method for execute all stages of a specific branch
1175
- ID.
1166
+ ) -> Result:
1167
+ """Execute all stage with specific branch ID.
1176
1168
 
1177
1169
  :param branch: (str) A branch ID.
1178
1170
  :param params: (DictData) A parameter data.
@@ -1180,7 +1172,7 @@ class ParallelStage(BaseStage): # pragma: no cov
1180
1172
  :param event: (Event) An Event manager instance that use to cancel this
1181
1173
  execution if it forces stopped by parent execution.
1182
1174
 
1183
- :rtype: DictData
1175
+ :rtype: Result
1184
1176
  """
1185
1177
  result.trace.debug(f"[STAGE]: Execute Branch: {branch!r}")
1186
1178
  context: DictData = copy.deepcopy(params)
@@ -1192,14 +1184,14 @@ class ParallelStage(BaseStage): # pragma: no cov
1192
1184
  stage.extras = self.extras
1193
1185
 
1194
1186
  if stage.is_skipped(params=context):
1195
- result.trace.info(f"... Skip stage: {stage.iden!r}")
1187
+ result.trace.info(f"[STAGE]: Skip stage: {stage.iden!r}")
1196
1188
  stage.set_outputs(output={"skipped": True}, to=output)
1197
1189
  continue
1198
1190
 
1199
1191
  if event and event.is_set():
1200
1192
  error_msg: str = (
1201
1193
  "Branch-Stage was canceled from event that had set before "
1202
- "stage item execution."
1194
+ "stage branch execution."
1203
1195
  )
1204
1196
  return result.catch(
1205
1197
  status=CANCEL,
@@ -1223,9 +1215,21 @@ class ParallelStage(BaseStage): # pragma: no cov
1223
1215
  stage.set_outputs(rs.context, to=output)
1224
1216
  stage.set_outputs(stage.get_outputs(output), to=context)
1225
1217
  except (StageException, UtilException) as e: # pragma: no cov
1226
- result.trace.error(f"[STAGE]: {e.__class__.__name__}: {e}")
1218
+ result.trace.error(
1219
+ f"[STAGE]: {e.__class__.__name__}:{NEWLINE}{e}"
1220
+ )
1221
+ result.catch(
1222
+ status=FAILED,
1223
+ parallel={
1224
+ branch: {
1225
+ "branch": branch,
1226
+ "stages": filter_func(output.pop("stages", {})),
1227
+ "errors": e.to_dict(),
1228
+ },
1229
+ },
1230
+ )
1227
1231
  raise StageException(
1228
- f"Sub-Stage execution error: {e.__class__.__name__}: {e}"
1232
+ f"Sub-Stage raise: {e.__class__.__name__}: {e}"
1229
1233
  ) from None
1230
1234
 
1231
1235
  if rs.status == FAILED:
@@ -1233,7 +1237,7 @@ class ParallelStage(BaseStage): # pragma: no cov
1233
1237
  f"Branch-Stage was break because it has a sub stage, "
1234
1238
  f"{stage.iden}, failed without raise error."
1235
1239
  )
1236
- return result.catch(
1240
+ result.catch(
1237
1241
  status=FAILED,
1238
1242
  parallel={
1239
1243
  branch: {
@@ -1243,6 +1247,7 @@ class ParallelStage(BaseStage): # pragma: no cov
1243
1247
  },
1244
1248
  },
1245
1249
  )
1250
+ raise StageException(error_msg)
1246
1251
 
1247
1252
  return result.catch(
1248
1253
  status=SUCCESS,
@@ -1270,19 +1275,28 @@ class ParallelStage(BaseStage): # pragma: no cov
1270
1275
 
1271
1276
  :rtype: Result
1272
1277
  """
1273
- if result is None: # pragma: no cov
1274
- result: Result = Result(
1275
- run_id=gen_id(self.name + (self.id or ""), unique=True),
1276
- extras=self.extras,
1277
- )
1278
+ result: Result = result or Result(
1279
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
1280
+ extras=self.extras,
1281
+ )
1278
1282
  event: Event = Event() if event is None else event
1279
1283
  result.trace.info(
1280
1284
  f"[STAGE]: Parallel-Execute: {self.max_workers} workers."
1281
1285
  )
1282
1286
  result.catch(status=WAIT, context={"parallel": {}})
1287
+ if event and event.is_set(): # pragma: no cov
1288
+ return result.catch(
1289
+ status=CANCEL,
1290
+ context={
1291
+ "errors": StageException(
1292
+ "Stage was canceled from event that had set "
1293
+ "before stage parallel execution."
1294
+ ).to_dict()
1295
+ },
1296
+ )
1297
+
1283
1298
  with ThreadPoolExecutor(
1284
- max_workers=self.max_workers,
1285
- thread_name_prefix="parallel_stage_exec_",
1299
+ max_workers=self.max_workers, thread_name_prefix="stage_parallel_"
1286
1300
  ) as executor:
1287
1301
 
1288
1302
  context: DictData = {}
@@ -1299,17 +1313,18 @@ class ParallelStage(BaseStage): # pragma: no cov
1299
1313
  for branch in self.parallel
1300
1314
  )
1301
1315
 
1302
- done = as_completed(futures, timeout=1800)
1303
- for future in done:
1316
+ for future in as_completed(futures):
1304
1317
  try:
1305
1318
  future.result()
1306
1319
  except StageException as e:
1307
1320
  status = FAILED
1308
1321
  result.trace.error(
1309
- f"[STAGE]: {e.__class__.__name__}:\n\t{e}"
1322
+ f"[STAGE]: {e.__class__.__name__}:{NEWLINE}{e}"
1310
1323
  )
1311
- context.update({"errors": e.to_dict()})
1312
-
1324
+ if "errors" in context:
1325
+ context["errors"].append(e.to_dict())
1326
+ else:
1327
+ context["errors"] = [e.to_dict()]
1313
1328
  return result.catch(status=status, context=context)
1314
1329
 
1315
1330
 
@@ -1318,7 +1333,7 @@ class ForEachStage(BaseStage):
1318
1333
  foreach list.
1319
1334
 
1320
1335
  This stage is not the low-level stage model because it runs
1321
- muti-stages in this stage execution.
1336
+ multi-stages in this stage execution.
1322
1337
 
1323
1338
  Data Validate:
1324
1339
  >>> stage = {
@@ -1363,7 +1378,7 @@ class ForEachStage(BaseStage):
1363
1378
  *,
1364
1379
  event: Event | None = None,
1365
1380
  ) -> Result:
1366
- """Execute foreach item from list of item.
1381
+ """Execute all stage with specific foreach item.
1367
1382
 
1368
1383
  :param item: (str | int) An item that want to execution.
1369
1384
  :param params: (DictData) A parameter data.
@@ -1385,7 +1400,7 @@ class ForEachStage(BaseStage):
1385
1400
  stage.extras = self.extras
1386
1401
 
1387
1402
  if stage.is_skipped(params=context):
1388
- result.trace.info(f"... Skip stage: {stage.iden!r}")
1403
+ result.trace.info(f"[STAGE]: Skip stage: {stage.iden!r}")
1389
1404
  stage.set_outputs(output={"skipped": True}, to=output)
1390
1405
  continue
1391
1406
 
@@ -1416,7 +1431,9 @@ class ForEachStage(BaseStage):
1416
1431
  stage.set_outputs(rs.context, to=output)
1417
1432
  stage.set_outputs(stage.get_outputs(output), to=context)
1418
1433
  except (StageException, UtilException) as e:
1419
- result.trace.error(f"[STAGE]: {e.__class__.__name__}: {e}")
1434
+ result.trace.error(
1435
+ f"[STAGE]: {e.__class__.__name__}:{NEWLINE}{e}"
1436
+ )
1420
1437
  result.catch(
1421
1438
  status=FAILED,
1422
1439
  foreach={
@@ -1436,7 +1453,8 @@ class ForEachStage(BaseStage):
1436
1453
  f"Item-Stage was break because it has a sub stage, "
1437
1454
  f"{stage.iden}, failed without raise error."
1438
1455
  )
1439
- return result.catch(
1456
+ result.trace.warning(f"[STAGE]: {error_msg}")
1457
+ result.catch(
1440
1458
  status=FAILED,
1441
1459
  foreach={
1442
1460
  item: {
@@ -1446,6 +1464,8 @@ class ForEachStage(BaseStage):
1446
1464
  },
1447
1465
  },
1448
1466
  )
1467
+ raise StageException(error_msg)
1468
+
1449
1469
  return result.catch(
1450
1470
  status=SUCCESS,
1451
1471
  foreach={
@@ -1470,21 +1490,24 @@ class ForEachStage(BaseStage):
1470
1490
  :param event: (Event) An Event manager instance that use to cancel this
1471
1491
  execution if it forces stopped by parent execution.
1472
1492
 
1493
+ :raise TypeError: If the foreach does not match with type list.
1494
+
1473
1495
  :rtype: Result
1474
1496
  """
1475
- if result is None: # pragma: no cov
1476
- result: Result = Result(
1477
- run_id=gen_id(self.name + (self.id or ""), unique=True),
1478
- extras=self.extras,
1479
- )
1497
+ result: Result = result or Result(
1498
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
1499
+ extras=self.extras,
1500
+ )
1480
1501
  event: Event = Event() if event is None else event
1481
1502
  foreach: Union[list[str], list[int]] = (
1482
1503
  param2template(self.foreach, params, extras=self.extras)
1483
1504
  if isinstance(self.foreach, str)
1484
1505
  else self.foreach
1485
1506
  )
1507
+
1508
+ # [VALIDATE]: Type of the foreach should be `list` type.
1486
1509
  if not isinstance(foreach, list):
1487
- raise StageException(f"Does not support foreach: {foreach!r}")
1510
+ raise TypeError(f"Does not support foreach: {foreach!r}")
1488
1511
 
1489
1512
  result.trace.info(f"[STAGE]: Foreach-Execute: {foreach!r}.")
1490
1513
  result.catch(status=WAIT, context={"items": foreach, "foreach": {}})
@@ -1531,7 +1554,7 @@ class ForEachStage(BaseStage):
1531
1554
  for future in done:
1532
1555
  try:
1533
1556
  future.result()
1534
- except (StageException, UtilException) as e:
1557
+ except StageException as e:
1535
1558
  status = FAILED
1536
1559
  result.trace.error(
1537
1560
  f"[STAGE]: {e.__class__.__name__}:{NEWLINE}{e}"
@@ -1544,6 +1567,9 @@ class UntilStage(BaseStage):
1544
1567
  """Until stage executor that will run stages in each loop until it valid
1545
1568
  with stop loop condition.
1546
1569
 
1570
+ This stage is not the low-level stage model because it runs
1571
+ multi-stages in this stage execution.
1572
+
1547
1573
  Data Validate:
1548
1574
  >>> stage = {
1549
1575
  ... "name": "Until stage execution",
@@ -1582,7 +1608,7 @@ class UntilStage(BaseStage):
1582
1608
  alias="max-loop",
1583
1609
  )
1584
1610
 
1585
- def execute_item(
1611
+ def execute_loop(
1586
1612
  self,
1587
1613
  item: T,
1588
1614
  loop: int,
@@ -1590,8 +1616,7 @@ class UntilStage(BaseStage):
1590
1616
  result: Result,
1591
1617
  event: Event | None = None,
1592
1618
  ) -> tuple[Result, T]:
1593
- """Execute loop item that was set from some stage or set by default loop
1594
- variable.
1619
+ """Execute all stage with specific loop and item.
1595
1620
 
1596
1621
  :param item: (T) An item that want to execution.
1597
1622
  :param loop: (int) A number of loop.
@@ -1601,6 +1626,7 @@ class UntilStage(BaseStage):
1601
1626
  execution if it forces stopped by parent execution.
1602
1627
 
1603
1628
  :rtype: tuple[Result, T]
1629
+ :return: Return a pair of Result and changed item.
1604
1630
  """
1605
1631
  result.trace.debug(f"... Execute until item: {item!r}")
1606
1632
  context: DictData = copy.deepcopy(params)
@@ -1613,14 +1639,14 @@ class UntilStage(BaseStage):
1613
1639
  stage.extras = self.extras
1614
1640
 
1615
1641
  if stage.is_skipped(params=context):
1616
- result.trace.info(f"... Skip stage: {stage.iden!r}")
1642
+ result.trace.info(f"[STAGE]: Skip stage: {stage.iden!r}")
1617
1643
  stage.set_outputs(output={"skipped": True}, to=output)
1618
1644
  continue
1619
1645
 
1620
1646
  if event and event.is_set():
1621
1647
  error_msg: str = (
1622
- "Item-Stage was canceled from event that had set before "
1623
- "stage item execution."
1648
+ "Loop-Stage was canceled from event that had set before "
1649
+ "stage loop execution."
1624
1650
  )
1625
1651
  return (
1626
1652
  result.catch(
@@ -1652,11 +1678,42 @@ class UntilStage(BaseStage):
1652
1678
 
1653
1679
  stage.set_outputs(_output, to=context)
1654
1680
  except (StageException, UtilException) as e:
1655
- result.trace.error(f"[STAGE]: {e.__class__.__name__}: {e}")
1681
+ result.trace.error(
1682
+ f"[STAGE]: {e.__class__.__name__}:{NEWLINE}{e}"
1683
+ )
1684
+ result.catch(
1685
+ status=FAILED,
1686
+ until={
1687
+ loop: {
1688
+ "loop": loop,
1689
+ "item": item,
1690
+ "stages": filter_func(output.pop("stages", {})),
1691
+ "errors": e.to_dict(),
1692
+ }
1693
+ },
1694
+ )
1656
1695
  raise StageException(
1657
1696
  f"Sub-Stage execution error: {e.__class__.__name__}: {e}"
1658
1697
  ) from None
1659
1698
 
1699
+ if rs.status == FAILED:
1700
+ error_msg: str = (
1701
+ f"Loop-Stage was break because it has a sub stage, "
1702
+ f"{stage.iden}, failed without raise error."
1703
+ )
1704
+ result.catch(
1705
+ status=FAILED,
1706
+ until={
1707
+ loop: {
1708
+ "loop": loop,
1709
+ "item": item,
1710
+ "stages": filter_func(output.pop("stages", {})),
1711
+ "errors": StageException(error_msg).to_dict(),
1712
+ }
1713
+ },
1714
+ )
1715
+ raise StageException(error_msg)
1716
+
1660
1717
  return (
1661
1718
  result.catch(
1662
1719
  status=SUCCESS,
@@ -1678,8 +1735,7 @@ class UntilStage(BaseStage):
1678
1735
  result: Result | None = None,
1679
1736
  event: Event | None = None,
1680
1737
  ) -> Result:
1681
- """Execute the stages that pass item from until condition field and
1682
- setter step.
1738
+ """Execute until loop with checking until condition.
1683
1739
 
1684
1740
  :param params: (DictData) A parameter data.
1685
1741
  :param result: (Result) A Result instance for return context and status.
@@ -1688,10 +1744,10 @@ class UntilStage(BaseStage):
1688
1744
 
1689
1745
  :rtype: Result
1690
1746
  """
1691
- if result is None: # pragma: no cov
1692
- result: Result = Result(
1693
- run_id=gen_id(self.name + (self.id or ""), unique=True)
1694
- )
1747
+ result: Result = result or Result(
1748
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
1749
+ extras=self.extras,
1750
+ )
1695
1751
 
1696
1752
  result.trace.info(f"[STAGE]: Until-Execution: {self.until}")
1697
1753
  item: Union[str, int, bool] = param2template(
@@ -1709,12 +1765,12 @@ class UntilStage(BaseStage):
1709
1765
  context={
1710
1766
  "errors": StageException(
1711
1767
  "Stage was canceled from event that had set "
1712
- "before stage until execution."
1768
+ "before stage loop execution."
1713
1769
  ).to_dict()
1714
1770
  },
1715
1771
  )
1716
1772
 
1717
- result, item = self.execute_item(
1773
+ result, item = self.execute_loop(
1718
1774
  item=item,
1719
1775
  loop=loop,
1720
1776
  params=params,
@@ -1725,10 +1781,10 @@ class UntilStage(BaseStage):
1725
1781
  loop += 1
1726
1782
  if item is None:
1727
1783
  result.trace.warning(
1728
- "... Does not have set item stage. It will use loop by "
1729
- "default."
1784
+ f"... Loop-Execute not set item. It use loop: {loop} by "
1785
+ f"default."
1730
1786
  )
1731
- item = loop
1787
+ item: int = loop
1732
1788
 
1733
1789
  next_track: bool = eval(
1734
1790
  param2template(
@@ -1741,8 +1797,8 @@ class UntilStage(BaseStage):
1741
1797
  )
1742
1798
  if not isinstance(next_track, bool):
1743
1799
  raise StageException(
1744
- "Return type of until condition does not be boolean, it"
1745
- f"return: {next_track!r}"
1800
+ "Return type of until condition not be `boolean`, getting"
1801
+ f": {next_track!r}"
1746
1802
  )
1747
1803
  track: bool = not next_track
1748
1804
  delay(0.025)
@@ -1830,7 +1886,6 @@ class CaseStage(BaseStage):
1830
1886
  context: DictData = copy.deepcopy(params)
1831
1887
  context.update({"case": case})
1832
1888
  output: DictData = {"case": case, "stages": {}}
1833
-
1834
1889
  for stage in stages:
1835
1890
 
1836
1891
  if self.extras:
@@ -1913,11 +1968,10 @@ class CaseStage(BaseStage):
1913
1968
 
1914
1969
  :rtype: Result
1915
1970
  """
1916
- if result is None: # pragma: no cov
1917
- result: Result = Result(
1918
- run_id=gen_id(self.name + (self.id or ""), unique=True),
1919
- extras=self.extras,
1920
- )
1971
+ result: Result = result or Result(
1972
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
1973
+ extras=self.extras,
1974
+ )
1921
1975
 
1922
1976
  _case: Optional[str] = param2template(
1923
1977
  self.case, params, extras=self.extras
@@ -1973,7 +2027,7 @@ class CaseStage(BaseStage):
1973
2027
 
1974
2028
 
1975
2029
  class RaiseStage(BaseStage): # pragma: no cov
1976
- """Raise error stage execution that raise StageException that use a message
2030
+ """Raise error stage executor that raise `StageException` that use a message
1977
2031
  field for making error message before raise.
1978
2032
 
1979
2033
  Data Validate:
@@ -2005,11 +2059,10 @@ class RaiseStage(BaseStage): # pragma: no cov
2005
2059
  :param event: (Event) An Event manager instance that use to cancel this
2006
2060
  execution if it forces stopped by parent execution.
2007
2061
  """
2008
- if result is None: # pragma: no cov
2009
- result: Result = Result(
2010
- run_id=gen_id(self.name + (self.id or ""), unique=True),
2011
- extras=self.extras,
2012
- )
2062
+ result: Result = result or Result(
2063
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
2064
+ extras=self.extras,
2065
+ )
2013
2066
  message: str = param2template(self.message, params, extras=self.extras)
2014
2067
  result.trace.info(f"[STAGE]: Raise-Execute: {message!r}.")
2015
2068
  raise StageException(message)
@@ -2163,10 +2216,10 @@ class DockerStage(BaseStage): # pragma: no cov
2163
2216
 
2164
2217
  :rtype: Result
2165
2218
  """
2166
- if result is None: # pragma: no cov
2167
- result: Result = Result(
2168
- run_id=gen_id(self.name + (self.id or ""), unique=True)
2169
- )
2219
+ result: Result = result or Result(
2220
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
2221
+ extras=self.extras,
2222
+ )
2170
2223
 
2171
2224
  result.trace.info(f"[STAGE]: Docker-Execute: {self.image}:{self.tag}")
2172
2225
 
@@ -2258,10 +2311,10 @@ class VirtualPyStage(PyStage): # pragma: no cov
2258
2311
 
2259
2312
  :rtype: Result
2260
2313
  """
2261
- if result is None: # pragma: no cov
2262
- result: Result = Result(
2263
- run_id=gen_id(self.name + (self.id or ""), unique=True)
2264
- )
2314
+ result: Result = result or Result(
2315
+ run_id=gen_id(self.name + (self.id or ""), unique=True),
2316
+ extras=self.extras,
2317
+ )
2265
2318
 
2266
2319
  result.trace.info(f"[STAGE]: Py-Virtual-Execute: {self.name}")
2267
2320
  run: str = param2template(dedent(self.run), params, extras=self.extras)