Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/config/files.py: 19%
49 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"""Contains methods for finding and reading configuration files."""
3from __future__ import annotations
5from pathlib import Path
6from typing import TYPE_CHECKING, Any, Dict, MutableMapping, Union
8from bumpversion.config.files_legacy import read_ini_file
9from bumpversion.ui import get_indented_logger, print_warning
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 bumpversion.config.models import Config
13 from bumpversion.version_part import Version
15logger = get_indented_logger(__name__)
17CONFIG_FILE_SEARCH_ORDER = (
18 ".bumpversion.cfg",
19 ".bumpversion.toml",
20 "setup.cfg",
21 "pyproject.toml",
22)
25def find_config_file(explicit_file: Union[str, Path, None] = None) -> Union[Path, None]:
26 """
27 Find the configuration file, if it exists.
29 If no explicit configuration file is passed, it will search in several files to
30 find its configuration.
32 Args:
33 explicit_file: The configuration file to explicitly use.
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(
42 (cfg_file for cfg_file in search_paths if cfg_file.exists() and "bumpversion]" in cfg_file.read_text()),
43 None,
44 )
47def read_config_file(config_file: Union[str, Path, None] = None) -> Dict[str, Any]:
48 """
49 Read the configuration file, if it exists.
51 If no explicit configuration file is passed, it will search in several files to
52 find its configuration.
54 Args:
55 config_file: The configuration file to explicitly use.
57 Returns:
58 A dictionary of read key-values
59 """
60 if not config_file:
61 logger.info("No configuration file found.")
62 return {}
64 config_path = Path(config_file)
65 if not config_path.exists():
66 logger.info("Configuration file not found: %s.", config_path)
67 return {}
69 logger.info("Reading config file: %s", config_file)
71 if config_path.suffix == ".cfg":
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":
75 return read_toml_file(config_path)
76 else:
77 logger.info("Unknown config file suffix: %s. Using defaults.", config_path.suffix)
78 return {}
81def read_toml_file(file_path: Path) -> Dict[str, Any]:
82 """
83 Parse a TOML file and return the `bumpversion` section.
85 Args:
86 file_path: The path to the TOML file.
88 Returns:
89 dict: A dictionary of the `bumpversion` section.
90 """
91 import tomlkit
93 # Load the TOML file
94 toml_data = tomlkit.parse(file_path.read_text()).unwrap()
96 return toml_data.get("tool", {}).get("bumpversion", {})
99def 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.
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
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
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 )
144 updater = DataFileUpdater(datafile_config, config.version_config.part_configs)
145 updater.update_file(current_version, new_version, context, dry_run)
146 logger.dedent()