ddeutil-workflow 0.0.37__py3-none-any.whl → 0.0.39__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.
@@ -18,7 +18,7 @@ try:
18
18
  except ImportError:
19
19
  from typing_extensions import ParamSpec
20
20
 
21
- from ddeutil.core import getdot, hasdot, import_string
21
+ from ddeutil.core import getdot, import_string
22
22
  from ddeutil.io import search_env_replace
23
23
 
24
24
  from .__types import DictData, Re
@@ -59,7 +59,8 @@ def custom_filter(name: str) -> Callable[P, FilterFunc]:
59
59
  """Custom filter decorator function that set function attributes, ``filter``
60
60
  for making filter registries variable.
61
61
 
62
- :param: name: A filter name for make different use-case of a function.
62
+ :param: name: (str) A filter name for make different use-case of a function.
63
+
63
64
  :rtype: Callable[P, FilterFunc]
64
65
  """
65
66
 
@@ -108,7 +109,7 @@ def get_args_const(
108
109
  ) -> tuple[str, list[Constant], dict[str, Constant]]:
109
110
  """Get arguments and keyword-arguments from function calling string.
110
111
 
111
- :param expr: An expr string value.
112
+ :param expr: (str) An expr string value.
112
113
 
113
114
  :rtype: tuple[str, list[Constant], dict[str, Constant]]
114
115
  """
