Skip to content

Commit

Permalink
Merge branch 'trunk' into 432-poetry-version
Browse files Browse the repository at this point in the history
  • Loading branch information
SmileyChris authored May 22, 2024
2 parents 5bee9d4 + 2bde077 commit 783e122
Show file tree
Hide file tree
Showing 19 changed files with 157 additions and 34 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,36 @@ jobs:
if: ${{ matrix.task.run-if }}


pre-commit:
name: Check pre-commit integration
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up python
uses: actions/setup-python@v5
with:
python-version: 3.12

- name: Install dependencies
run: python -m pip install pre-commit

- name: Install pre-commit
run: |
pre-commit install
- name: Update pre-commit
run: |
pre-commit autoupdate
- name: Run pre-commit
run: |
pre-commit run -a
pypi-publish:
name: Check tag and publish
# Only trigger this for tag changes.
Expand Down Expand Up @@ -292,6 +322,7 @@ jobs:
- test-windows
- coverage
- check
- pre-commit
steps:
- name: Require all successes
uses: re-actors/alls-green@3a2de129f0713010a71314c74e33c0e3ef90e696
Expand Down
9 changes: 7 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ci:

repos:
- repo: https://github.com/psf/black
rev: 24.3.0
rev: 24.4.2
hooks:
- id: black

Expand All @@ -26,10 +26,15 @@ repos:
- id: flake8

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: debug-statements
- id: check-toml
- id: check-yaml

- repo: https://github.com/twisted/towncrier
rev: 23.11.0
hooks:
- id: towncrier-check
9 changes: 8 additions & 1 deletion RELEASE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,14 @@ In ``src/towncrier/_version.py`` the version is set using ``incremental`` such a

Commit and push the changes.

Merge the commit in the main branch.
Merge the commit in the main branch, **without using squash**.

We tag the release based on a commit from the release branch.
If we merge with squash,
the release tag commit will no longer be found in the main branch history.
With a squash merge, the whole branch history is lost.
This causes the `pre-commit autoupdate` to fail.
See `PR590 <https://github.com/twisted/towncrier/pull/590>`_ for more details.

You can announce the release over IRC or Gitter.

Expand Down
6 changes: 5 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
import os

from datetime import date

from towncrier import __version__ as towncrier_version
Expand Down Expand Up @@ -90,7 +92,9 @@
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
if os.environ.get("READTHEDOCS_VERSION_NAME", "trunk") not in ("trunk", "latest"):
# Remove the "Edit on GitHub" link for non-trunk versions of the docs
html_theme_options = {"top_of_page_buttons": []}

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
Expand Down
4 changes: 2 additions & 2 deletions docs/pre-commit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Usage with the default configuration
repos:
- repo: https://github.com/twisted/towncrier
rev: 22.13.0 # run 'pre-commit autoupdate' to update
rev: 23.11.0 # run 'pre-commit autoupdate' to update
hooks:
- id: towncrier-check
Expand All @@ -30,7 +30,7 @@ News fragments are stored in ``changelog.d/`` in the root of the repository and
repos:
- repo: https://github.com/twisted/towncrier
rev: 22.13.0 # run 'pre-commit autoupdate' to update
rev: 23.11.0 # run 'pre-commit autoupdate' to update
hooks:
- id: towncrier-update
files: $changelog\.d/
Expand Down
2 changes: 2 additions & 0 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ You should get an output similar to this::

Note: if you configure a Markdown file (for example, ``filename = "CHANGES.md"``) in your configuration file, the titles will be output in Markdown format instead.

Note: all files (news fragments, the news file, the configuration file, and templates) are encoded and are expected to be encoded as UTF-8.


