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

Refactor _writer & bring to 100% coverage #419

Merged
merged 18 commits into from
Sep 3, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ as the option 'title_format', already exists in newsfile, ``ValueError`` will be
you "already produced newsfiles for this version".

If ``single_file`` is set to ``false`` instead, each versioned ``towncrier build`` will generate a
separate newsfile, whose name is formatted as the patten given by option ``filename``.
separate newsfile, whose name is formatted as the pattern given by option ``filename``.
For example, if ``filename="{version}-notes.rst"``, then the release note with version "7.8.9" will
be written to the file "7.8.9-notes.rst". If the newsfile already exists, its content
will be overwriten with new release note, without throwing a ``ValueError`` warning.
Expand Down
66 changes: 44 additions & 22 deletions src/towncrier/_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,55 @@


def append_to_newsfile(
directory, filename, start_string, top_line, content, single_file=True
directory, filename, start_string, top_line, content, single_file
):
"""
Write *content* to *directory*/*filename* behind *start_string*.

Double-check *top_line* (i.e. the release header) is not already in the
file.

if *single_file* is True, add it to an existing file, otherwise create a
fresh one.
"""
news_file = os.path.join(directory, filename)

if single_file:
if not os.path.exists(news_file):
existing_content = ""
else:
with open(news_file, encoding="utf8") as f:
existing_content = f.read()
existing_content = existing_content.split(start_string, 1)
else:
existing_content = [""]

if top_line and top_line in existing_content[-1]:
header, prev_body = _figure_out_existing_content(
news_file, start_string, single_file
)

if top_line and top_line in prev_body:
raise ValueError("It seems you've already produced newsfiles for this version?")

with open(os.path.join(directory, filename), "wb") as f:
with open(news_file, "w", encoding="utf8") as f:
hynek marked this conversation as resolved.
Show resolved Hide resolved
if header:
f.write(header)

f.write(content)

if prev_body:
f.write(f"\n\n{prev_body}")


def _figure_out_existing_content(news_file, start_string, single_file):
"""
Try to read *news_file* and split it into header (everything before
*start_string*) and the old body (everything after *start_string*).

If there's no *start_string*, return empty header.

Empty file and per-release files have neither.
"""
if not single_file or not os.path.exists(news_file):
# Per-release news files always start empty.
# Non-existent files have no existing content.
return "", ""

with open(news_file, encoding="utf8") as f:
content = f.read()

if len(existing_content) > 1:
f.write(existing_content.pop(0).rstrip().encode("utf8"))
if start_string:
f.write(("\n\n" + start_string + "\n").encode("utf8"))
t = content.split(start_string, 1)
if len(t) == 2:
return f"{t[0].rstrip()}\n\n{start_string}\n", t[1].lstrip()

f.write(content.encode("utf8"))
if existing_content:
if existing_content[0]:
f.write(b"\n\n")
f.write(existing_content[0].lstrip().encode("utf8"))
return "", content.lstrip()
Empty file.
4 changes: 3 additions & 1 deletion src/towncrier/test/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ def do_build_once_with(version, fragment_file, fragment):
"01-01-2001",
"--yes",
],
catch_exceptions=False,
)
# not git repository, manually remove fragment file
Path(f"newsfragments/{fragment_file}").unlink()
Expand Down Expand Up @@ -1010,7 +1011,7 @@ def test_start_string(self):
with open("newsfragments/123.feature", "w") as f:
f.write("Adds levitation")
with open("NEWS.rst", "w") as f:
f.write("a line\n\nanother\n\nRelease notes start marker\n")
f.write("a line\n\nanother\n\nRelease notes start marker\na footer!\n")

result = runner.invoke(
_main,
Expand Down Expand Up @@ -1045,6 +1046,7 @@ def test_start_string(self):
- Adds levitation (#123)


a footer!
"""
)

Expand Down
3 changes: 3 additions & 0 deletions src/towncrier/test/test_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ def test_append_at_top(self):
wrap=True,
versiondata={"name": "MyProject", "version": "1.0", "date": "never"},
),
True,
hynek marked this conversation as resolved.
Show resolved Hide resolved
)

with open(os.path.join(tempdir, "NEWS.rst")) as f:
Expand Down Expand Up @@ -221,6 +222,7 @@ def test_append_at_top_with_hint(self):
wrap=True,
versiondata={"name": "MyProject", "version": "1.0", "date": "never"},
),
True,
hynek marked this conversation as resolved.
Show resolved Hide resolved
)

with open(os.path.join(tempdir, "NEWS.rst")) as f:
Expand Down Expand Up @@ -259,6 +261,7 @@ def test_multiple_file_no_start_string(self):
start_string=None,
top_line="",
content=content,
single_file=True,
)

with open(os.path.join(tempdir, "NEWS.rst")) as f:
Expand Down