From 728edd30d18ec4d4601243dd7cf26a198ff1c2ab Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Mon, 5 Aug 2024 15:12:13 +0200 Subject: [PATCH 1/5] Update tests --- src/towncrier/test/test_build.py | 103 ++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 9 deletions(-) diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py index 4556cca3..e02469e2 100644 --- a/src/towncrier/test/test_build.py +++ b/src/towncrier/test/test_build.py @@ -15,7 +15,7 @@ from .._shell import cli from ..build import _main -from .helpers import read, with_git_project, with_project, write +from .helpers import read, read_pkg_resource, with_git_project, with_project, write class TestCli(TestCase): @@ -270,9 +270,7 @@ def run_order_scenario(sections, types): [[tool.towncrier.section]] path = "{section}" name = "{section}" - """.format( - section=section - ) + """.format(section=section) ) ) @@ -284,9 +282,7 @@ def run_order_scenario(sections, types): directory = "{type_}" name = "{type_}" showcontent = true - """.format( - type_=type_ - ) + """.format(type_=type_) ) ) @@ -1050,7 +1046,15 @@ def test_title_format_custom(self, runner): def test_title_format_custom_markdown(self, runner): """ A non-empty title format adds the specified title, and if the target filename is - markdown then the title is added as a markdown header. + markdown then the title is added as given by the config. + In this way, full control is given to the user. + We make this choice for markdown files + because markdown header levels depend on where in the file + the section is being written and require modifications in the same line, + hence there is no easy way to know what to do to get the header to be at the right level. + This avoids a repeat of the regression introduced in + [#610](https://github.com/twisted/towncrier/pull/610), + which mistakenly assumed that starting the line with '# ' would work in all use cases. """ with open("foo/newsfragments/123.feature", "w") as f: f.write("Adds levitation") @@ -1075,7 +1079,7 @@ def test_title_format_custom_markdown(self, runner): Draft only -- nothing has been written. What is seen below is what would be written. - # [20-01-2001] CUSTOM RELEASE for FooBarBaz version 7.8.9 + [20-01-2001] CUSTOM RELEASE for FooBarBaz version 7.8.9 ### Features @@ -1089,6 +1093,87 @@ def test_title_format_custom_markdown(self, runner): self.assertEqual(0, result.exit_code) self.assertEqual(expected_output, result.output) + @with_project( + config=""" + [tool.towncrier] + package = "foo" + filename = "NEWS.md" + title_format = "### [{project_date}] CUSTOM RELEASE for {name} version {version}" + template = "custom_template.md" + """ + ) + def test_markdown_injected_after_header(self, runner): + """ + Test that we can inject markdown after some fixed header + and have the injected markdown header levels set at the desired level. + This avoids a repeat of the regression introduced in + [#610](https://github.com/twisted/towncrier/pull/610), + which mistakenly assumed that starting the line with '# ' would work in all use cases. + """ + write("foo/newsfragments/123.feature", "Adds levitation") + write( + "NEWS.md", + contents=""" + # Top title + + ## Section title + + Some text explaining something + + another line + + ## Release notes + + + + a footer! + """, + dedent=True, + ) + + default_template = read_pkg_resource("templates/default.md") + write( + "custom_template.md", + contents=default_template.replace( + "### {{ definitions", "#### {{ definitions" + ), + ) + + result = runner.invoke(_main, ["--date", "01-01-2001"], catch_exceptions=False) + + with open("foo/newsfragments/123.feature", "w") as f: + f.write("Adds levitation") + + self.assertEqual(0, result.exit_code, result.output) + output = read("NEWS.md") + + expected_output = dedent( + """ + # Top title + + ## Section title + + Some text explaining something + + another line + + ## Release notes + + + + ### [01-01-2001] CUSTOM RELEASE for Foo version 1.2.3 + + #### Features + + - Adds levitation (#123) + + + a footer! + """ + ) + + self.assertEqual(expected_output, output) + @with_project( config=""" [tool.towncrier] From ccba12c10101941ce69b817382e126e3e0e7a32a Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Mon, 5 Aug 2024 15:12:40 +0200 Subject: [PATCH 2/5] Apply fix --- src/towncrier/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/towncrier/build.py b/src/towncrier/build.py index 546ef113..3d183925 100644 --- a/src/towncrier/build.py +++ b/src/towncrier/build.py @@ -232,7 +232,7 @@ def __main( name=project_name, version=project_version, project_date=project_date ) if is_markdown: - parts = [f"# {top_line}"] + parts = [top_line] else: parts = [top_line, config.underlines[0] * len(top_line)] parts.append(rendered) From 0146da830204620964333532fbe49a67a08a66b3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 13:13:14 +0000 Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/towncrier/test/test_build.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py index e02469e2..f97fa91d 100644 --- a/src/towncrier/test/test_build.py +++ b/src/towncrier/test/test_build.py @@ -270,7 +270,9 @@ def run_order_scenario(sections, types): [[tool.towncrier.section]] path = "{section}" name = "{section}" - """.format(section=section) + """.format( + section=section + ) ) ) @@ -282,7 +284,9 @@ def run_order_scenario(sections, types): directory = "{type_}" name = "{type_}" showcontent = true - """.format(type_=type_) + """.format( + type_=type_ + ) ) ) From a9c708b5e7cf3f0f40a6bf2a56fc34c29e48fe5e Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Mon, 5 Aug 2024 15:16:36 +0200 Subject: [PATCH 4/5] News fragment --- src/towncrier/newsfragments/651.bugfix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/towncrier/newsfragments/651.bugfix.md diff --git a/src/towncrier/newsfragments/651.bugfix.md b/src/towncrier/newsfragments/651.bugfix.md new file mode 100644 index 00000000..3b3f4c0e --- /dev/null +++ b/src/towncrier/newsfragments/651.bugfix.md @@ -0,0 +1 @@ +Control of the header formatting is once again completely up to the user when they are writing markdown files (fixes a regression introduced in [#610](https://github.com/twisted/towncrier/pull/610)). From 8c03b86eed0de9a3649e3570e2bcb4e9ec6867ba Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Mon, 5 Aug 2024 15:22:01 +0200 Subject: [PATCH 5/5] Update docs --- docs/configuration.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index fbbe730b..c55299ba 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -80,7 +80,10 @@ Top level keys ``""`` by default. - Formatted titles are appended a line of ``=`` on the following line (reStructuredText title format) unless the template has an ``.md`` suffix, in which case the title will instead be prefixed with ``#`` (markdown title format). + When using reStructuredText, formatted titles are underlined using the ``underlines`` configuration. + For titles, the first value from ``underlines`` is used to create the underline (which is inserted on the line following the title). + If the template has an ``.md`` suffix, we assume we are looking at markdown format and the title is applied as, i.e. full control over the title format is given to the user. + This choice is made because setting the correct markdown header level automatically is non-trivial (mainly because you don't know what context the generated CHANGELOG entries are being written into). ``issue_format`` A format string for rendering the issue/ticket number in newsfiles.