Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use common code between draft and not for combining top line and rendered #303

Merged
merged 15 commits into from
Mar 15, 2022
Merged
4 changes: 2 additions & 2 deletions src/towncrier/_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,14 @@ def render_issue(issue_format, issue):
def render_fragments(
template,
issue_format,
top_line,
fragments,
definitions,
underlines,
wrap,
versiondata,
top_underline="=",
all_bullets=False,
render_title=True,
):
"""
Render the fragments into a news file.
Expand Down Expand Up @@ -289,7 +289,7 @@ def get_indent(text):
return u""

res = jinja_template.render(
top_line=top_line,
render_title=render_title,
sections=data,
definitions=definitions,
underlines=underlines,
Expand Down
25 changes: 22 additions & 3 deletions src/towncrier/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,30 +141,49 @@ def __main(
top_line = config["title_format"].format(
name=project_name, version=project_version, project_date=project_date
)
render_title_with_fragments = False
render_title_separately = True
elif config["title_format"] is False:
# This is an odd check but since we support both "" and False with
# different effects we have to do something a bit abnormal here.
top_line = ""
render_title_separately = False
render_title_with_fragments = False
else:
top_line = ""
render_title_separately = False
render_title_with_fragments = True

rendered = render_fragments(
# The 0th underline is used for the top line
template,
config["issue_format"],
top_line,
fragments,
definitions,
config["underlines"][1:],
config["wrap"],
{"name": project_name, "version": project_version, "date": project_date},
top_underline=config["underlines"][0],
all_bullets=config["all_bullets"],
render_title=render_title_with_fragments,
)

if render_title_separately:
content = "\n".join([
top_line,
config["underlines"][0] * len(top_line),
rendered,
])
else:
content = rendered

if draft:
click.echo(
"Draft only -- nothing has been written.\n"
"What is seen below is what would be written.\n",
err=to_err,
)
click.echo(rendered)
click.echo(content)
else:
click.echo("Writing to newsfile...", err=to_err)
start_string = config["start_string"]
Expand All @@ -181,7 +200,7 @@ def __main(
news_file,
start_string,
top_line,
rendered,
content,
single_file=config["single_file"],
)

Expand Down
1 change: 1 addition & 0 deletions src/towncrier/newsfragments/105.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The extra newline between the title and rendered content when using ``--draft`` is no longer inserted.
7 changes: 3 additions & 4 deletions src/towncrier/templates/default.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
{% if top_line %}
{{ top_line }}
{{ top_underline * ((top_line)|length)}}
{% elif versiondata.name %}
{% if render_title %}
{% if versiondata.name %}
{{ versiondata.name }} {{ versiondata.version }} ({{ versiondata.date }})
{{ top_underline * ((versiondata.name + versiondata.version + versiondata.date)|length + 4)}}
{% else %}
{{ versiondata.version }} ({{ versiondata.date }})
{{ top_underline * ((versiondata.version + versiondata.date)|length + 3)}}
{% endif %}
{% endif %}
{% for section, _ in sections.items() %}
{% set underline = underlines[0] %}{% if section %}{{section}}
{{ underline * section|length }}{% set underline = underlines[1] %}
Expand Down
2 changes: 2 additions & 0 deletions src/towncrier/templates/hr-between-versions.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{% if render_title %}
{% if versiondata.name %}
{{ versiondata.name }} {{ versiondata.version }} ({{ versiondata.date }})
{{ top_underline * ((versiondata.name + versiondata.version + versiondata.date)|length + 4)}}
{% else %}
{{ versiondata.version }} ({{ versiondata.date }})
{{ top_underline * ((versiondata.version + versiondata.date)|length + 3)}}
{% endif %}
{% endif %}
{% for section, _ in sections.items() %}
{% set underline = underlines[0] %}{% if section %}{{section}}
{{ underline * section|length }}{% set underline = underlines[1] %}
Expand Down
2 changes: 2 additions & 0 deletions src/towncrier/templates/single-file-no-bullets.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{% if render_title %}
{% if versiondata.name %}
{{ versiondata.name }} {{ versiondata.version }} ({{ versiondata.date }})
{{ top_underline * ((versiondata.name + versiondata.version + versiondata.date)|length + 4)}}
{% else %}
{{ versiondata.version }} ({{ versiondata.date }})
{{ top_underline * ((versiondata.version + versiondata.date)|length + 3)}}
{% endif %}
{% endif %}
{% for section, _ in sections.items() %}
{% set underline = underlines[0] %}{% if section %}{{section}}
{{ underline * section|length }}{% set underline = underlines[1] %}
Expand Down
90 changes: 80 additions & 10 deletions src/towncrier/test/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,12 +740,25 @@ def test_title_format_false(self):
[tool.towncrier]
package = "foo"
title_format = false
template = "template.rst"
"""))
os.mkdir("foo")
os.mkdir("foo/newsfragments")
# Towncrier ignores .rst extension
with open("foo/newsfragments/124.feature.rst", "w") as f:
f.write("Extends levitation")
with open("template.rst", "w") as f:
f.write(dedent("""\
Here's a hardcoded title added by the template
==============================================
{% for section in sections %}
{% set underline = "-" %}
{% for category, val in definitions.items() if category in sections[section] %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like all these jinja directives from the template are not used in this test.

I don't understand why you would like to have title_format = false and a custom template.
With a custom template you can just don't include the title part without having to use False.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this template should be able to have all these normal template bits removed. Change incoming.

Does it matter why you would want that scenario if it is documented and released functionality? Or is this question more about making sure we have a common understanding of the feature than questioning if the situation should be tested? I haven't really thought through what I think the configuration design ought to be as I'm targeting a bugfix+feature release without introducing breaking changes (nor deprecations).

None the less, false is exactly for the case where you specify a template that provides its own title. If you don't specify false then you will (should? i think?... :[) get the default title before whatever your template does. I do feel funny about the existing non-empty string or empty string/unspecified or false possibilities for title_format. I guess I see the use cases along the lines of 'default title format and template' (unspecified or empty string), 'the default template is fine but i want to change just the title format' (non-empty string), and 'gosh darn it let me just write everything in my custom template' (false).

Hopefully this helps... this is definitely an area that strikes me as simply confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it matter why you would want that scenario if it is documented and released functionality? Or is this question more about making sure we have a common understanding of the feature than questioning if the situation should be tested?

It's more about understanding the feature and its valid use cases.

I imagine someone reading this test 1 year in the future, looking at a bug and will say: Why you need this feature with a custom template.

So I prefer to have a test in which the feature is tested like in real file, and not using a combination of configuration option that are possible, but will never be used.

At the same time, I think that this test is wrong. We should have a full test for the default template itself.

This should also be a test for the {% if render_title %} part of the default template


{% for text, values in sections[section][category]|dictsort(by='value') %}
- {{ text }}

{% endfor %}
{% endfor %}
{% endfor %}
"""))

