From 0aa818b5ad8d21f62811464fb7f4570414c9c9ea Mon Sep 17 00:00:00 2001 From: Arthur Eigenbrot Date: Fri, 2 Aug 2024 11:51:54 -0600 Subject: [PATCH 1/5] Add failing tests for build and check that lack of wildcard support I.e., these are what we want to fix --- src/towncrier/test/test_build.py | 9 ++++++++- src/towncrier/test/test_check.py | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py index 4556cca3..3df0f585 100644 --- a/src/towncrier/test/test_build.py +++ b/src/towncrier/test/test_build.py @@ -1588,7 +1588,8 @@ def test_uncommitted_files(self, runner, commit): config=""" [tool.towncrier] package = "foo" - ignore = ["template.jinja", "CAPYBARAS.md"] + ignore = ["template.jinja", "CAPYBARAS.md", \ + "star_wildcard*", "question_wildcard_?", "seq_wildcard_[ab]"] """ ) def test_ignored_files(self, runner): @@ -1603,6 +1604,12 @@ def test_ignored_files(self, runner): f.write("This markdown file has been manually ignored") with open("foo/newsfragments/.gitignore", "w") as f: f.write("gitignore is automatically ignored") + with open("foo/newsfragments/star_wildcard_bar", "w") as f: + f.write("Manually ignored with * wildcard") + with open("foo/newsfragments/question_wildcard_1", "w") as f: + f.write("Manually ignored with ? wildcard") + with open("foo/newsfragments/seq_wildcard_a", "w") as f: + f.write("Manually ignored with [] wildcard") result = runner.invoke(_main, ["--draft"]) self.assertEqual(0, result.exit_code, result.output) diff --git a/src/towncrier/test/test_check.py b/src/towncrier/test/test_check.py index 7305b11d..ebf215be 100644 --- a/src/towncrier/test/test_check.py +++ b/src/towncrier/test/test_check.py @@ -476,7 +476,11 @@ def test_ignored_files(self, runner): """ When `ignore` is set in config, files with those names are ignored. """ - create_project("pyproject.toml", extra_config='ignore = ["template.jinja"]') + create_project( + "pyproject.toml", + extra_config='ignore = ["template.jinja", "star_wildcard*", "question_wildcard_?", ' + '"seq_wildcard_[ab]"]', + ) write( "foo/newsfragments/124.feature", @@ -484,6 +488,16 @@ def test_ignored_files(self, runner): ) write("foo/newsfragments/template.jinja", "This is manually ignored") write("foo/newsfragments/.gitignore", "gitignore is automatically ignored") + write("foo/newsfragments/star_wildcard_foo", "Manually ignored with * wildcard") + write("foo/newsfragments/STAR_WILDCARD_bar", "Manually ignored with * wildcard") + write( + "foo/newsfragments/question_wildcard_1", "Manually ignored with ? wildcard" + ) + write( + "foo/newsfragments/QUESTION_WILDCARD_1", "Manually ignored with ? wildcard" + ) + write("foo/newsfragments/seq_wildcard_a", "Manually ignored with [] wildcard") + write("foo/newsfragments/SEQ_WILDCARD_b", "Manually ignored with [] wildcard") commit("add stuff") result = runner.invoke(towncrier_check, ["--compare-with", "main"]) From 80452be953e9b469fdcbf543413cf79bfe205f49 Mon Sep 17 00:00:00 2001 From: Arthur Eigenbrot Date: Fri, 2 Aug 2024 13:20:28 -0600 Subject: [PATCH 2/5] Use `fnmatch` to allow for pattern matching in "ignore" config option This still captures exact matches (i.e., the previous behavior) --- src/towncrier/_builder.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/towncrier/_builder.py b/src/towncrier/_builder.py index d1f65f98..276e7755 100644 --- a/src/towncrier/_builder.py +++ b/src/towncrier/_builder.py @@ -9,6 +9,7 @@ import textwrap from collections import defaultdict +from fnmatch import fnmatch from pathlib import Path from typing import Any, DefaultDict, Iterable, Iterator, Mapping, NamedTuple, Sequence @@ -142,7 +143,12 @@ def find_fragments( file_content = {} for basename in files: - if basename.lower() in ignored_files: + if any( + [ + fnmatch(basename.lower(), ignore_pattern) + for ignore_pattern in ignored_files + ] + ): continue issue, category, counter = parse_newfragment_basename( From 6867fdde389d020502acee320c600b975f42cf3b Mon Sep 17 00:00:00 2001 From: Arthur Eigenbrot Date: Fri, 2 Aug 2024 13:24:17 -0600 Subject: [PATCH 3/5] Update docs for "ignore" config option to mention new wildcard ability --- docs/configuration.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configuration.rst b/docs/configuration.rst index 4f253cd8..e7b55e21 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -132,6 +132,7 @@ Top level keys ``ignore`` A case-insensitive list of filenames in the news fragments directory to ignore. + Wildcard matching is supported via the `fnmatch `_ function. ``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). From 065de270dcfbac62b55a25ac920c2f63f1f39cc9 Mon Sep 17 00:00:00 2001 From: Arthur Eigenbrot Date: Fri, 2 Aug 2024 13:32:46 -0600 Subject: [PATCH 4/5] Add changelog fragment --- src/towncrier/newsfragments/644.feature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/towncrier/newsfragments/644.feature.rst diff --git a/src/towncrier/newsfragments/644.feature.rst b/src/towncrier/newsfragments/644.feature.rst new file mode 100644 index 00000000..4c09a148 --- /dev/null +++ b/src/towncrier/newsfragments/644.feature.rst @@ -0,0 +1 @@ +Config `ignore` option now supports wildcard matching via `fnmatch `_. From 90b665e54b9c6600c2f349311734e6c471ca2fb8 Mon Sep 17 00:00:00 2001 From: Arthur Eigenbrot Date: Mon, 5 Aug 2024 08:39:58 -0600 Subject: [PATCH 5/5] Simplify wildcard tests cases to only cover a single file We can trust that `fnmatch` works the way it's supposed to. --- src/towncrier/test/test_build.py | 8 ++------ src/towncrier/test/test_check.py | 13 ++----------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py index 3df0f585..31bbae29 100644 --- a/src/towncrier/test/test_build.py +++ b/src/towncrier/test/test_build.py @@ -1588,13 +1588,13 @@ def test_uncommitted_files(self, runner, commit): config=""" [tool.towncrier] package = "foo" - ignore = ["template.jinja", "CAPYBARAS.md", \ - "star_wildcard*", "question_wildcard_?", "seq_wildcard_[ab]"] + ignore = ["template.jinja", "CAPYBARAS.md", "seq_wildcard_[ab]"] """ ) def test_ignored_files(self, runner): """ When `ignore` is set in config, files with those names are ignored. + Configuration supports wildcard matching with `fnmatch`. """ with open("foo/newsfragments/123.feature", "w") as f: f.write("This has valid filename (control case)") @@ -1604,10 +1604,6 @@ def test_ignored_files(self, runner): f.write("This markdown file has been manually ignored") with open("foo/newsfragments/.gitignore", "w") as f: f.write("gitignore is automatically ignored") - with open("foo/newsfragments/star_wildcard_bar", "w") as f: - f.write("Manually ignored with * wildcard") - with open("foo/newsfragments/question_wildcard_1", "w") as f: - f.write("Manually ignored with ? wildcard") with open("foo/newsfragments/seq_wildcard_a", "w") as f: f.write("Manually ignored with [] wildcard") diff --git a/src/towncrier/test/test_check.py b/src/towncrier/test/test_check.py index ebf215be..baa33561 100644 --- a/src/towncrier/test/test_check.py +++ b/src/towncrier/test/test_check.py @@ -475,11 +475,11 @@ def test_in_different_dir_with_nondefault_newsfragments_directory(self, runner): def test_ignored_files(self, runner): """ When `ignore` is set in config, files with those names are ignored. + Configuration supports wildcard matching with `fnmatch`. """ create_project( "pyproject.toml", - extra_config='ignore = ["template.jinja", "star_wildcard*", "question_wildcard_?", ' - '"seq_wildcard_[ab]"]', + extra_config='ignore = ["template.jinja", "star_wildcard*"]', ) write( @@ -489,15 +489,6 @@ def test_ignored_files(self, runner): write("foo/newsfragments/template.jinja", "This is manually ignored") write("foo/newsfragments/.gitignore", "gitignore is automatically ignored") write("foo/newsfragments/star_wildcard_foo", "Manually ignored with * wildcard") - write("foo/newsfragments/STAR_WILDCARD_bar", "Manually ignored with * wildcard") - write( - "foo/newsfragments/question_wildcard_1", "Manually ignored with ? wildcard" - ) - write( - "foo/newsfragments/QUESTION_WILDCARD_1", "Manually ignored with ? wildcard" - ) - write("foo/newsfragments/seq_wildcard_a", "Manually ignored with [] wildcard") - write("foo/newsfragments/SEQ_WILDCARD_b", "Manually ignored with [] wildcard") commit("add stuff") result = runner.invoke(towncrier_check, ["--compare-with", "main"])