Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/config/__init__.py: 23%

40 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-15 09:15 -0600

1"""Configuration management.""" 

2from __future__ import annotations 

3 

4from typing import TYPE_CHECKING, Union 

5 

6from bumpversion.config.files import read_config_file 

7from bumpversion.config.models import Config 

8from bumpversion.exceptions import ConfigurationError 

9from bumpversion.ui import get_indented_logger 

10 

11if TYPE_CHECKING: # pragma: no-coverage 11 ↛ 12line 11 didn't jump to line 12, because the condition on line 11 was never true

12 from pathlib import Path 

13 

14logger = get_indented_logger(__name__) 

15 

16DEFAULTS = { 

17 "current_version": None, 

18 "parse": r"(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)", 

19 "serialize": ["{major}.{minor}.{patch}"], 

20 "search": "{current_version}", 

21 "replace": "{new_version}", 

22 "regex": False, 

23 "ignore_missing_version": False, 

24 "tag": False, 

25 "sign_tags": False, 

26 "tag_name": "v{new_version}", 

27 "tag_message": "Bump version: {current_version} → {new_version}", 

28 "allow_dirty": False, 

29 "commit": False, 

30 "message": "Bump version: {current_version} → {new_version}", 

31 "commit_args": None, 

32 "scm_info": None, 

33 "parts": {}, 

34 "files": [], 

35} 

36 

37 

38def get_configuration(config_file: Union[str, Path, None] = None, **overrides) -> Config: 

39 """ 

40 Return the configuration based on any configuration files and overrides. 

41 

42 Args: 

43 config_file: An explicit configuration file to use, otherwise search for one 

44 **overrides: Specific configuration key-values to override in the configuration 

45 

46 Returns: 

47 The configuration 

48 """ 

49 from bumpversion.config.utils import get_all_file_configs, get_all_part_configs 

50 from bumpversion.scm import SCMInfo, SourceCodeManager, get_scm_info # noqa: F401 

51 

52 logger.info("Reading configuration") 

53 logger.indent() 

54 

55 config_dict = DEFAULTS.copy() 

56 parsed_config = read_config_file(config_file) if config_file else {} 

57 

58 # We want to strip out unrecognized key-values to avoid inadvertent issues 

59 config_dict.update({key: val for key, val in parsed_config.items() if key in DEFAULTS.keys()}) 

60 

61 allowed_overrides = set(DEFAULTS.keys()) 

62 config_dict.update({key: val for key, val in overrides.items() if key in allowed_overrides}) 

63 

64 # Set any missing version parts 

65 config_dict["parts"] = get_all_part_configs(config_dict) 

66 

67 # Set any missing file configuration 

68 config_dict["files"] = get_all_file_configs(config_dict) 

69 

70 # Resolve the SCMInfo class for Pydantic's BaseSettings 

71 Config.model_rebuild() 

72 config = Config(**config_dict) # type: ignore[arg-type] 

73 

74 # Get the information about the SCM 

75 scm_info = get_scm_info(config.tag_name, config.parse) 

76 config.scm_info = scm_info 

77 

78 # Update and verify the current_version 

79 config.current_version = check_current_version(config) 

80 

81 logger.dedent() 

82 

83 return config 

84 

85 

86def check_current_version(config: Config) -> str: 

87 """ 

88 Returns the current version. 

89 

90 If the current version is not specified in the config file, command line or env variable, 

91 it attempts to retrieve it via a tag. 

92 

93 Args: 

94 config: The current configuration dictionary. 

95 

96 Returns: 

97 The version number 

98 

99 Raises: 

100 ConfigurationError: If it can't find the current version 

101 """ 

102 current_version = config.current_version 

103 scm_info = config.scm_info 

104 

105 if current_version is None and scm_info.current_version: 

106 return scm_info.current_version 

107 elif current_version and scm_info.current_version and current_version != scm_info.current_version: 

108 logger.warning( 

109 "Specified version (%s) does not match last tagged version (%s)", 

110 current_version, 

111 scm_info.current_version, 

112 ) 

113 return current_version 

114 elif current_version: 

115 return current_version 

116 

117 raise ConfigurationError("Unable to determine the current version.")