result = runner.invoke(
_main,
Expand All @@ -767,13 +780,8 @@ def test_title_format_false(self):
Draft only -- nothing has been written.
What is seen below is what would be written.

FooBarBaz 7.8.9 (20-01-2001)
============================

Features
--------

- Extends levitation (#124)
Here's a hardcoded title added by the template
==============================================

""")

Expand Down Expand Up @@ -836,3 +844,65 @@ def test_start_string(self):
""")

self.assertEqual(expected_output, output)

def test_with_topline_and_template_and_draft(self):
"""
Spacing is proper when drafting with a topline and a template.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what the difference between test_title_format_custom and this test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It at least differs in that this specifies a custom template while test_title_format_custom leaves the default template in use. When writing this test it ended up a bit confusing to me too how all the bits were interacting but it did seem to recreate the issue reported at #105.

I feel like the existing implementation code had evolved and needed cleanup but as it was it offered corners where specifying a title format _with_ a custom template _and_ draft (and maybe something about the title-less feature section?) could result in some unique bug.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. But I think that this test can be removed.
Now that we use the exact same output for draft and final,#105 should be fixed.

I would prefer not to have this tests as it's long and confusing.

The test only checks the output of draft.

A good test for #105 would had generated the output with and without draft and compare them to make sure they are exactly the same.

But I don't think that we need extra test for that.

"""
runner = CliRunner()

with runner.isolated_filesystem():
with open("pyproject.toml", "w") as f:
f.write(dedent("""\
[tool.towncrier]
title_format = "{version} - {project_date}"
template = "template.rst"

[[tool.towncrier.type]]
directory = "feature"
name = ""
showcontent = true
"""))
os.mkdir("newsfragments")
with open("newsfragments/123.feature", "w") as f:
f.write("Adds levitation")
with open("template.rst", "w") as f:
f.write(dedent("""\
{% for section in sections %}
{% set underline = "-" %}
{% for category, val in definitions.items() if category in sections[section] %}

{% for text, values in sections[section][category]|dictsort(by='value') %}
- {{ text }}

{% endfor %}
{% endfor %}
{% endfor %}
"""))

result = runner.invoke(
_main,
[
"--version=7.8.9",
"--name=foo",
"--date=20-01-2001",
"--draft",
],
)

expected_output = dedent("""\
Loading template...
Finding news fragments...
Rendering news fragments...
Draft only -- nothing has been written.
What is seen below is what would be written.

7.8.9 - 20-01-2001
==================

- Adds levitation

""")

self.assertEqual(0, result.exit_code, result.output)
self.assertEqual(expected_output, result.output)
34 changes: 0 additions & 34 deletions src/towncrier/test/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

from __future__ import absolute_import, division

from textwrap import dedent

import pkg_resources

from twisted.trial.unittest import TestCase
Expand Down Expand Up @@ -131,7 +129,6 @@ def test_basic(self):
output = render_fragments(
template,
None,
"",
fragments,
definitions,
["-", "~"],
Expand Down Expand Up @@ -176,7 +173,6 @@ def test_basic(self):
output = render_fragments(
template,
None,
"",
fragments,
definitions,
["*", "^"],
Expand Down Expand Up @@ -222,7 +218,6 @@ def test_issue_format(self):
output = render_fragments(
template,
u"xx{issue}",
"",
fragments,
definitions,
["-", "~"],
Expand Down Expand Up @@ -281,7 +276,6 @@ def test_line_wrapping(self):
output = render_fragments(
template,
None,
"",
fragments,
definitions,
["-", "~"],
Expand Down Expand Up @@ -333,38 +327,10 @@ def test_line_wrapping_disabled(self):
output = render_fragments(
template,
None,
"",
fragments,
definitions,
["-", "~"],
wrap=False,
versiondata={"name": "MyProject", "version": "1.0", "date": "never"},
)
self.assertEqual(output, expected_output)

def test_title_format_specified(self):
"""
Title format replaces default top line rendering.
"""
template = pkg_resources.resource_string(
"towncrier", "templates/default.rst"
).decode("utf8")

fragments = split_fragments(fragments={}, definitions=OrderedDict())
output = render_fragments(
template=template,
issue_format=None,
top_line="A custom top line",
fragments=fragments,
definitions=OrderedDict(),
underlines=["-", "~"],
wrap=False,
versiondata={"name": "MyProject", "version": "1.0", "date": "never"},
)

expected_output = dedent(u"""\
A custom top line
=================
""")

self.assertEqual(expected_output, output)
3 changes: 0 additions & 3 deletions src/towncrier/test/test_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ def test_append_at_top(self):
render_fragments(
template,
None,
"",
fragments,
definitions,
["-", "~"],
Expand Down Expand Up @@ -214,7 +213,6 @@ def test_append_at_top_with_hint(self):
render_fragments(
template,
None,
"",
fragments,
definitions,
["-", "~"],
Expand Down Expand Up @@ -246,7 +244,6 @@ def test_multiple_file_no_start_string(self):
content = render_fragments(
template=template,
issue_format=None,
top_line="",
fragments=fragments,
definitions=definitions,
underlines=["-", "~"],
Expand Down