0
# File Operations
1
2
Pattern-based file modification system for updating version strings across multiple files with configurable search and replace patterns. Supports both simple text replacement and complex structured data file updates with comprehensive logging and validation.
3
4
## Capabilities
5
6
### Configured File Management
7
8
Core class for handling version updates in individual files according to configuration specifications.
9
10
```python { .api }
11
class ConfiguredFile:
12
"""
13
Handles version changes in individual files per configuration.
14
15
Manages file reading, pattern matching, version replacement, and writing
16
with support for regex patterns, structured data files, and validation.
17
"""
18
19
def __init__(
20
self,
21
file_change: FileChange,
22
version_config: VersionConfig
23
) -> None:
24
"""
25
Initialize configured file with change specification.
26
27
Args:
28
file_change: File modification configuration
29
version_config: Version parsing and formatting configuration
30
"""
31
32
def update_file(
33
self,
34
current_version: Version,
35
new_version: Version,
36
context: Dict[str, Any],
37
dry_run: bool = False
38
) -> None:
39
"""
40
Update file with new version strings.
41
42
Searches for current version patterns and replaces with new version
43
according to configured search/replace patterns and options.
44
45
Args:
46
current_version: Current Version object
47
new_version: New Version object
48
context: Template context for formatting
49
dry_run: Preview changes without modifying file
50
51
Raises:
52
VersionNotFoundError: Version pattern not found in file
53
FileNotFoundError: File doesn't exist and not configured to ignore
54
"""
55
56
@property
57
def filename(self) -> str:
58
"""File path being managed."""
59
60
@property
61
def search_for(self) -> str:
62
"""Search pattern used for finding version strings."""
63
64
@property
65
def replace_with(self) -> str:
66
"""Replacement pattern for new version strings."""
67
68
class FileUpdater:
69
"""
70
Base class for updating file content with version changes.
71
72
Handles text-based file modifications with pattern matching,
73
validation, and change logging capabilities.
74
"""
75
76
def __init__(self, file_change: FileChange) -> None:
77
"""Initialize file updater with change configuration."""
78
79
def update_file(
80
self,
81
search_for: str,
82
replace_with: str,
83
dry_run: bool = False
84
) -> None:
85
"""
86
Update file content with search and replace operation.
87
88
Args:
89
search_for: Pattern to search for
90
replace_with: Replacement string
91
dry_run: Preview without modifying file
92
"""
93
94
class DataFileUpdater(FileUpdater):
95
"""
96
Specialized updater for structured data files.
97
98
Handles JSON, TOML, and YAML files by parsing structure,
99
updating specific keys, and preserving formatting.
100
"""
101
102
def update_file(
103
self,
104
search_for: str,
105
replace_with: str,
106
dry_run: bool = False
107
) -> None:
108
"""
109
Update structured data file at specified key path.
110
111
Parses file format, navigates to key path, updates value,
112
and writes back with preserved formatting.
113
"""
114
```
115
116
### File Operation Functions
117
118
High-level functions for managing multiple files and resolving configurations.
119
120
```python { .api }
121
def modify_files(
122
files: List[ConfiguredFile],
123
current_version: Version,
124
new_version: Version,
125
context: Dict[str, Any],
126
dry_run: bool = False
127
) -> None:
128
"""
129
Apply version changes to list of configured files.
130
131
Processes multiple files in sequence, updating version strings
132
according to each file's configuration with comprehensive logging.
133
134
Args:
135
files: List of ConfiguredFile objects to update
136
current_version: Current Version object
137
new_version: New Version object
138
context: Template context for pattern formatting
139
dry_run: Preview changes without modifying files
140
141
Raises:
142
VersionNotFoundError: Version not found in one or more files
143
"""
144
145
def resolve_file_config(
146
files_config: List[FileChange],
147
version_config: VersionConfig
148
) -> List[ConfiguredFile]:
149
"""
150
Convert file change configurations into configured file objects.
151
152
Creates ConfiguredFile instances from FileChange specifications,
153
applying version configuration and validating file paths.
154
155
Args:
156
files_config: List of FileChange configurations
157
version_config: Version parsing/formatting configuration
158
159
Returns:
160
List of ConfiguredFile objects ready for updates
161
"""
162
163
def contains_pattern(search: re.Pattern, contents: str) -> bool:
164
"""
165
Check if file contents contain regex pattern.
166
167
Args:
168
search: Compiled regex pattern
169
contents: File contents to search
170
171
Returns:
172
True if pattern found, False otherwise
173
"""
174
175
def log_changes(
176
file_path: str,
177
file_content_before: str,
178
file_content_after: str,
179
dry_run: bool = False
180
) -> None:
181
"""
182
Log file changes with diff output.
183
184
Displays unified diff showing changes made to file content
185
with color formatting and dry-run indicators.
186
187
Args:
188
file_path: Path to file being modified
189
file_content_before: Original file content
190
file_content_after: Modified file content
191
dry_run: Whether this is a dry-run preview
192
"""
193
```
194
195
## File Configuration Patterns
196
197
### Basic Text Replacement
198
199
Simple search and replace in text files:
200
201
```python
202
from bumpversion.config.models import FileChange
203
204
# Basic version replacement
205
file_config = FileChange(
206
filename="setup.py",
207
search="version='{current_version}'",
208
replace="version='{new_version}'"
209
)
210
211
# Using default patterns (searches for current_version, replaces with new_version)
212
file_config = FileChange(filename="src/mypackage/__init__.py")
213
```
214
215
### Regex Patterns
216
217
Advanced pattern matching with regular expressions:
218
219
```python
220
# Regex-based replacement
221
file_config = FileChange(
222
filename="version.txt",
223
search=r"Version:\s*{current_version}",
224
replace="Version: {new_version}",
225
regex=True
226
)
227
228
# Complex regex with capture groups
229
file_config = FileChange(
230
filename="Dockerfile",
231
search=r"(LABEL version=){current_version}",
232
replace=r"\1{new_version}",
233
regex=True
234
)
235
```
236
237
### Structured Data Files
238
239
Updates to JSON, TOML, and YAML files using key paths:
240
241
```python
242
# Update JSON file at specific key
243
file_config = FileChange(
244
filename="package.json",
245
key_path="version"
246
)
247
248
# Update nested TOML key
249
file_config = FileChange(
250
filename="pyproject.toml",
251
key_path="project.version"
252
)
253
254
# Update YAML with custom patterns
255
file_config = FileChange(
256
filename="chart.yaml",
257
key_path="version",
258
search="{current_version}",
259
replace="{new_version}"
260
)
261
```
262
263
### Glob Patterns
264
265
Apply configurations to multiple files matching patterns:
266
267
```python
268
# Update all Python files in src/
269
file_config = FileChange(
270
glob="src/**/*.py",
271
search="__version__ = '{current_version}'",
272
replace="__version__ = '{new_version}'"
273
)
274
275
# Update version in all markdown files
276
file_config = FileChange(
277
glob="docs/*.md",
278
search="Version {current_version}",
279
replace="Version {new_version}"
280
)
281
```
282
283
### Error Handling Options
284
285
Configure behavior for missing files and versions:
286
287
```python
288
# Ignore if file doesn't exist
289
file_config = FileChange(
290
filename="optional_file.txt",
291
ignore_missing_file=True
292
)
293
294
# Ignore if version pattern not found
295
file_config = FileChange(
296
filename="changelog.md",
297
search="## Version {current_version}",
298
replace="## Version {new_version}",
299
ignore_missing_version=True
300
)
301
```
302
303
## Usage Examples
304
305
### Basic File Updates
306
307
```python
308
from bumpversion.files import ConfiguredFile, modify_files
309
from bumpversion.config.models import FileChange
310
from bumpversion.versioning.version_config import VersionConfig
311
312
# Create file configurations
313
file_changes = [
314
FileChange(filename="setup.py"),
315
FileChange(
316
filename="src/mypackage/__init__.py",
317
search="__version__ = '{current_version}'",
318
replace="__version__ = '{new_version}'"
319
)
320
]
321
322
# Create version config
323
version_config = VersionConfig(
324
parse=r"(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)",
325
serialize=["{major}.{minor}.{patch}"],
326
search="{current_version}",
327
replace="{new_version}",
328
part_configs={}
329
)
330
331
# Create configured files
332
from bumpversion.files import resolve_file_config
333
configured_files = resolve_file_config(file_changes, version_config)
334
335
# Update files
336
from bumpversion.versioning.models import Version
337
current_version = Version({"major": "1", "minor": "0", "patch": "0"}, None)
338
new_version = Version({"major": "1", "minor": "0", "patch": "1"}, None)
339
340
modify_files(
341
files=configured_files,
342
current_version=current_version,
343
new_version=new_version,
344
context={"current_version": "1.0.0", "new_version": "1.0.1"},
345
dry_run=True # Preview changes
346
)
347
```
348
349
### Individual File Operations
350
351
```python
352
from bumpversion.files import ConfiguredFile
353
354
# Create configured file
355
file_change = FileChange(
356
filename="VERSION",
357
search="{current_version}",
358
replace="{new_version}"
359
)
360
361
configured_file = ConfiguredFile(file_change, version_config)
362
363
# Update individual file
364
configured_file.update_file(
365
current_version=current_version,
366
new_version=new_version,
367
context={"current_version": "1.0.0", "new_version": "1.0.1"},
368
dry_run=False
369
)
370
```
371
372
### Structured Data File Updates
373
374
```python
375
# Update package.json version
376
json_file = FileChange(
377
filename="package.json",
378
key_path="version"
379
)
380
381
# Update pyproject.toml version
382
toml_file = FileChange(
383
filename="pyproject.toml",
384
key_path="project.version"
385
)
386
387
# Update Kubernetes manifest
388
yaml_file = FileChange(
389
filename="k8s/deployment.yaml",
390
key_path="spec.template.spec.containers[0].image",
391
search="myapp:{current_version}",
392
replace="myapp:{new_version}"
393
)
394
395
configured_files = resolve_file_config([json_file, toml_file, yaml_file], version_config)
396
modify_files(configured_files, current_version, new_version, context)
397
```
398
399
### Advanced Pattern Matching
400
401
```python
402
# Complex regex replacement
403
complex_file = FileChange(
404
filename="docs/installation.md",
405
search=r"(pip install mypackage==){current_version}",
406
replace=r"\1{new_version}",
407
regex=True
408
)
409
410
# Multiple pattern file
411
multi_pattern_file = FileChange(
412
filename="README.md",
413
search="Version {current_version}",
414
replace="Version {new_version}"
415
)
416
417
# Date-based replacement with context
418
date_file = FileChange(
419
filename="CHANGELOG.md",
420
search="## Unreleased",
421
replace="## {new_version} ({now:%Y-%m-%d})"
422
)
423
```
424
425
### Error Handling and Validation
426
427
```python
428
# Graceful error handling
429
robust_config = FileChange(
430
filename="optional-config.ini",
431
search="version = {current_version}",
432
replace="version = {new_version}",
433
ignore_missing_file=True,
434
ignore_missing_version=True
435
)
436
437
# Strict validation (default)
438
strict_config = FileChange(
439
filename="critical-file.py",
440
search="VERSION = '{current_version}'",
441
replace="VERSION = '{new_version}'"
442
# Will raise exceptions if file missing or version not found
443
)
444
```