Skip to content

Commit

Permalink
ENH: Add single file and no bullet point option
Browse files Browse the repository at this point in the history
The single file options means that the file name is formatted
when it is set to False (and appending will never happen).

When `all_bullets` is set to false, then fragmets that should be
rendered as bullet points will have include the bullet itself.
In that case, bullets will be sorted to the front (bullets include
"*", "-", and "#." enumeration).
To make indentation of the ticket info easier, a `get_indent(text)`
function is exposed to the jinja template.
  • Loading branch information
seberg committed Sep 12, 2019
1 parent 4068ee4 commit 0409982
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ Towncrier has the following global options, which can be specified in the toml f
issue_format = "format string for {issue} (issue is the first part of fragment name)"
underlines: "=-~"
wrap = false # Wrap text to 79 characters
all_bullets = true # make all fragments bullet points
```
If a single file is used, the content of this file are overwritten each time.

Expand Down
40 changes: 37 additions & 3 deletions src/towncrier/_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def prefixed_lines():
# Takes the output from find_fragments above. Probably it would be useful to
# add an example output here. Next time someone digs deep enough to figure it
# out, please do so...
def split_fragments(fragments, definitions):
def split_fragments(fragments, definitions, all_bullets=True):

output = OrderedDict()

Expand All @@ -126,7 +126,14 @@ def split_fragments(fragments, definitions):

for (ticket, category, counter), content in section_fragments.items():

content = indent(content.strip(), u" ")[2:]
if all_bullets:
# By default all fragmetns are append by "-" automatically,
# and need to be indented because of that.
# (otherwise, assume they are formatted correctly)
content = indent(content.strip(), u" ")[2:]
else:
# Assume the text is formatted correctly
content = content.rstrip()

if definitions[category]["showcontent"] is False:
content = u""
Expand Down Expand Up @@ -161,6 +168,19 @@ def entry_key(entry):
return [issue_key(issue) for issue in issues]


def bullet_key(entry):
text, _ = entry
if not text:
return -1
if text[:2] == u"- ":
return 0
elif text[:2] == "* ":
return 1
elif text[:3] == u"#. ":
return 2
return 3


def render_issue(issue_format, issue):
if issue_format is None:
try:
Expand All @@ -181,6 +201,7 @@ def render_fragments(
wrap,
versiondata,
top_underline="=",
all_bullets=False,
):
"""
Render the fragments into a news file.
Expand Down Expand Up @@ -213,6 +234,8 @@ def render_fragments(
# - Fix the other thing (#1)
# - Fix the thing (#2, #7, #123)
entries.sort(key=entry_key)
if not all_bullets:
entries.sort(key=bullet_key)

# Then we put these nicely sorted entries back in an ordered dict
# for the template, after formatting each issue number
Expand All @@ -225,12 +248,23 @@ def render_fragments(

done = []

def get_indent(text):
# If bullets are not assumed and we wrap, the subsequent
# indentation depends on whether or not this is a bullet point.
# (it is probably usually best to disable wrapping in that case)
if all_bullets or text[:2] == u"- " or text[:2] == u"* ":
return u" "
elif text[:3] == "#. ":
return u" "
return u""

res = jinja_template.render(
sections=data,
definitions=definitions,
underlines=underlines,
versiondata=versiondata,
top_underline=top_underline,
get_indent=get_indent, # simplify indentation in the jinja template.
)

for line in res.split(u"\n"):
Expand All @@ -239,7 +273,7 @@ def render_fragments(
textwrap.fill(
line,
width=79,
subsequent_indent=u" ",
subsequent_indent=get_indent(line),
break_long_words=False,
break_on_hyphens=False,
)
Expand Down
9 changes: 9 additions & 0 deletions src/towncrier/_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ def parse_toml(config):
failing_option="single_file",
)

single_file = config.get("single_file", True)
if not isinstance(single_file, bool):
raise ValueError("`single_file` option must be a boolean: false or true.")

all_bullets = config.get("all_bullets", True)
if not isinstance(all_bullets, bool):
raise ValueError("`all_bullets` must be boolean: false or true.")

return {
"package": config.get("package", ""),
"package_dir": config.get("package_dir", "."),
Expand All @@ -93,4 +101,5 @@ def parse_toml(config):
"issue_format": config.get("issue_format"),
"underlines": config.get("underlines", _underlines),
"wrap": wrap,
"all_bullets": all_bullets,
}
3 changes: 2 additions & 1 deletion src/towncrier/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def __main(
)

click.echo("Rendering news fragments...", err=to_err)
fragments = split_fragments(fragments, definitions)
fragments = split_fragments(fragments, definitions, all_bullets=config["all_bullets"])

if project_version is None:
project_version = get_version(
Expand Down Expand Up @@ -158,6 +158,7 @@ def __main(
config["wrap"],
{"name": project_name, "version": project_version, "date": project_date},
top_underline=config["underlines"][0],
all_bullets=config["all_bullets"],
)

if draft:
Expand Down
8 changes: 8 additions & 0 deletions src/towncrier/newsfragments/158.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
There is now the option for ``all_bullets = false`` in the configuration.
Setting ``all_bullets`` to false means that news fragments have to include
the bullet point if they should be rendered as enumerations, otherwise
they are rendered directly (this means fragments can include a header.).
It is necessary to set this option to avoid (incorrect) automatic indentation
of multiline fragments that do not include bullet points.
The ``template-single-file-no-bullets.rst`` file gives an example template
using these options.
38 changes: 38 additions & 0 deletions src/towncrier/templates/template-single-file-no-bullets.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% set title = "{} {} Release Notes".format(versiondata.name, versiondata.version) %}
{{ "=" * title|length }}
{{ title }}
{{ "=" * title|length }}

{% for section, _ in sections.items() %}
{% set underline = underlines[0] %}{% if section %}{{ section }}
{{ underline * section|length }}{% set underline = underlines[1] %}

{% endif %}
{% if sections[section] %}
{% for category, val in definitions.items() if category in sections[section] %}

{{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }}

{% if definitions[category]['showcontent'] %}
{% for text, values in sections[section][category].items() %}
{{ text }}
{{ get_indent(text) }}({{values|join(', ') }})

{% endfor %}
{% else %}
- {{ sections[section][category]['']|join(', ') }}

{% endif %}
{% if sections[section][category]|length == 0 %}
No significant changes.

{% else %}
{% endif %}
{% endfor %}
{% else %}
No significant changes.


{% endif %}
{% endfor %}

0 comments on commit 0409982

Please sign in to comment.