ddeutil-workflow 0.0.72__py3-none-any.whl → 0.0.73__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.
@@ -1 +1 @@
1
- __version__: str = "0.0.72"
1
+ __version__: str = "0.0.73"
ddeutil/workflow/conf.py CHANGED
@@ -109,7 +109,7 @@ class Config: # pragma: no cov
109
109
  "LOG_FORMAT",
110
110
  (
111
111
  "%(asctime)s.%(msecs)03d (%(process)-5d, "
112
- "%(thread)-5d) [%(levelname)-7s] %(message)-120s "
112
+ "%(thread)-5d) [%(levelname)-7s] (%(cut_id)s) %(message)-120s "
113
113
  "(%(filename)s:%(lineno)s) (%(name)-10s)"
114
114
  ),
115
115
  )
@@ -119,8 +119,8 @@ class Config: # pragma: no cov
119
119
  return env(
120
120
  "LOG_FORMAT_FILE",
121
121
  (
122
- "{datetime} ({process:5d}, {thread:5d}) {message:120s} "
123
- "({filename}:{lineno})"
122
+ "{datetime} ({process:5d}, {thread:5d}) ({cut_id}) "
123
+ "{message:120s} ({filename}:{lineno})"
124
124
  ),
125
125
  )
126
126
 
@@ -222,6 +222,7 @@ class YamlParser:
222
222
  paths: Optional[list[Path]] = None,
223
223
  obj: Optional[Union[object, str]] = None,
224
224
  extras: Optional[DictData] = None,
225
+ ignore_filename: Optional[str] = None,
225
226
  ) -> DictData:
226
227
  """Find data with specific key and return the latest modify date data if
227
228
  this key exists multiple files.
@@ -229,9 +230,12 @@ class YamlParser:
229
230
  :param name: (str) A name of data that want to find.
230
231
  :param path: (Path) A config path object.
231
232
  :param paths: (list[Path]) A list of config path object.
232
- :param obj:
233
+ :param obj: (object | str) An object that want to validate matching
234
+ before return.
233
235
  :param extras: (DictData) An extra parameter that use to override core
234
236
  config values.
237
+ :param ignore_filename: (str) An ignore filename. Default is
238
+ ``.confignore`` filename.
235
239
 
236
240
  :rtype: DictData
237
241
  """
@@ -252,13 +256,13 @@ class YamlParser:
252
256
  for path in paths:
253
257
  for file in glob_files(path):
254
258
 
255
- if cls.is_ignore(file, path):
259
+ if cls.is_ignore(file, path, ignore_filename=ignore_filename):
256
260
  continue
257
261
 
258
262
  if data := cls.filter_yaml(file, name=name):
259
263
  if not obj_type:
260
264
  all_data.append((file.lstat().st_mtime, data))
261
- elif data.get("type", "") == obj_type:
265
+ elif (t := data.get("type")) and t == obj_type:
262
266
  all_data.append((file.lstat().st_mtime, data))
263
267
  else:
264
268
  continue
@@ -274,6 +278,7 @@ class YamlParser:
274
278
  paths: Optional[list[Path]] = None,
275
279
  excluded: Optional[list[str]] = None,
276
280
  extras: Optional[DictData] = None,
281
+ ignore_filename: Optional[str] = None,
277
282
  ) -> Iterator[tuple[str, DictData]]:
278
283
  """Find all data that match with object type in config path. This class
279
284
  method can use include and exclude list of identity name for filter and
@@ -287,6 +292,8 @@ class YamlParser:
287
292
  data.
288
293
  :param extras: (DictData) An extra parameter that use to override core
289
294
  config values.
295
+ :param ignore_filename: (str) An ignore filename. Default is
296
+ ``.confignore`` filename.
290
297
 
291
298
  :rtype: Iterator[tuple[str, DictData]]
292
299
  """
@@ -308,7 +315,7 @@ class YamlParser:
308
315
  for path in paths:
309
316
  for file in glob_files(path):
310
317
 
