Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/utils.py: 23%
33 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-15 09:15 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-15 09:15 -0600
1"""General utilities."""
2import string
3from collections import ChainMap
4from dataclasses import asdict
5from typing import TYPE_CHECKING, Any, List, Optional, Tuple
7if TYPE_CHECKING: # pragma: no-coverage 7 ↛ 8line 7 didn't jump to line 8, because the condition on line 7 was never true
8 from bumpversion.config import Config
9 from bumpversion.version_part import Version
12def extract_regex_flags(regex_pattern: str) -> Tuple[str, str]:
13 """
14 Extract the regex flags from the regex pattern.
16 Args:
17 regex_pattern: The pattern that might start with regex flags
19 Returns:
20 A tuple of the regex pattern without the flag string and regex flag string
21 """
22 import re
24 flag_pattern = r"^(\(\?[aiLmsux]+\))"
25 bits = re.split(flag_pattern, regex_pattern)
26 return (regex_pattern, "") if len(bits) == 1 else (bits[2], bits[1])
29def recursive_sort_dict(input_value: Any) -> Any:
30 """Sort a dictionary recursively."""
31 if not isinstance(input_value, dict):
32 return input_value
34 return {key: recursive_sort_dict(input_value[key]) for key in sorted(input_value.keys())}
37def key_val_string(d: dict) -> str:
38 """Render the dictionary as a comma-delimited key=value string."""
39 return ", ".join(f"{k}={v}" for k, v in sorted(d.items()))
42def prefixed_environ() -> dict:
43 """Return a dict of the environment with keys wrapped in `${}`."""
44 import os
46 return {f"${key}": value for key, value in os.environ.items()}
49def labels_for_format(serialize_format: str) -> List[str]:
50 """Return a list of labels for the given serialize_format."""
51 return [item[1] for item in string.Formatter().parse(serialize_format) if item[1]]
54def get_context(
55 config: "Config", current_version: Optional["Version"] = None, new_version: Optional["Version"] = None
56) -> ChainMap:
57 """Return the context for rendering messages and tags."""
58 import datetime
60 ctx = ChainMap(
61 {"current_version": config.current_version},
62 {"now": datetime.datetime.now(), "utcnow": datetime.datetime.utcnow()},
63 prefixed_environ(),
64 asdict(config.scm_info),
65 {c: c for c in ("#", ";")},
66 )
67 if current_version:
68 ctx = ctx.new_child({f"current_{part}": current_version[part].value for part in current_version})
69 if new_version:
70 ctx = ctx.new_child({f"new_{part}": new_version[part].value for part in new_version})
71 return ctx
74def get_overrides(**kwargs) -> dict:
75 """Return a dictionary containing only the overridden key-values."""
76 return {key: val for key, val in kwargs.items() if val is not None}