Coverage for /Users/coordt/Documents/code/bump-my-version/bumpversion/utils.py: 70%
39 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-06-12 09:26 -0500
« prev ^ index » next coverage.py v7.4.4, created at 2024-06-12 09:26 -0500
1"""General utilities."""
3import string
4from typing import Any, List, Tuple
7def extract_regex_flags(regex_pattern: str) -> Tuple[str, str]:
8 """
9 Extract the regex flags from the regex pattern.
11 Args:
12 regex_pattern: The pattern that might start with regex flags
14 Returns:
15 A tuple of the regex pattern without the flag string and regex flag string
16 """
17 import re
19 flag_pattern = r"^(\(\?[aiLmsux]+\))"
20 bits = re.split(flag_pattern, regex_pattern)
21 return (regex_pattern, "") if len(bits) == 1 else (bits[2], bits[1])
24def recursive_sort_dict(input_value: Any) -> Any:
25 """Sort a dictionary recursively."""
26 if not isinstance(input_value, dict):
27 return input_value
29 return {key: recursive_sort_dict(input_value[key]) for key in sorted(input_value.keys())}
32def key_val_string(d: dict) -> str:
33 """Render the dictionary as a comma-delimited key=value string."""
34 return ", ".join(f"{k}={v}" for k, v in sorted(d.items()))
37def labels_for_format(serialize_format: str) -> List[str]:
38 """Return a list of labels for the given serialize_format."""
39 return [item[1] for item in string.Formatter().parse(serialize_format) if item[1]]
42def get_overrides(**kwargs) -> dict:
43 """Return a dictionary containing only the overridden key-values."""
44 return {key: val for key, val in kwargs.items() if val is not None}
47def get_nested_value(d: dict, path: str) -> Any:
48 """
49 Retrieves the value of a nested key in a dictionary based on the given path.
51 Args:
52 d: The dictionary to search.
53 path: A string representing the path to the nested key, separated by periods.
55 Returns:
56 The value of the nested key.
58 Raises:
59 KeyError: If a key in the path does not exist.
60 ValueError: If an element in the path is not a dictionary.
61 """
62 keys = path.split(".")
63 current_element = d
65 for key in keys:
66 if not isinstance(current_element, dict): 66 ↛ 67line 66 didn't jump to line 67, because the condition on line 66 was never true
67 raise ValueError(f"Element at '{'.'.join(keys[:keys.index(key)])}' is not a dictionary")
69 if key not in current_element: 69 ↛ 70line 69 didn't jump to line 70, because the condition on line 69 was never true
70 raise KeyError(f"Key '{key}' not found at '{'.'.join(keys[:keys.index(key)])}'")
72 current_element = current_element[key]
74 return current_element
77def set_nested_value(d: dict, value: Any, path: str) -> None:
78 """
79 Sets the value of a nested key in a dictionary based on the given path.
81 Args:
82 d: The dictionary to search.
83 value: The value to set.
84 path: A string representing the path to the nested key, separated by periods.
86 Raises:
87 ValueError: If an element in the path is not a dictionary.
88 """
89 keys = path.split(".")
90 last_element = keys[-1]
91 current_element = d
93 for i, key in enumerate(keys):
94 if key == last_element:
95 current_element[key] = value
96 elif key not in current_element: 96 ↛ 97line 96 didn't jump to line 97, because the condition on line 96 was never true
97 raise KeyError(f"Key '{key}' not found at '{'.'.join(keys[:keys.index(key)])}'")
98 elif not isinstance(current_element[key], dict): 98 ↛ 99line 98 didn't jump to line 99, because the condition on line 98 was never true
99 raise ValueError(f"Path '{'.'.join(keys[:i+1])}' does not lead to a dictionary.")
100 else:
101 current_element = current_element[key]