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

1"""Contains methods for finding and reading configuration files."""

2

3 from __future__ import annotations

4

5 from pathlib import Path

6 from typing import TYPE_CHECKING, Any, Dict, MutableMapping, Union

7

8 from bumpversion.config.files_legacy import read_ini_file

9 from bumpversion.ui import get_indented_logger, print_warning

10

11 if 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 bumpversion.config.models import Config

13 from bumpversion.version_part import Version

14

15 logger = get_indented_logger(__name__)

16

17 CONFIG_FILE_SEARCH_ORDER = (

18 ".bumpversion.cfg",

19 ".bumpversion.toml",

20 "setup.cfg",

21 "pyproject.toml",

22)

23

24

25 def find_config_file(explicit_file: Union[str, Path, None] = None) -> Union[Path, None]:

26 """

27 Find the configuration file, if it exists.

28

29 If no explicit configuration file is passed, it will search in several files to

30 find its configuration.

31

32 Args:

33 explicit_file: The configuration file to explicitly use.

34

35 Returns:

36 The configuration file path

37 """

38 search_paths = (

39 [Path(explicit_file)] if explicit_file else [Path.cwd().joinpath(path) for path in CONFIG_FILE_SEARCH_ORDER]

40 )

41 return next( 41 ↛ exitline 41 didn't jump to the function exit

42 (cfg_file for cfg_file in search_paths if cfg_file.exists() and "bumpversion]" in cfg_file.read_text()),

43 None,

44 )

45

46

47 def read_config_file(config_file: Union[str, Path, None] = None) -> Dict[str, Any]:

48 """

49 Read the configuration file, if it exists.

50

51 If no explicit configuration file is passed, it will search in several files to

52 find its configuration.

53

54 Args:

55 config_file: The configuration file to explicitly use.

56

57 Returns:

58 A dictionary of read key-values

59 """

60 if not config_file: 60 ↛ 61line 60 didn't jump to line 61, because the condition on line 60 was never true

61 logger.info("No configuration file found.")

62 return {}

63

64 config_path = Path(config_file)

65 if not config_path.exists(): 65 ↛ 66line 65 didn't jump to line 66, because the condition on line 65 was never true

66 logger.info("Configuration file not found: %s.", config_path)

67 return {}

68

69 logger.info("Reading config file: %s", config_file)

70

71 if config_path.suffix == ".cfg": 71 ↛ 72line 71 didn't jump to line 72, because the condition on line 71 was never true

72 print_warning("The .cfg file format is deprecated. Please use .toml instead.")

73 return read_ini_file(config_path)

74 elif config_path.suffix == ".toml": 74 ↛ 77line 74 didn't jump to line 77, because the condition on line 74 was never false

75 return read_toml_file(config_path)

76 else:

77 logger.info("Unknown config file suffix: %s. Using defaults.", config_path.suffix)

78 return {}

79

80

81 def read_toml_file(file_path: Path) -> Dict[str, Any]:

82 """

83 Parse a TOML file and return the `bumpversion` section.

84

85 Args:

86 file_path: The path to the TOML file.

87

88 Returns:

89 dict: A dictionary of the `bumpversion` section.

90 """

91 import tomlkit

92

93 # Load the TOML file

94 toml_data = tomlkit.parse(file_path.read_text()).unwrap()

95

96 return toml_data.get("tool", {}).get("bumpversion", {})

97

98

99 def update_config_file(

100 config_file: Union[str, Path],

101 config: Config,

102 current_version: Version,

103 new_version: Version,

104 context: MutableMapping,

105 dry_run: bool = False,

106) -> None:

107 """

108 Update the current_version key in the configuration file.

109

110 Args:

111 config_file: The configuration file to explicitly use.

112 config: The configuration to use.

113 current_version: The current version.

114 new_version: The new version.

115 context: The context to use for serialization.

116 dry_run: True if the update should be a dry run.

117 """

118 from bumpversion.config.models import FileChange

119 from bumpversion.files import DataFileUpdater

120

121 if not config_file:

122 logger.info("\n%sNo configuration file found to update.", logger.indent_str)

123 return

124 else:

125 logger.info("\n%sProcessing config file: %s", logger.indent_str, config_file)

126 logger.indent()

127 config_path = Path(config_file)

128 if config_path.suffix != ".toml":

129 logger.info("You must have a `.toml` suffix to update the config file: %s.", config_path)

130 return

131

132 # TODO: Eventually this should be transformed into another default "files_to_modify" entry

133 datafile_config = FileChange(

134 filename=str(config_path),

135 key_path="tool.bumpversion.current_version",

136 search=config.search,

137 replace=config.replace,

138 regex=config.regex,

139 ignore_missing_version=config.ignore_missing_version,

140 serialize=config.serialize,

141 parse=config.parse,

142 )

143

144 updater = DataFileUpdater(datafile_config, config.version_config.part_configs)

145 updater.update_file(current_version, new_version, context, dry_run)

146 logger.dedent()