311
- if cls.is_ignore(file, path):
318
+ if cls.is_ignore(file, path, ignore_filename=ignore_filename):
312
319
  continue
313
320
 
314
321
  for key, data in cls.filter_yaml(file).items():
@@ -316,7 +323,7 @@ class YamlParser:
316
323
  if key in excluded:
317
324
  continue
318
325
 
319
- if data.get("type", "") == obj_type:
326
+ if (t := data.get("type")) and t == obj_type:
320
327
  marking: tuple[float, DictData] = (
321
328
  file.lstat().st_mtime,
322
329
  data,
@@ -1311,6 +1311,17 @@ class CallStage(BaseRetryStage):
1311
1311
  alias="with",
1312
1312
  )
1313
1313
 
1314
+ @field_validator("args", mode="before")
1315
+ def __validate_args_key(cls, value: Any) -> Any:
1316
+ if isinstance(value, dict):
1317
+ if any(k in value for k in ("result", "extras")):
1318
+ raise ValueError(
1319
+ "The argument on workflow template for the caller stage "
1320
+ "should not pass `result` and `extras`. They are special "
1321
+ "arguments."
1322
+ )
1323
+ return value
1324
+
1314
1325
  def execute(
1315
1326
  self,
1316
1327
  params: DictData,
@@ -1348,9 +1359,10 @@ class CallStage(BaseRetryStage):
1348
1359
 
1349
1360
  # VALIDATE: check input task caller parameters that exists before
1350
1361
  # calling.
1351
- args: DictData = {"result": result} | param2template(
1352
- self.args, params, extras=self.extras
1353
- )
1362
+ args: DictData = {
1363
+ "result": result,
1364
+ "extras": self.extras,
1365
+ } | param2template(self.args, params, extras=self.extras)
1354
1366
  sig = inspect.signature(call_func)
1355
1367
  necessary_params: list[str] = []
1356
1368
  has_keyword: bool = False
@@ -1369,14 +1381,21 @@ class CallStage(BaseRetryStage):
1369
1381
  (k.removeprefix("_") not in args and k not in args)
1370
1382
  for k in necessary_params
1371
1383
  ):
1384
+ necessary_params.remove("result")
1385
+ necessary_params.remove("extras")
1386
+ args.pop("result")
1387
+ args.pop("extras")
1372
1388
  raise ValueError(
1373
1389
  f"Necessary params, ({', '.join(necessary_params)}, ), "
1374
- f"does not set to args, {list(args.keys())}."
1390
+ f"does not set to args. It already set {list(args.keys())}."
1375
1391
  )
1376
1392
 
1377
1393
  if "result" not in sig.parameters and not has_keyword:
1378
1394
  args.pop("result")
1379
1395
 
1396
+ if "extras" not in sig.parameters and not has_keyword:
1397
+ args.pop("extras")
1398
+
1380
1399
  if event and event.is_set():
1381
1400
  raise StageCancelError(
1382
1401
  "Execution was canceled from the event before start parallel."
@@ -1441,9 +1460,10 @@ class CallStage(BaseRetryStage):
1441
1460
 
1442
1461
  # VALIDATE: check input task caller parameters that exists before
1443
1462
  # calling.
1444
- args: DictData = {"result": result} | param2template(
1445
- self.args, params, extras=self.extras
1446
- )
1463
+ args: DictData = {
1464
+ "result": result,
1465
+ "extras": self.extras,
1466
+ } | param2template(self.args, params, extras=self.extras)
1447
1467
  sig = inspect.signature(call_func)
1448
1468
  necessary_params: list[str] = []
1449
1469
  has_keyword: bool = False
@@ -1462,14 +1482,20 @@ class CallStage(BaseRetryStage):
1462
1482
  (k.removeprefix("_") not in args and k not in args)
1463
1483
  for k in necessary_params
1464
1484
  ):