@@ -154,7 +155,7 @@ def get_args_from_filter(
154
155
  and validate it with the filter functions mapping dict.
155
156
 
156
157
  :param ft:
157
- :param filters:
158
+ :param filters: A mapping of filter registry.
158
159
 
159
160
  :rtype: tuple[str, FilterRegistry, list[Any], dict[Any, Any]]
160
161
  """
@@ -185,7 +186,7 @@ def map_post_filter(
185
186
 
186
187
  :param value: A string value that want to map with filter function.
187
188
  :param post_filter: A list of post-filter function name.
188
- :param filters: A filter registry.
189
+ :param filters: A mapping of filter registry.
189
190
 
190
191
  :rtype: T
191
192
  """
@@ -203,8 +204,8 @@ def map_post_filter(
203
204
  except Exception as err:
204
205
  logger.warning(str(err))
205
206
  raise UtilException(
206
- f"The post-filter function: {func_name} does not fit with "
207
- f"{value} (type: {type(value).__name__})."
207
+ f"The post-filter: {func_name!r} does not fit with {value!r} "
208
+ f"(type: {type(value).__name__})."
208
209
  ) from None
209
210
  return value
210
211
 
@@ -258,10 +259,10 @@ def str2template(
258
259
  with the workflow parameter types that is `str`, `int`, `datetime`, and
259
260
  `list`.
260
261
 
261
- :param value: A string value that want to map with params
262
- :param params: A parameter value that getting with matched regular
263
- expression.
264
- :param filters:
262
+ :param value: (str) A string value that want to map with params.
263
+ :param params: (DictData) A parameter value that getting with matched
264
+ regular expression.
265
+ :param filters: A mapping of filter registry.
265
266
 
266
267
  :rtype: str
267
268
  """
@@ -281,11 +282,14 @@ def str2template(
281
282
  for i in (found.post_filters.strip().removeprefix("|").split("|"))
282
283
  if i != ""
283
284
  ]
284
- if not hasdot(caller, params):
285
- raise UtilException(f"The params does not set caller: {caller!r}.")
286
285
 
287
286
  # NOTE: from validate step, it guarantees that caller exists in params.
288
- getter: Any = getdot(caller, params)
287
+ try:
288
+ getter: Any = getdot(caller, params)
289
+ except ValueError as err:
290
+ raise UtilException(
291
+ f"Params does not set caller: {caller!r}."
292
+ ) from err
289
293
 
290
294
  # NOTE:
291
295
  # If type of getter caller is not string type, and it does not use to
@@ -301,25 +305,33 @@ def str2template(
301
305
 
302
306
  value: str = value.replace(found.full, getter, 1)
303
307
 
308
+ if value == "None":
309
+ return None
310
+
304
311
  return search_env_replace(value)
305
312
 
306
313
 
307
- def param2template(value: T, params: DictData) -> T:
314
+ def param2template(
315
+ value: T,
316
+ params: DictData,
317
+ filters: dict[str, FilterRegistry] | None = None,
318
+ ) -> T:
308
319
  """Pass param to template string that can search by ``RE_CALLER`` regular
309
320
  expression.
310
321
 
311
322
  :param value: A value that want to map with params
312
323
  :param params: A parameter value that getting with matched regular
313
324
  expression.
325
+ :param filters: A filter mapping for mapping with `map_post_filter` func.
314
326
 
315
327
  :rtype: T
316
328
  :returns: An any getter value from the params input.
317
329
  """
318
- filters: dict[str, FilterRegistry] = make_filter_registry()
330
+ filters: dict[str, FilterRegistry] = filters or make_filter_registry()
319
331
  if isinstance(value, dict):
320
- return {k: param2template(value[k], params) for k in value}
332
+ return {k: param2template(value[k], params, filters) for k in value}
321
333
  elif isinstance(value, (list, tuple, set)):
322
- return type(value)([param2template(i, params) for i in value])
334
+ return type(value)([param2template(i, params, filters) for i in value])
323
335
  elif not isinstance(value, str):
324
336
  return value
325
337
  return str2template(value, params, filters=filters)
@@ -329,8 +341,9 @@ def param2template(value: T, params: DictData) -> T:
329
341
  def datetime_format(value: datetime, fmt: str = "%Y-%m-%d %H:%M:%S") -> str:
330
342
  """Format datetime object to string with the format.
331
343
 
332
- :param value: A datetime value that want to format to string value.
333
- :param fmt: A format string pattern that passing to the `dt.strftime`
344
+ :param value: (datetime) A datetime value that want to format to string
345
+ value.
346
+ :param fmt: (str) A format string pattern that passing to the `dt.strftime`
334
347
  method.
335
348
 
336
349
  :rtype: str
@@ -340,3 +353,9 @@ def datetime_format(value: datetime, fmt: str = "%Y-%m-%d %H:%M:%S") -> str:
340
353
  raise UtilException(
341
354
  "This custom function should pass input value with datetime type."
342
355
  )
356
+
357
+
358
+ @custom_filter("coalesce") # pragma: no cov
359
+ def coalesce(value: T | None, default: Any) -> T:
360
+ """Coalesce with default value if the main value is None."""
361
+ return default if value is None else value
ddeutil/workflow/utils.py CHANGED
@@ -5,10 +5,9 @@
5
5
  # ------------------------------------------------------------------------------
6
6
  from __future__ import annotations
7
7
 
8
- import logging
9
8
  import stat
10
9
  import time
11
- from collections.abc import Iterator, Mapping
10
+ from collections.abc import Iterator
12
11
  from datetime import date, datetime, timedelta
13
12
  from hashlib import md5
14
13
  from inspect import isfunction
@@ -24,7 +23,6 @@ from .__types import DictData, Matrix
24
23
 
25
24
  T = TypeVar("T")
26
25
  UTC = ZoneInfo("UTC")
27
- logger = logging.getLogger("ddeutil.workflow")
28
26
 
29
27
 
30
28
  def get_dt_now(
@@ -188,29 +186,6 @@ def filter_func(value: T) -> T:
188
186
  return value
189
187
 
190
188
 
191
- def dash2underscore(
192
- key: str,
193
- values: DictData,
194
- *,
195
- fixed: str | None = None,
196
- ) -> DictData:
197
- """Change key name that has dash to underscore.
198
-
199
- :param key:
200
- :param values:
201
- :param fixed:
202
-
203
- Examples:
204
- >>> dash2underscore('foo-bar', {"foo-bar": "demo"})
205
- {'foo_bar': 'demo'}
206
-
207
- :rtype: DictData
208
- """
209
- if key in values:
210
- values[(fixed or key.replace("-", "_"))] = values.pop(key)
211
- return values
212
-
213
-
214
189
  def cross_product(matrix: Matrix) -> Iterator[DictData]:
215
190
  """Iterator of products value from matrix.
216
191
 
@@ -267,21 +242,3 @@ def cut_id(run_id: str, *, num: int = 6) -> str:
267
242
  :rtype: str
268
243
  """
269
244
  return run_id[-num:]
270
-
271
-
272
- def deep_update(origin: DictData, u: Mapping) -> DictData:
273
- """Deep update dict.
274
-
275
- Example:
276
- >>> deep_update(
277
- ... origin={"jobs": {"job01": "foo"}},
278
- ... u={"jobs": {"job02": "bar"}},
279
- ... )
280
- {"jobs": {"job01": "foo", "job02": "bar"}}
281
- """
282
- for k, value in u.items():
283
- if isinstance(value, Mapping) and value:
284
- origin[k] = deep_update(origin.get(k, {}), value)
285
- else:
286
- origin[k] = value
287
- return origin