Skip to content
Open
Changes from all 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
13 changes: 11 additions & 2 deletions src/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import shutil
import sys
import traceback
import codecs

import scriptengine # type: ignore

Expand Down Expand Up @@ -151,8 +152,16 @@ def ui_error_with_traceback(message):
def open_utf8(path, mode):
# ScriptEngine runs on Python 2.7; the builtin open() writes a byte stream and would
# implicitly encode unicode text as ascii, crashing on Cyrillic / accented chars / smart
# punctuation. io.open with an explicit encoding keeps everything UTF-8 round-trippable.
return io.open(path, mode, encoding="utf-8")
# punctuation. codecs.open with an explicit encoding keeps everything UTF-8 round-trippable.
#
# io.open(path, mode, encoding="utf-8") looks equivalent but is unreliable on the
# IronPython 2.7 runtime CODESYS ScriptEngine uses: encoding resolution can silently
# fall back to the OS ANSI code page instead of true UTF-8, which corrupts any
# non ASCII character(umlauts, accented letters, smart punctuation, etc.) on export and
# then fail to decode on the next import ("'unknown' codec can't decode byte ...").
# codec.open is the long-standing, well-supported way to do UTF-8 text I/O on
# Python 2 / IronPython and does not have this problems.
return codecs.open(path, mode, encoding="utf-8")


def print_python_version():
Expand Down