Skip to content

Commit 3c93f13

Browse files
committed
Refactor in response to review
- Change `build_ignore_filenames` to `ignore` in config - Remove `--strict` option from `towncrier build`
1 parent 0993534 commit 3c93f13

File tree

9 files changed

+86
-82
lines changed

9 files changed

+86
-82
lines changed

docs/cli.rst

-5
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ also remove the fragments directory if now empty.
6464

6565
Don't delete news fragments after the build and don't ask for confirmation whether to delete or keep the fragments.
6666

67-
.. option:: --strict
68-
69-
Fail if there are any news fragments that have invalid filenames.
70-
This is automatically turned on if ``build_ignore_filenames`` has been set in the configuration.
71-
7267

7368
``towncrier create``
7469
--------------------

docs/configuration.rst

+5-3
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,12 @@ Top level keys
130130

131131
``true`` by default.
132132

133-
``build_ignore_filenames``
134-
A list of filenames in the news fragments directory to ignore when building the news file.
133+
``ignore``
134+
A list of filenames in the news fragments directory to ignore.
135135

136-
If this is configured, it turns on the ``--strict`` build mode which will fail if there are any news fragment files not in this list that have invalid filenames. Note that if a template is used, it should also be included here.
136+
``towncrier check`` will fail if there are any news fragment files that have invalid filenames, except for those in the list. ``towncrier build`` will likewise fail, but only if this list has been configured (set to an empty list if there are no files to ignore).
137+
138+
Note that if a custom template is stored in the news fragment directory, you should add it to this list.
137139

138140
``None`` by default.
139141

docs/tutorial.rst

-5
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,6 @@ Create this folder::
4747

4848
The ``.gitignore`` will remain and keep Git from not tracking the directory.
4949

50-
If needed, you can also specify a list of filenames for ``towncrier`` to ignore in the news fragments directory::
51-
52-
[tool.towncrier]
53-
build_ignore_filenames = ["README.rst"]
54-
5550

5651
Detecting Version
5752
-----------------

src/towncrier/_builder.py

+5-11
Original file line numberDiff line numberDiff line change
@@ -107,21 +107,16 @@ def __call__(self, section_directory: str = "") -> str:
107107
def find_fragments(
108108
base_directory: str,
109109
config: Config,
110-
strict: bool | None,
110+
strict: bool,
111111
) -> tuple[Mapping[str, Mapping[tuple[str, str, int], str]], list[tuple[str, str]]]:
112112
"""
113113
Sections are a dictonary of section names to paths.
114114
115-
In strict mode, raise ClickException if any fragments have an invalid name.
115+
If strict, raise ClickException if any fragments have an invalid name.
116116
"""
117-
if strict is None:
118-
# If strict mode is not set, turn it on only if build_ignore_filenames is set
119-
# (this maintains backward compatibility).
120-
strict = config.build_ignore_filenames is not None
121-
122117
ignored_files = {".gitignore"}
123-
if config.build_ignore_filenames:
124-
ignored_files.update(config.build_ignore_filenames)
118+
if config.ignore:
119+
ignored_files.update(config.ignore)
125120

126121
get_section_path = FragmentsPath(base_directory, config)
127122

@@ -142,7 +137,6 @@ def find_fragments(
142137
file_content = {}
143138

144139
for basename in files:
145-
# Skip files that are deliberately ignored
146140
if basename in ignored_files:
147141
continue
148142

@@ -154,7 +148,7 @@ def find_fragments(
154148
raise ClickException(
155149
f"Invalid news fragment name: {basename}\n"
156150
"If this filename is deliberate, add it to "
157-
"'build_ignore_filenames' in your configuration."
151+
"'ignore' in your configuration."
158152
)
159153
continue
160154
assert issue is not None

src/towncrier/_settings/load.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Config:
5454
orphan_prefix: str = "+"
5555
create_eof_newline: bool = True
5656
create_add_extension: bool = True
57-
build_ignore_filenames: list[str] | None = None
57+
ignore: list[str] | None = None
5858

5959

6060
class ConfigError(ClickException):

src/towncrier/build.py

+7-15
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,6 @@ def _validate_answer(ctx: Context, param: Option, value: bool) -> bool:
106106
help="Do not ask for confirmations. But keep news fragments.",
107107
callback=_validate_answer,
108108
)
109-
@click.option(
110-
"--strict",
111-
"strict",
112-
default=None,
113-
flag_value=True,
114-
help=(
115-
"Fail if there are any news fragments that have invalid filenames (this is "
116-
"automatically turned on if 'build_ignore_filenames' has been set in the "
117-
"configuration)."
118-
),
119-
)
120109
def _main(
121110
draft: bool,
122111
directory: str | None,
@@ -126,7 +115,6 @@ def _main(
126115
project_date: str | None,
127116
answer_yes: bool,
128117
answer_keep: bool,
129-
strict: bool | None,
130118
) -> None:
131119
"""
132120
Build a combined news file from news fragment.
@@ -141,7 +129,6 @@ def _main(
141129
project_date,
142130
answer_yes,
143131
answer_keep,
144-
strict,
145132
)
146133
except ConfigError as e:
147134
print(e, file=sys.stderr)
@@ -157,7 +144,6 @@ def __main(
157144
project_date: str | None,
158145
answer_yes: bool,
159146
answer_keep: bool,
160-
strict: bool | None,
161147
) -> None:
162148
"""
163149
The main entry point.
@@ -192,7 +178,13 @@ def __main(
192178

193179
click.echo("Finding news fragments...", err=to_err)
194180

195-
fragment_contents, fragment_files = find_fragments(base_directory, config, strict)
181+
fragment_contents, fragment_files = find_fragments(
182+
base_directory,
183+
config,
184+
# Fail if any fragment filenames are invalid only if ignore list is set
185+
# (this maintains backward compatibility):
186+
strict=(config.ignore is not None),
187+
)
196188
fragment_filenames = [filename for (filename, _category) in fragment_files]
197189

198190
click.echo("Rendering news fragments...", err=to_err)
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
``towncrier check`` will now fail if any news fragments have invalid filenames.
22

3-
Added a new configuration option called ``build_ignore_filenames`` that allows you to specify a list of filenames that should be ignored. If this is set, ``towncrier build`` will also fail if any filenames are invalid, except for those in the list.
3+
Added a new configuration option called ``ignore`` that allows you to specify a list of filenames that should be ignored. If this is set, ``towncrier build`` will also fail if any filenames are invalid, except for those in the list.

src/towncrier/test/test_build.py

+36-30
Original file line numberDiff line numberDiff line change
@@ -1535,55 +1535,61 @@ def test_orphans_in_non_showcontent_markdown(self, runner):
15351535
config="""
15361536
[tool.towncrier]
15371537
package = "foo"
1538-
build_ignore_filenames = ["template.jinja", "CAPYBARAS.md"]
1538+
ignore = ["template.jinja", "CAPYBARAS.md"]
15391539
"""
15401540
)
1541-
def test_invalid_fragment_names(self, runner):
1541+
def test_ignored_files(self, runner):
15421542
"""
1543-
When build_ignore_filenames is set, files with those names are ignored.
1543+
When `ignore` is set in config, files with those names are ignored.
15441544
"""
1545-
opts = ["--draft", "--date", "01-01-2001", "--version", "1.0.0"]
1546-
# Valid filename:
15471545
with open("foo/newsfragments/123.feature", "w") as f:
1548-
f.write("Adds levitation")
1549-
# Files that should be ignored:
1546+
f.write("This has valid filename (control case)")
15501547
with open("foo/newsfragments/template.jinja", "w") as f:
1551-
f.write("Jinja template")
1548+
f.write("This template has been manually ignored")
15521549
with open("foo/newsfragments/CAPYBARAS.md", "w") as f:
1553-
f.write("Peanut butter")
1554-
# Automatically ignored:
1550+
f.write("This markdown file has been manually ignored")
15551551
with open("foo/newsfragments/.gitignore", "w") as f:
1556-
f.write("!.gitignore")
1552+
f.write("gitignore is automatically ignored")
15571553

1558-
result = runner.invoke(_main, opts)
1559-
# Should succeed
1554+
result = runner.invoke(
1555+
_main, ["--draft", "--date", "01-01-2001", "--version", "1.0.0"]
1556+
)
15601557
self.assertEqual(0, result.exit_code, result.output)
15611558

1562-
# Invalid filename:
1559+
@with_project(
1560+
config="""
1561+
[tool.towncrier]
1562+
package = "foo"
1563+
ignore = []
1564+
"""
1565+
)
1566+
def test_invalid_fragment_name(self, runner):
1567+
"""
1568+
When `ignore` is set in config, invalid filenames cause failure.
1569+
"""
1570+
with open("foo/newsfragments/123.feature", "w") as f:
1571+
f.write("This has valid filename (control case)")
15631572
with open("foo/newsfragments/feature.124", "w") as f:
1564-
f.write("Extends levitation")
1573+
f.write("This has the issue and category the wrong way round")
15651574

1566-
result = runner.invoke(_main, opts)
1567-
# Should now fail
1575+
result = runner.invoke(
1576+
_main, ["--draft", "--date", "01-01-2001", "--version", "1.0.0"]
1577+
)
15681578
self.assertEqual(1, result.exit_code, result.output)
15691579
self.assertIn("Invalid news fragment name: feature.124", result.output)
15701580

15711581
@with_project()
1572-
def test_invalid_fragment_names_strict(self, runner):
1582+
def test_no_ignore_configured(self, runner):
15731583
"""
1574-
When using --strict, any invalid filenames will cause an error even if
1575-
build_ignore_filenames is NOT set.
1584+
When `ignore` is not set in config, invalid filenames are skipped.
1585+
1586+
This maintains backward compatibility with before we added `ignore`
1587+
to the configuration spec.
15761588
"""
1577-
opts = ["--draft", "--date", "01-01-2001", "--version", "1.0.0"]
1578-
# Invalid filename:
15791589
with open("foo/newsfragments/feature.124", "w") as f:
1580-
f.write("Extends levitation")
1590+
f.write("This has the issue and category the wrong way round")
15811591

1582-
result = runner.invoke(_main, opts)
1583-
# Should succeed in normal mode
1592+
result = runner.invoke(
1593+
_main, ["--draft", "--date", "01-01-2001", "--version", "1.0.0"]
1594+
)
15841595
self.assertEqual(0, result.exit_code, result.output)
1585-
1586-
result = runner.invoke(_main, [*opts, "--strict"])
1587-
# Should now fail
1588-
self.assertEqual(1, result.exit_code, result.output)
1589-
self.assertIn("Invalid news fragment name: feature.124", result.output)

src/towncrier/test/test_check.py

+31-11
Original file line numberDiff line numberDiff line change
@@ -472,21 +472,41 @@ def test_in_different_dir_with_nondefault_newsfragments_directory(self, runner):
472472
)
473473

474474
@with_isolated_runner
475-
def test_invalid_fragment_name(self, runner):
476-
create_project("pyproject.toml")
477-
opts = ["--compare-with", "main"]
475+
def test_ignored_files(self, runner):
476+
"""
477+
When `ignore` is set in config, files with those names are ignored.
478+
"""
479+
create_project("pyproject.toml", extra_config='ignore = ["template.jinja"]')
478480

479-
write("foo/bar.py", "# Scorpions!")
480-
write("foo/newsfragments/123.feature", "Adds scorpions")
481-
write("foo/newsfragments/.gitignore", "!.gitignore")
481+
write(
482+
"foo/newsfragments/123.feature",
483+
"This fragment has valid name (control case)",
484+
)
485+
write("foo/newsfragments/template.jinja", "This is manually ignored")
486+
write("foo/newsfragments/.gitignore", "gitignore is automatically ignored")
482487
commit("add stuff")
483488

484-
result = runner.invoke(towncrier_check, opts)
489+
result = runner.invoke(towncrier_check, ["--compare-with", "main"])
485490
self.assertEqual(0, result.exit_code, result.output)
486491

487-
# Make invalid filename:
488-
os.rename("foo/newsfragments/123.feature", "foo/newsfragments/feature.123")
492+
@with_isolated_runner
493+
def test_invalid_fragment_name(self, runner):
494+
"""
495+
Fails if a news fragment has an invalid name, even if `ignore` is not set in
496+
the config.
497+
"""
498+
create_project("pyproject.toml")
499+
500+
write(
501+
"foo/newsfragments/123.feature",
502+
"This fragment has valid name (control case)",
503+
)
504+
write(
505+
"foo/newsfragments/feature.124",
506+
"This has issue and category wrong way round",
507+
)
508+
commit("add stuff")
489509

490-
result = runner.invoke(towncrier_check, opts)
510+
result = runner.invoke(towncrier_check, ["--compare-with", "main"])
491511
self.assertEqual(1, result.exit_code, result.output)
492-
self.assertIn("Invalid news fragment name: feature.123", result.output)
512+
self.assertIn("Invalid news fragment name: feature.124", result.output)

0 commit comments

Comments
 (0)