Skip to content

Commit 449b70a

Browse files
committed
Added documentation about regular expressions
1 parent a295a32 commit 449b70a

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

docsrc/reference/search-and-replace-config.md

+32
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
Bump-my-version uses a combination of [template strings](https://docs.python.org/3/library/string.html#format-string-syntax) using a [formatting context](formatting-context.md) and regular expressions to search the configured files for the old or current version and replace the text with the new version.
44

5+
Bump My Version falls back to using a simple string search if the search template is not a valid regular expression or if the `no-regex` flag is `True`. The search template is always rendered using the formatting context. The basic logic is:
6+
7+
1. Escape the formatting context for use in a regular expression.
8+
2. Render the search string using the escaped formatting context.
9+
3. Attempt to compile the rendered search string as a regular expression.
10+
4. If the rendered search string is a valid regular expression, use it.
11+
5. If the rendered search string is _not_ a valid regular expression or the `no-regex` flag is `True`, use the search string rendered with the unescaped context.
12+
513
## Using template strings
614

715
Both the search and replace templates are rendered using the [formatting context](formatting-context.md). However, only the search template is also treated as a regular expression. The replacement fields available in the formatting context are enclosed in curly braces `{}`.
@@ -54,3 +62,27 @@ Gets rendered to:
5462
```
5563

5664
This string is used as a regular expression pattern to search.
65+
66+
## Regular expression special characters
67+
68+
The `.`, `^`, `$`, `*`, `+`, `?`, `()`, `[]`, `{}`, `\`, `|` characters are special characters in regular expressions. If your search string contains these characters, you must escape them with a backslash (`\`) to treat them as literal characters or set the `no-regex` flag to `True`.
69+
70+
For example, if you are looking for this string in a file:
71+
72+
```text
73+
[Unreleased] 2023-07-17
74+
```
75+
76+
and you use this search pattern:
77+
78+
```text
79+
[Unreleased] \\d{{4}}-\\d{{2}}-\\d{{2}}
80+
```
81+
82+
Bump My Version will not find the string. While the rendered regular expression `[Unreleased] \d{4}-\d{2}-\d{2}` is valid, it is not searching for the literal `[Unreleased]`. Instead, it matches a single character in the list `U`, `n`, `r`, `e`, `l`, `a`, `s`, `d`.
83+
84+
You must escape the `[` and `]` to treat them as literal characters:
85+
86+
```text
87+
\[Unreleased\] \\d{{4}}-\\d{{2}}-\\d{{2}}
88+
```

tests/test_files.py

+24
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,30 @@ def test_regex_search(tmp_path: Path) -> None:
419419
assert version_path.read_text() == f"Release {now} '1.2.4'"
420420

421421

422+
def test_regex_search_with_escaped_chars(tmp_path: Path) -> None:
423+
"""A search that uses special characters is not treated as a regex."""
424+
# Arrange
425+
version_path = tmp_path / "VERSION"
426+
version_path.write_text("## [Release] 1.2.3 1234-56-78")
427+
428+
overrides = {
429+
"current_version": "1.2.3",
430+
"search": r"## \[Release\] {current_version} \d{{4}}-\d{{2}}-\d{{2}}",
431+
"replace": r"## [Release] {new_version} {now:%Y-%m-%d}",
432+
"files": [{"filename": str(version_path)}],
433+
}
434+
conf, version_config, current_version = get_config_data(overrides)
435+
new_version = current_version.bump("patch", version_config.order)
436+
cfg_files = [files.ConfiguredFile(file_cfg, version_config) for file_cfg in conf.files]
437+
438+
# Act
439+
files.modify_files(cfg_files, current_version, new_version, get_context(conf))
440+
441+
# Assert
442+
now = datetime.now().isoformat()[:10]
443+
assert version_path.read_text() == f"## [Release] 1.2.4 {now}"
444+
445+
422446
def test_bad_regex_search(tmp_path: Path, caplog) -> None:
423447
"""A search string not meant to be a regex is still found and replaced."""
424448
# Arrange

0 commit comments

Comments
 (0)