Producing News Files In Production
----------------------------------
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ dependencies = [
dev = [
"packaging",
"sphinx >= 5",
"furo",
"furo >= 2024.05.06",
"twisted",
"nox",
]
Expand Down
4 changes: 2 additions & 2 deletions src/towncrier/_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import textwrap

from collections import defaultdict
from pathlib import Path
from typing import Any, DefaultDict, Iterable, Iterator, Mapping, Sequence

from jinja2 import Template
Expand Down Expand Up @@ -111,8 +112,7 @@ def find_fragments(

full_filename = os.path.join(section_dir, basename)
fragment_filenames.append(full_filename)
with open(full_filename, "rb") as f:
data = f.read().decode("utf8", "replace")
data = Path(full_filename).read_text(encoding="utf-8", errors="replace")

if (ticket, category, counter) in file_content:
raise ValueError(
Expand Down
36 changes: 25 additions & 11 deletions src/towncrier/_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,22 @@

from __future__ import annotations

import sys

from pathlib import Path
from typing import Any


if sys.version_info < (3, 10):
# Compatibility shim for newline parameter to write_text, added in 3.10
def _newline_write_text(path: Path, content: str, **kwargs: Any) -> None:
with path.open("w", **kwargs) as strm: # pragma: no branch
strm.write(content)

else:

def _newline_write_text(path: Path, content: str, **kwargs: Any) -> None:
path.write_text(content, **kwargs)


def append_to_newsfile(
Expand Down Expand Up @@ -37,15 +52,17 @@ def append_to_newsfile(
if top_line and top_line in prev_body:
raise ValueError("It seems you've already produced newsfiles for this version?")

# Leave newlines alone. This probably leads to inconsistent newlines,
# because we've loaded existing content with universal newlines, but that's
# the original behavior.
with news_file.open("w", encoding="utf8", newline="") as f:
if header:
f.write(header)
_newline_write_text(
news_file,
# If there is no previous body that means we're writing a brand new news file.
# We don't want extra whitespace at the end of this new file.
f.write(content + prev_body if prev_body else content.rstrip() + "\n")
header + (content + prev_body if prev_body else content.rstrip() + "\n"),
encoding="utf-8",
# Leave newlines alone. This probably leads to inconsistent newlines,
# because we've loaded existing content with universal newlines, but that's
# the original behavior.
newline="",
)


def _figure_out_existing_content(
Expand All @@ -64,10 +81,7 @@ def _figure_out_existing_content(
# Non-existent files have no existing content.
return "", ""

# If we didn't use universal newlines here, we wouldn't find *start_string*
# which usually contains a `\n`.
with news_file.open(encoding="utf8") as f:
content = f.read()
content = Path(news_file).read_text(encoding="utf-8")

t = content.split(start_string, 1)
if len(t) == 2:
Expand Down
9 changes: 5 additions & 4 deletions src/towncrier/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
Build a combined news file from news fragments.
"""


from __future__ import annotations

import os
import sys

from datetime import date
from pathlib import Path

import click

Expand Down Expand Up @@ -166,11 +166,12 @@ def __main(
click.echo("Loading template...", err=to_err)
if isinstance(config.template, tuple):
template = (
resources.files(config.template[0]).joinpath(config.template[1]).read_text()
resources.files(config.template[0])
.joinpath(config.template[1])
.read_text(encoding="utf-8")
)
else:
with open(config.template, encoding="utf-8") as tmpl:
template = tmpl.read()
template = Path(config.template).read_text(encoding="utf-8")

click.echo("Finding news fragments...", err=to_err)

Expand Down
16 changes: 9 additions & 7 deletions src/towncrier/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

import os

from pathlib import Path

import click

from ._settings import config_option_help, load_config_from_options
Expand Down Expand Up @@ -165,27 +167,27 @@ def __main(
if edit:
if content == DEFAULT_CONTENT:
content = ""
content = _get_news_content_from_user(content)
content = _get_news_content_from_user(content, extension=filename_ext)
if not content:
click.echo("Aborted creating news fragment due to empty message.")
ctx.exit(1)

with open(segment_file, "w") as f:
f.write(content)
if config.create_eof_newline and content and not content.endswith("\n"):
f.write("\n")
add_newline = bool(
config.create_eof_newline and content and not content.endswith("\n")
)
Path(segment_file).write_text(content + "\n" * add_newline, encoding="utf-8")

click.echo(f"Created news fragment at {segment_file}")


def _get_news_content_from_user(message: str) -> str:
def _get_news_content_from_user(message: str, extension: str = "") -> str:
initial_content = """
# Please write your news content. Lines starting with '#' will be ignored, and
# an empty message aborts.
"""
if message:
initial_content = f"{message}\n{initial_content}"
content = click.edit(initial_content)
content = click.edit(initial_content, extension=extension or ".txt")
if content is None:
return message
all_lines = content.split("\n")
Expand Down
1 change: 1 addition & 0 deletions src/towncrier/newsfragments/561.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add explicit encoding to read_text.
Empty file.
1 change: 1 addition & 0 deletions src/towncrier/newsfragments/591.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Leveraged pathlib in most file operations.
1 change: 1 addition & 0 deletions src/towncrier/newsfragments/594.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The temporary file ``towncrier create`` creates now uses the correct ``.rst`` or ``.md`` extension, which may help your editor with with syntax highlighting.
1 change: 1 addition & 0 deletions src/towncrier/newsfragments/596.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove github edit link in non-trunk versions of docs
1 change: 1 addition & 0 deletions src/towncrier/newsfragments/597.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix readthedocs to keep the edit link for ``latest`` in addition to ``trunk``.
2 changes: 1 addition & 1 deletion src/towncrier/test/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def read_pkg_resource(path: str) -> str:
"""
Read *path* from the towncrier package.
"""
return (resources.files("towncrier") / path).read_text("utf8")
return (resources.files("towncrier") / path).read_text("utf-8")


def with_isolated_runner(fn: Callable[..., Any]) -> Callable[..., Any]:
Expand Down
56 changes: 54 additions & 2 deletions src/towncrier/test/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def test_edit_without_comments(self):
self._test_success(content=content, additional_args=["--edit"])
mock_edit.assert_called_once_with(
"\n# Please write your news content. Lines starting "
"with '#' will be ignored, and\n# an empty message aborts.\n"
"with '#' will be ignored, and\n# an empty message aborts.\n",
extension=".rst",
)

def test_edit_with_comment(self):
Expand All @@ -87,6 +88,56 @@ def test_edit_abort(self):
self.assertEqual([], os.listdir("foo/newsfragments"))
self.assertEqual(1, result.exit_code)

def test_edit_markdown_extension(self):
"""
The temporary file extension used when editing is ``.md`` if the main filename
also uses that extension.
"""

with mock.patch("click.edit") as mock_edit:
mock_edit.return_value = "This is line 1"
self._test_success(
content=["This is line 1"],
config=dedent(
"""\
[tool.towncrier]
package = "foo"
filename = "README.md"
"""
),
additional_args=["--edit"],
)
mock_edit.assert_called_once_with(
"\n# Please write your news content. Lines starting "
"with '#' will be ignored, and\n# an empty message aborts.\n",
extension=".md",
)

def test_edit_unknown_extension(self):
"""
The temporary file extension used when editing is ``.txt`` if it the main
filename isn't ``.rst`` or ``.md``.
"""

with mock.patch("click.edit") as mock_edit:
mock_edit.return_value = "This is line 1"
self._test_success(
content=["This is line 1"],
config=dedent(
"""\
[tool.towncrier]
package = "foo"
filename = "README.FIRST"
"""
),
additional_args=["--edit"],
)
mock_edit.assert_called_once_with(
"\n# Please write your news content. Lines starting "
"with '#' will be ignored, and\n# an empty message aborts.\n",
extension=".txt",
)

def test_content(self):
"""
When creating a new fragment the content can be passed as a
Expand Down Expand Up @@ -132,7 +183,8 @@ def test_message_and_edit(self):
)
mock_edit.assert_called_once_with(
f"{content_line}\n\n# Please write your news content. Lines starting "
"with '#' will be ignored, and\n# an empty message aborts.\n"
"with '#' will be ignored, and\n# an empty message aborts.\n",
extension=".rst",
)

def test_different_directory(self):
Expand Down

0 comments on commit 783e122

Please sign in to comment.