3
3
from __future__ import annotations
4
4
5
5
import logging
6
- import re
7
- from difflib import context_diff
8
6
from pathlib import Path
9
7
from typing import TYPE_CHECKING , Any , Dict , MutableMapping , Union
10
8
9
+ from bumpversion .config .files_legacy import read_ini_file
11
10
from bumpversion .ui import print_warning
12
11
13
12
if TYPE_CHECKING : # pragma: no-coverage
17
16
logger = logging .getLogger (__name__ )
18
17
19
18
CONFIG_FILE_SEARCH_ORDER = (
20
- Path ( ".bumpversion.cfg" ) ,
21
- Path ( ".bumpversion.toml" ) ,
22
- Path ( "setup.cfg" ) ,
23
- Path ( "pyproject.toml" ) ,
19
+ ".bumpversion.cfg" ,
20
+ ".bumpversion.toml" ,
21
+ "setup.cfg" ,
22
+ "pyproject.toml" ,
24
23
)
25
24
26
25
@@ -37,7 +36,9 @@ def find_config_file(explicit_file: Union[str, Path, None] = None) -> Union[Path
37
36
Returns:
38
37
The configuration file path
39
38
"""
40
- search_paths = [Path (explicit_file )] if explicit_file else CONFIG_FILE_SEARCH_ORDER
39
+ search_paths = (
40
+ [Path (explicit_file )] if explicit_file else [Path .cwd ().joinpath (path ) for path in CONFIG_FILE_SEARCH_ORDER ]
41
+ )
41
42
return next (
42
43
(cfg_file for cfg_file in search_paths if cfg_file .exists () and "bumpversion]" in cfg_file .read_text ()),
43
44
None ,
@@ -61,77 +62,21 @@ def read_config_file(config_file: Union[str, Path, None] = None) -> Dict[str, An
61
62
logger .info ("No configuration file found." )
62
63
return {}
63
64
64
- logger .info ("Reading config file %s:" , config_file )
65
65
config_path = Path (config_file )
66
+ if not config_path .exists ():
67
+ logger .info ("Configuration file not found: %s." , config_path )
68
+ return {}
69
+
70
+ logger .info ("Reading config file %s:" , config_file )
71
+
66
72
if config_path .suffix == ".cfg" :
67
73
print_warning ("The .cfg file format is deprecated. Please use .toml instead." )
68
74
return read_ini_file (config_path )
69
75
elif config_path .suffix == ".toml" :
70
76
return read_toml_file (config_path )
71
- return {}
72
-
73
-
74
- def read_ini_file (file_path : Path ) -> Dict [str , Any ]: # noqa: C901
75
- """
76
- Parse an INI file and return a dictionary of sections and their options.
77
-
78
- Args:
79
- file_path: The path to the INI file.
80
-
81
- Returns:
82
- dict: A dictionary of sections and their options.
83
- """
84
- import configparser
85
-
86
- from bumpversion import autocast
87
-
88
- # Create a ConfigParser object and read the INI file
89
- config_parser = configparser .RawConfigParser ()
90
- if file_path .name == "setup.cfg" :
91
- config_parser = configparser .ConfigParser ()
92
-
93
- config_parser .read (file_path )
94
-
95
- # Create an empty dictionary to hold the parsed sections and options
96
- bumpversion_options : Dict [str , Any ] = {"files" : [], "parts" : {}}
97
-
98
- # Loop through each section in the INI file
99
- for section_name in config_parser .sections ():
100
- if not section_name .startswith ("bumpversion" ):
101
- continue
102
-
103
- section_parts = section_name .split (":" )
104
- num_parts = len (section_parts )
105
- options = {key : autocast .autocast_value (val ) for key , val in config_parser .items (section_name )}
106
-
107
- if num_parts == 1 : # bumpversion section
108
- bumpversion_options .update (options )
109
- serialize = bumpversion_options .get ("serialize" , [])
110
- if "message" in bumpversion_options and isinstance (bumpversion_options ["message" ], list ):
111
- bumpversion_options ["message" ] = "," .join (bumpversion_options ["message" ])
112
- if not isinstance (serialize , list ):
113
- bumpversion_options ["serialize" ] = [serialize ]
114
- elif num_parts > 1 and section_parts [1 ].startswith ("file" ):
115
- file_options = {
116
- "filename" : section_parts [2 ],
117
- }
118
- file_options .update (options )
119
- if "replace" in file_options and isinstance (file_options ["replace" ], list ):
120
- file_options ["replace" ] = "\n " .join (file_options ["replace" ])
121
- bumpversion_options ["files" ].append (file_options )
122
- elif num_parts > 1 and section_parts [1 ].startswith ("glob" ):
123
- file_options = {
124
- "glob" : section_parts [2 ],
125
- }
126
- file_options .update (options )
127
- if "replace" in file_options and isinstance (file_options ["replace" ], list ):
128
- file_options ["replace" ] = "\n " .join (file_options ["replace" ])
129
- bumpversion_options ["files" ].append (file_options )
130
- elif num_parts > 1 and section_parts [1 ].startswith ("part" ):
131
- bumpversion_options ["parts" ][section_parts [2 ]] = options
132
-
133
- # Return the dictionary of sections and options
134
- return bumpversion_options
77
+ else :
78
+ logger .info ("Unknown config file suffix: %s. Using defaults." , config_path .suffix )
79
+ return {}
135
80
136
81
137
82
def read_toml_file (file_path : Path ) -> Dict [str , Any ]:
@@ -180,7 +125,7 @@ def update_config_file(
180
125
181
126
config_path = Path (config_file )
182
127
if config_path .suffix != ".toml" :
183
- logger .info ("Could not find the current version in the config file: %s." , config_path )
128
+ logger .info ("You must have a `.toml` suffix to update the config file: %s." , config_path )
184
129
return
185
130
186
131
# TODO: Eventually this should be transformed into another default "files_to_modify" entry
@@ -197,57 +142,3 @@ def update_config_file(
197
142
198
143
updater = DataFileUpdater (datafile_config , config .version_config .part_configs )
199
144
updater .update_file (current_version , new_version , context , dry_run )
200
-
201
-
202
- def update_ini_config_file (
203
- config_file : Union [str , Path ], current_version : str , new_version : str , dry_run : bool = False
204
- ) -> None :
205
- """
206
- Update the current_version key in the configuration file.
207
-
208
- Instead of parsing and re-writing the config file with new information, it will use
209
- a regular expression to just replace the current_version value. The idea is it will
210
- avoid unintentional changes (like formatting) to the config file.
211
-
212
- Args:
213
- config_file: The configuration file to explicitly use.
214
- current_version: The serialized current version.
215
- new_version: The serialized new version.
216
- dry_run: True if the update should be a dry run.
217
- """
218
- cfg_current_version_regex = re .compile (
219
- f"(?P<section_prefix>\\ [bumpversion]\n [^[]*current_version\\ s*=\\ s*)(?P<version>{ current_version } )" ,
220
- re .MULTILINE ,
221
- )
222
-
223
- config_path = Path (config_file )
224
- existing_config = config_path .read_text ()
225
- if config_path .suffix == ".cfg" and cfg_current_version_regex .search (existing_config ):
226
- sub_str = f"\\ g<section_prefix>{ new_version } "
227
- new_config = cfg_current_version_regex .sub (sub_str , existing_config )
228
- else :
229
- logger .info ("Could not find the current version in the config file: %s." , config_path )
230
- return
231
-
232
- logger .info (
233
- "%s to config file %s:" ,
234
- "Would write" if dry_run else "Writing" ,
235
- config_path ,
236
- )
237
-
238
- logger .info (
239
- "\n " .join (
240
- list (
241
- context_diff (
242
- existing_config .splitlines (),
243
- new_config .splitlines (),
244
- fromfile = f"before { config_path } " ,
245
- tofile = f"after { config_path } " ,
246
- lineterm = "" ,
247
- )
248
- )
249
- )
250
- )
251
-
252
- if not dry_run :
253
- config_path .write_text (new_config )
0 commit comments