|
1 | 1 | """Tests of the configuration utilities."""
|
2 | 2 |
|
3 | 3 | from pathlib import Path
|
4 |
| -from typing import Any |
| 4 | +from typing import Any, List |
5 | 5 |
|
6 | 6 | import tomlkit
|
7 | 7 | import pytest
|
8 | 8 | from pytest import param
|
9 | 9 |
|
10 |
| -from bumpversion.config.utils import get_all_file_configs, get_all_part_configs, resolve_glob_files |
| 10 | +from bumpversion.config.utils import get_all_file_configs, resolve_glob_files, glob_exclude_pattern |
11 | 11 | from bumpversion.config.models import FileChange
|
12 | 12 | from bumpversion.config import DEFAULTS
|
13 | 13 | from tests.conftest import inside_dir
|
@@ -37,7 +37,7 @@ def test_uses_defaults_for_missing_keys(self, tmp_path: Path):
|
37 | 37 |
|
38 | 38 | for key in FileChange.model_fields.keys():
|
39 | 39 | global_key = key if key != "ignore_missing_file" else "ignore_missing_files"
|
40 |
| - if key not in ["filename", "glob", "key_path"]: |
| 40 | + if key not in ["filename", "glob", "key_path", "glob_exclude"]: |
41 | 41 | file_val = getattr(file_configs[0], key)
|
42 | 42 | assert file_val == DEFAULTS[global_key]
|
43 | 43 |
|
@@ -113,3 +113,75 @@ def test_all_attributes_are_copied(self, tmp_path: Path):
|
113 | 113 | assert resolved_file.ignore_missing_version is True
|
114 | 114 | assert resolved_file.ignore_missing_file is True
|
115 | 115 | assert resolved_file.regex is True
|
| 116 | + |
| 117 | + def test_excludes_configured_patterns(self, tmp_path: Path): |
| 118 | + """Test that excludes configured patterns work.""" |
| 119 | + file1 = tmp_path.joinpath("setup.cfg") |
| 120 | + file2 = tmp_path.joinpath("subdir/setup.cfg") |
| 121 | + file1.touch() |
| 122 | + file2.parent.mkdir() |
| 123 | + file2.touch() |
| 124 | + |
| 125 | + file_cfg = FileChange( |
| 126 | + filename=None, |
| 127 | + glob="**/*.cfg", |
| 128 | + glob_exclude=["subdir/**"], |
| 129 | + key_path=None, |
| 130 | + parse=r"v(?P<major>\d+)", |
| 131 | + serialize=("v{major}",), |
| 132 | + search="v{current_version}", |
| 133 | + replace="v{new_version}", |
| 134 | + ignore_missing_version=True, |
| 135 | + ignore_missing_file=True, |
| 136 | + regex=True, |
| 137 | + ) |
| 138 | + with inside_dir(tmp_path): |
| 139 | + resolved_files = resolve_glob_files(file_cfg) |
| 140 | + |
| 141 | + assert len(resolved_files) == 1 |
| 142 | + |
| 143 | + |
| 144 | +class TestGlobExcludePattern: |
| 145 | + """Tests for the glob_exclude_pattern function.""" |
| 146 | + |
| 147 | + @pytest.mark.parametrize(["empty_pattern"], [param([], id="empty list"), param(None, id="None")]) |
| 148 | + def test_empty_list_returns_empty_string_pattern(self, empty_pattern: Any): |
| 149 | + """When passed an empty list, it should return a pattern that only matches an empty string.""" |
| 150 | + assert glob_exclude_pattern(empty_pattern).pattern == r"^$" |
| 151 | + |
| 152 | + @pytest.mark.parametrize( |
| 153 | + ["patterns", "expected"], |
| 154 | + [ |
| 155 | + param(["foo.txt", ""], "(?s:foo\\.txt)\\Z", id="empty string"), |
| 156 | + param(["foo.txt", None], "(?s:foo\\.txt)\\Z", id="None value"), |
| 157 | + param(["foo.txt", "", "bar.txt"], "(?s:foo\\.txt)\\Z|(?s:bar\\.txt)\\Z", id="Empty string in the middle"), |
| 158 | + ], |
| 159 | + ) |
| 160 | + def test_empty_values_are_excluded(self, patterns: List, expected: str): |
| 161 | + """Empty values are excluded from the compiled pattern.""" |
| 162 | + assert glob_exclude_pattern(patterns).pattern == expected |
| 163 | + |
| 164 | + def test_list_of_empty_patterns_return_empty_string_pattern(self): |
| 165 | + """When passed a list of empty strings, it should return a pattern that only matches an empty string.""" |
| 166 | + assert glob_exclude_pattern(["", "", None]).pattern == r"^$" |
| 167 | + |
| 168 | + def test_trailing_slash_appends_stars(self): |
| 169 | + """ |
| 170 | + When a string has a trailing slash, two asterisks are appended. |
| 171 | +
|
| 172 | + `fnmatch.translate` converts `**` to `.*` |
| 173 | + """ |
| 174 | + assert glob_exclude_pattern(["foo/"]).pattern == "(?s:foo/.*)\\Z" |
| 175 | + |
| 176 | + @pytest.mark.parametrize( |
| 177 | + ["file_path", "excluded"], |
| 178 | + [param("node_modules/foo/file.js", True), param("build/foo/file.js", True), param("code/file.js", False)], |
| 179 | + ) |
| 180 | + def test_output_pattern_matches_files(self, file_path: str, excluded: bool): |
| 181 | + """The output pattern should match file paths appropriately.""" |
| 182 | + exclude_matcher = glob_exclude_pattern(["node_modules/", "build/"]) |
| 183 | + |
| 184 | + if excluded: |
| 185 | + assert exclude_matcher.match(file_path) |
| 186 | + else: |
| 187 | + assert not exclude_matcher.match(file_path) |
0 commit comments