1485
+ necessary_params.remove("result")
1486
+ necessary_params.remove("extras")
1487
+ args.pop("result")
1488
+ args.pop("extras")
1465
1489
  raise ValueError(
1466
1490
  f"Necessary params, ({', '.join(necessary_params)}, ), "
1467
- f"does not set to args, {list(args.keys())}."
1491
+ f"does not set to args. It already set {list(args.keys())}."
1468
1492
  )
1469
-
1470
1493
  if "result" not in sig.parameters and not has_keyword:
1471
1494
  args.pop("result")
1472
1495
 
1496
+ if "extras" not in sig.parameters and not has_keyword:
1497
+ args.pop("extras")
1498
+
1473
1499
  args: DictData = self.validate_model_args(call_func, args, result)
1474
1500
  if inspect.iscoroutinefunction(call_func):
1475
1501
  rs: DictOrModel = await call_func(
@@ -76,7 +76,7 @@ PREFIX_LOGS_REGEX: re.Pattern[str] = re.compile(
76
76
  ) # pragma: no cov
77
77
 
78
78
 
79
- class PrefixMsg(BaseModel):
79
+ class Message(BaseModel):
80
80
  """Prefix Message model for receive grouping dict from searching prefix data
81
81
  from logging message.
82
82
  """
@@ -92,9 +92,9 @@ class PrefixMsg(BaseModel):
92
92
  msg (str): A message that want to extract.
93
93
 
94
94
  Returns:
95
- PrefixMsg: the validated model from a string message.
95
+ Message: the validated model from a string message.
96
96
  """
97
- return PrefixMsg.model_validate(
97
+ return Message.model_validate(
98
98
  obj=PREFIX_LOGS_REGEX.search(msg).groupdict()
99
99
  )
100
100
 
@@ -126,6 +126,9 @@ class TraceMeta(BaseModel): # pragma: no cov
126
126
  process: int = Field(description="A process ID.")
127
127
  thread: int = Field(description="A thread ID.")
128
128
  message: str = Field(description="A message log.")
129
+ cut_id: Optional[str] = Field(
130
+ default=None, description="A cutting of running ID."
131
+ )
129
132
  filename: str = Field(description="A filename of this log.")
130
133
  lineno: int = Field(description="A line number of this log.")
131
134
 
@@ -157,6 +160,7 @@ class TraceMeta(BaseModel): # pragma: no cov
157
160
  mode: Literal["stdout", "stderr"],
158
161
  message: str,
159
162
  level: str,
163
+ cutting_id: str,
160
164
  *,
161
165
  extras: Optional[DictData] = None,
162
166
  ) -> Self:
@@ -166,6 +170,7 @@ class TraceMeta(BaseModel): # pragma: no cov
166
170
  :param mode: (Literal["stdout", "stderr"]) A metadata mode.
167
171
  :param message: (str) A message.
168
172
  :param level: (str) A log level.
173
+ :param cutting_id: (str)
169
174
  :param extras: (DictData) An extra parameter that want to override core
170
175
  config values.
171
176
 
@@ -185,6 +190,7 @@ class TraceMeta(BaseModel): # pragma: no cov
185
190
  process=os.getpid(),
186
191
  thread=get_ident(),
187
192
  message=message,
193
+ cut_id=cutting_id,
188
194
  filename=frame_info.filename.split(os.path.sep)[-1],
189
195
  lineno=frame_info.lineno,
190
196
  )
@@ -529,10 +535,7 @@ class ConsoleTrace(BaseTrace): # pragma: no cov
529
535
 
530
536
  :rtype: str
531
537
  """
532
- return prepare_newline(
533
- f"({self.cut_id}) "
534
- f"{PrefixMsg.from_str(message).prepare(self.extras)}"
535
- )
538
+ return prepare_newline(Message.from_str(message).prepare(self.extras))
536
539
 
537
540
  def _logging(
538
541
  self, message: str, mode: str, *, is_err: bool = False
@@ -655,7 +658,11 @@ class FileTrace(ConsoleTrace): # pragma: no cov
655
658
 
656
659
  mode: Literal["stdout", "stderr"] = "stderr" if is_err else "stdout"
657
660
  trace_meta: TraceMeta = TraceMeta.make(
658
- mode=mode, level=level, message=message, extras=self.extras
661
+ mode=mode,
662
+ level=level,
663
+ message=message,
664
+ cutting_id=self.cut_id,
665
+ extras=self.extras,
659
666
  )
660
667
 
661
668
  with (self.pointer / f"{mode}.txt").open(
@@ -684,7 +691,11 @@ class FileTrace(ConsoleTrace): # pragma: no cov
684
691
 
685
692
  mode: Literal["stdout", "stderr"] = "stderr" if is_err else "stdout"
686
693
  trace_meta: TraceMeta = TraceMeta.make(
687
- mode=mode, level=level, message=message, extras=self.extras
694
+ mode=mode,
695
+ level=level,
696
+ message=message,
697
+ cutting_id=self.cut_id,
698
+ extras=self.extras,
688
699
  )
689
700
 
690
701
  async with aiofiles.open(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ddeutil-workflow
3
- Version: 0.0.72
3
+ Version: 0.0.73
4
4
  Summary: Lightweight workflow orchestration with YAML template
5
5
  Author-email: ddeutils <korawich.anu@gmail.com>
6
6
  License: MIT
@@ -1,19 +1,19 @@
1
- ddeutil/workflow/__about__.py,sha256=VthLlJATFFZHEcP5syc1TRdzGF0zHfM2k5hzVK_WmRk,28
1
+ ddeutil/workflow/__about__.py,sha256=Ht-dVJZ9jffiZCn55sCsjQbRLgRrXbeX4g38xoyJcmo,28
2
2
  ddeutil/workflow/__cron.py,sha256=BOKQcreiex0SAigrK1gnLxpvOeF3aca_rQwyz9Kfve4,28751
3
3
  ddeutil/workflow/__init__.py,sha256=HUy9XkBe7ttpUupJS4JDuj3aGp2QmJZfz8m2kHAIwdw,927
4
4
  ddeutil/workflow/__main__.py,sha256=Qd-f8z2Q2vpiEP2x6PBFsJrpACWDVxFKQk820MhFmHo,59
5
5
  ddeutil/workflow/__types.py,sha256=uNfoRbVmNK5O37UUMVnqcmoghD9oMS1q9fXC0APnjSI,4584
6
6
  ddeutil/workflow/audits.py,sha256=1pg4a5wdZCAKOqMr1Z_ofzRAFsDarN1BIJenWwn9xkg,11435
7
7
  ddeutil/workflow/cli.py,sha256=7cdn4f9KYOBK4CFs7sGmM2c0iYvzXiPtHnklSuD7ObU,5676
8
- ddeutil/workflow/conf.py,sha256=ZkXNiiIljqNVoLo46Gbp37-NNMfDCz5g9JiyNeJNoXE,13973
8
+ ddeutil/workflow/conf.py,sha256=dxPzaLL9Wsg_3k6diQn4jqxT9jkqdsjDEGl81qLhVpY,14472
9
9
  ddeutil/workflow/errors.py,sha256=O5rq80Sqj0QMeIsWXpRUhiFLTq0o8bwm5BQ4kuq6xmI,3013
10
10
  ddeutil/workflow/event.py,sha256=0fGcous2vAF5DZ-aengk_vovgHoWNRoIiidSxk9ytkw,11119
11
11
  ddeutil/workflow/job.py,sha256=kviOQeSUsx0Z7CL0foblTulg2m_l6a3M3SMRxg9RWeg,39151
12
12
  ddeutil/workflow/params.py,sha256=Pco3DyjptC5Jkx53dhLL9xlIQdJvNAZs4FLzMUfXpbQ,12402
13
13
  ddeutil/workflow/result.py,sha256=ctxNSaY9tZPHEAUgvDkjWWu2APeTmlZCf1Hb0XVbbFo,8173
14
14
  ddeutil/workflow/reusables.py,sha256=LSn0XTkzGHf4ulOmWub29F0JZHt0NEyzrFd4ZFx_g_k,21622
15
- ddeutil/workflow/stages.py,sha256=kzMEMRTEuG52EOw51zyVO6LE-oiiqTIRUCk_OMcWZTM,106506
16
- ddeutil/workflow/traces.py,sha256=DrKzxgp9FJUJd_oWYHiMtR1z8R7HeweAL4_Y8q0_pz8,25048
15
+ ddeutil/workflow/stages.py,sha256=xJqVxJvah3nsJSgOHL3BFm5M_UzM8RSEeIIlx96qUAI,107564
16
+ ddeutil/workflow/traces.py,sha256=2XTX0ZQnbtKAp__PU4KCuBrx_8fTDpiIiBnKqeFCrLY,25318
17
17
  ddeutil/workflow/utils.py,sha256=-yWVShFGUJwUL5DU4xi-f2UGLXEuuv8sTf-GmVGjNt0,9674
18
18
  ddeutil/workflow/workflow.py,sha256=sy-HEKLmGPE1tDNr_cpm3CQsMEDP6fkXDHC9UsVSVDE,36214
19
19
  ddeutil/workflow/api/__init__.py,sha256=W3fe6_NLHSUzr4Tsu79w3pmvrYjpLeP3zBk4mtpPyqg,2843
@@ -22,9 +22,9 @@ ddeutil/workflow/api/routes/__init__.py,sha256=JRaJZB0D6mgR17MbZo8yLtdYDtD62AA8M
22
22
  ddeutil/workflow/api/routes/job.py,sha256=x809G5gCbJS257txj9eLLTbCbFK8ercXWzPDLuv5gEM,2953
23
23
  ddeutil/workflow/api/routes/logs.py,sha256=HiXw93PeIiaK_xJjM8lbD2ED1Il-W1iM51085nc7qmg,5286
24
24
  ddeutil/workflow/api/routes/workflows.py,sha256=D76cdLb2_9Dkfe2_8xt06CvPhAyJMqxyYkUgAs8Qlnw,4402
25
- ddeutil_workflow-0.0.72.dist-info/licenses/LICENSE,sha256=nGFZ1QEhhhWeMHf9n99_fdt4vQaXS29xWKxt-OcLywk,1085
26
- ddeutil_workflow-0.0.72.dist-info/METADATA,sha256=rXtrkQ-LS9dx4DIIWOAz44e0bXSGrm_zujUNvb-uujs,15221
27
- ddeutil_workflow-0.0.72.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- ddeutil_workflow-0.0.72.dist-info/entry_points.txt,sha256=qDTpPSauL0ciO6T4iSVt8bJeYrVEkkoEEw_RlGx6Kgk,63
29
- ddeutil_workflow-0.0.72.dist-info/top_level.txt,sha256=m9M6XeSWDwt_yMsmH6gcOjHZVK5O0-vgtNBuncHjzW4,8
30
- ddeutil_workflow-0.0.72.dist-info/RECORD,,
25
+ ddeutil_workflow-0.0.73.dist-info/licenses/LICENSE,sha256=nGFZ1QEhhhWeMHf9n99_fdt4vQaXS29xWKxt-OcLywk,1085
26
+ ddeutil_workflow-0.0.73.dist-info/METADATA,sha256=0R6aQshHh_MWHRGKQwlrCfUToucyG3cLRuEDv_QDTKY,15221
27
+ ddeutil_workflow-0.0.73.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ ddeutil_workflow-0.0.73.dist-info/entry_points.txt,sha256=qDTpPSauL0ciO6T4iSVt8bJeYrVEkkoEEw_RlGx6Kgk,63
29
+ ddeutil_workflow-0.0.73.dist-info/top_level.txt,sha256=m9M6XeSWDwt_yMsmH6gcOjHZVK5O0-vgtNBuncHjzW4,8
30
+ ddeutil_workflow-0.0.73.dist-info/RECORD,,