Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/config/__init__.py: 83%
40 statements
« prev ^ index » next coverage.py v7.3.2, created at 2024-02-24 07:50 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2024-02-24 07:50 -0600
1"""Configuration management."""
3from __future__ import annotations
5from typing import TYPE_CHECKING, Union
7from bumpversion.config.files import read_config_file
8from bumpversion.config.models import Config
9from bumpversion.exceptions import ConfigurationError
10from bumpversion.ui import get_indented_logger
12if TYPE_CHECKING: # pragma: no-coverage 12 ↛ 13line 12 didn't jump to line 13, because the condition on line 12 was never true
13 from pathlib import Path
15logger = get_indented_logger(__name__)
17DEFAULTS = {
18 "current_version": None,
19 "parse": r"(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)",
20 "serialize": ["{major}.{minor}.{patch}"],
21 "search": "{current_version}",
22 "replace": "{new_version}",
23 "regex": False,
24 "ignore_missing_version": False,
25 "ignore_missing_files": False,
26 "tag": False,
27 "sign_tags": False,
28 "tag_name": "v{new_version}",
29 "tag_message": "Bump version: {current_version} → {new_version}",
30 "allow_dirty": False,
31 "commit": False,
32 "message": "Bump version: {current_version} → {new_version}",
33 "commit_args": None,
34 "scm_info": None,
35 "parts": {},
36 "files": [],
37}
40def get_configuration(config_file: Union[str, Path, None] = None, **overrides) -> Config:
41 """
42 Return the configuration based on any configuration files and overrides.
44 Args:
45 config_file: An explicit configuration file to use, otherwise search for one
46 **overrides: Specific configuration key-values to override in the configuration
48 Returns:
49 The configuration
50 """
51 from bumpversion.config.utils import get_all_file_configs, get_all_part_configs
52 from bumpversion.scm import SCMInfo, SourceCodeManager, get_scm_info # noqa: F401
54 logger.info("Reading configuration")
55 logger.indent()
57 config_dict = DEFAULTS.copy()
58 parsed_config = read_config_file(config_file) if config_file else {}
60 # We want to strip out unrecognized key-values to avoid inadvertent issues
61 config_dict.update({key: val for key, val in parsed_config.items() if key in DEFAULTS.keys()})
63 allowed_overrides = set(DEFAULTS.keys())
64 config_dict.update({key: val for key, val in overrides.items() if key in allowed_overrides})
66 # Set any missing version parts
67 config_dict["parts"] = get_all_part_configs(config_dict)
69 # Set any missing file configuration
70 config_dict["files"] = get_all_file_configs(config_dict)
72 # Resolve the SCMInfo class for Pydantic's BaseSettings
73 Config.model_rebuild()
74 config = Config(**config_dict) # type: ignore[arg-type]
76 # Get the information about the SCM
77 scm_info = get_scm_info(config.tag_name, config.parse)
78 config.scm_info = scm_info
80 # Update and verify the current_version
81 config.current_version = check_current_version(config)
83 logger.dedent()
85 return config
88def check_current_version(config: Config) -> str:
89 """
90 Returns the current version.
92 If the current version is not specified in the config file, command line or env variable,
93 it attempts to retrieve it via a tag.
95 Args:
96 config: The current configuration dictionary.
98 Returns:
99 The version number
101 Raises:
102 ConfigurationError: If it can't find the current version
103 """
104 current_version = config.current_version
105 scm_info = config.scm_info
107 if current_version is None and scm_info.current_version: 107 ↛ 108line 107 didn't jump to line 108, because the condition on line 107 was never true
108 return scm_info.current_version
109 elif current_version and scm_info.current_version and current_version != scm_info.current_version: 109 ↛ 110line 109 didn't jump to line 110, because the condition on line 109 was never true
110 logger.warning(
111 "Specified version (%s) does not match last tagged version (%s)",
112 current_version,
113 scm_info.current_version,
114 )
115 return current_version
116 elif current_version: 116 ↛ 119line 116 didn't jump to line 119, because the condition on line 116 was never false
117 return current_version
119 raise ConfigurationError("Unable to determine the current version.")