Skip to content

fix(changelog): read the previous changelog as UTF-8 - #1505

Open
Alpenj wants to merge 2 commits into
python-semantic-release:masterfrom
Alpenj:fix-read-file-utf8
Open

Alpenj wants to merge 2 commits into
python-semantic-release:masterfrom
Alpenj:fix-read-file-utf8

Conversation

@Alpenj

@Alpenj Alpenj commented Nov 6, 2026

Copy link
Copy Markdown

Purpose

On Windows with a non-UTF-8 code page (for example cp1252, or cp949 on Korean Windows), updating an existing changelog that contains non-ASCII text fails or corrupts it. In update mode, the previous changelog is read with the read_file template filter, which opened the file with the locale encoding, while the changelog writer saves the changelog as UTF-8. Text such as emoji headings or author names then fails with

UnicodeDecodeError: 'cp949' codec can't decode byte 0xe2 in position 28: illegal multibyte sequence

or, with cp1252, is rewritten as mojibake when the bytes happen to decode (✨ becomes ✨).

Rationale

The writer already uses UTF-8 (write_text(..., encoding="utf-8") in cli/changelog_writer.py, and open(..., encoding="utf-8") in changelog/template.py), so the filter now reads the file with the same encoding. On Linux and macOS the locale encoding is usually UTF-8, so nothing changes there.

How did you test?

On Windows 11 (cp949), Python 3.12:

  • Added test_read_file_reads_utf8_whatever_the_locale_encoding. It writes a UTF-8 changelog that contains ✨ and Łukasz, which neither cp1252 nor cp949 can decode, and checks that read_file returns the text unchanged. It fails without the fix (the error above) and passes with it.
  • pytest tests/unit/semantic_release/changelog/: 138 passed, 7 failed, 15 skipped. The 7 failures are in test_release_notes.py and also fail without this change on this machine: they expect \r\n line endings and get \n.
  • ruff check and ruff format --check on the changed files. I did not run mypy or the e2e tests.

How to Verify

  1. On Windows with a non-UTF-8 code page, run pytest tests/unit/semantic_release/changelog/test_changelog_context.py -k read_file.
  2. Revert the change in src/semantic_release/changelog/context.py and run it again: the new test fails with a UnicodeDecodeError.

PR Completion Checklist

  • Reviewed & followed the Contributor Guidelines

  • Changes Implemented & Validation pipeline succeeds

  • Commits follow the Conventional Commits standard
    and are separated into the proper commit type and scope (recommended order: test, build, feat/fix, docs)

  • Appropriate Unit tests added/updated

  • Appropriate End-to-End tests added/updated

  • Appropriate Documentation added/updated and syntax validated for sphinx build (see Contributor Guidelines)

This PR was prepared and opened by Claude Code (claude-opus-5-5), an AI agent, on behalf of the account owner.

🤖 Generated with Claude Code

Alpenj and others added 2 commits November 6, 2026 08:44
The `read_file` template filter read the previous changelog with the
locale encoding, while the changelog writer saves it as UTF-8. On Windows
with a non-UTF-8 code page (for example cp1252 or cp949), updating a
changelog that contains non-ASCII text, such as emoji headings or author
names, failed with a UnicodeDecodeError or rewrote the text as mojibake.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant