codekingpro/portable-devtools
114k
1"""Usage utilities."""2 3from collections.abc import Callable4 5 6def _dict_int_op(7 left: dict,8 right: dict,9 op: Callable[[int, int], int],10 *,11 default: int = 0,12 depth: int = 0,13 max_depth: int = 100,14) -> dict:15 """Apply an integer operation to corresponding values in two dictionaries.16 17 Recursively combines two dictionaries by applying the given operation to integer18 values at matching keys.19 20 Supports nested dictionaries.21 22 Args:23 left: First dictionary to combine.24 right: Second dictionary to combine.25 op: Binary operation function to apply to integer values.26 default: Default value to use when a key is missing from a dictionary.27 depth: Current recursion depth (used internally).28 max_depth: Maximum recursion depth (to prevent infinite loops).29 30 Returns:31 A new dictionary with combined values.32 33 Raises:34 ValueError: If `max_depth` is exceeded or if value types are not supported.35 """36 if depth >= max_depth:37 msg = f"{max_depth=} exceeded, unable to combine dicts."38 raise ValueError(msg)39 combined: dict = {}40 for k in set(left).union(right):41 if isinstance(left.get(k, default), int) and isinstance(42 right.get(k, default), int43 ):44 combined[k] = op(left.get(k, default), right.get(k, default))45 elif isinstance(left.get(k, {}), dict) and isinstance(right.get(k, {}), dict):46 combined[k] = _dict_int_op(47 left.get(k, {}),48 right.get(k, {}),49 op,50 default=default,51 depth=depth + 1,52 max_depth=max_depth,53 )54 else:55 types = [type(d[k]) for d in (left, right) if k in d]56 msg = (57 f"Unknown value types: {types}. Only dict and int values are supported."58 )59 raise ValueError(msg) # noqa: TRY00460 return combined61 