fix(rename): read and write source files as UTF-8
All Submissions:
- Have you followed the guidelines stated in CONTRIBUTING.md file?
- Have you checked to ensure there aren't any other open Pull Requests for the desired changed?
Type of change
- Bug fix (non-breaking change which fixes an issue)
What and why
reflex rename <new_name> walks the user's app and rewrites imports and the app
name in every .py and .md file. The read/modify/write in
rename_imports_and_app_name (reflex/utils/rename.py) used
Path.read_text() and Path.write_text() with no encoding= argument, so both
default to the platform's locale encoding. On a Western Windows locale that is
cp1252, not UTF-8.
The consequences on non-UTF-8 locales:
- Silent corruption (Western Windows, cp1252): a UTF-8-authored file that
contains non-ASCII bytes (curly quotes in docstrings, accented identifiers or
string literals, emoji) is decoded as cp1252, rewritten, and written back as
cp1252, mangling the user's own source. - Hard failure (CJK codepages):
read_text()raisesUnicodeDecodeError,
aborting the rename partway through the tree and leaving some files already
rewritten and others not, i.e. an inconsistent app.
On a POSIX UTF-8 locale it round-trips, so this is effectively Windows-specific.
The fix passes encoding="utf-8" on both calls. This mirrors the repo's own
reflex/utils/path_ops.py find_replace, which already reads and writes the same
read/replace/write pattern with encoding="utf-8"; rename.py was the outlier.
Changes
reflex/utils/rename.py: addencoding="utf-8"to theread_text()and
write_text()calls inrename_imports_and_app_name(+2 / -2).tests/units/test_prerequisites.py: add regression test
test_rename_imports_and_app_name_preserves_utf8, colocated with the existing
rename tests. It simulates a cp1252 default (monkeypatchingPath.read_text/
write_textso a missingencodingfalls back to cp1252, while an explicit
encoding=still passes through), writes a UTF-8 file with realistic non-ASCII
content, runs the rename, and asserts the bytes are preserved exactly and the
rename still happened. The test fails before the fix (UnicodeDecodeError) and
passes after.news/<pr>.bugfix.md: towncrier changelog fragment.
Changes To Core Features:
- Have you added an explanation of what your changes do and why you'd like us to include them? (above)
- Have you written new tests for your core changes, as applicable?
- Have you successfully ran tests with your changes locally?
Locally (all green):
uv run pytest tests/units/test_prerequisites.py -k rename-> 6 passeduv run pytest tests/units/test_prerequisites.py tests/units/utils-> 677 passed, 4 skippeduv run ruff check .(changed files) -> All checks passeduv run ruff format --check .(changed files) -> already formatteduv run pyright reflex/utils/rename.py tests/units/test_prerequisites.py-> 0 errorsuv run towncrier check --compare-with origin/main-> fragment found
Greptile Summary
This PR makes reflex rename preserve source-file text across platform locales. The main changes are:
- Detect and preserve declared Python source encodings.
- Read and write other supported files as UTF-8.
- Preserve LF and CRLF line endings.
- Add tests for UTF-8, cp1252, and line-ending behavior.
Confidence Score: 5/5
This looks safe to merge.
- The declared-encoding failure is addressed with Python's standard encoding detection.
- Reads and writes use the same detected encoding.
- Tests cover the affected encoding and line-ending paths.
- No blocking issues remain in the changed code.
Important Files Changed
| Filename | Overview |
|---|---|
| reflex/utils/rename.py | Detects declared Python encodings and preserves the selected encoding and original line endings during rename. |
| tests/units/test_prerequisites.py | Adds tests for UTF-8 under a non-UTF-8 locale, declared cp1252 source, and LF/CRLF preservation. |
| news/6761.bugfix.md | Documents the source-encoding and line-ending preservation fix. |
Reviews (5): Last reviewed commit: "fix(rename): preserve source line ending..." | Re-trigger Greptile
Context used: