Skip to content

Commit ac30e9b

Browse files
miss-islingtonserhiy-storchakaclaude
authored
[3.15] gh-85320: Use UTF-8 for IDLE configuration and breakpoint files (GH-152475) (GH-152555)
They were read and written using the locale encoding, which could corrupt non-ASCII paths and made them non-portable. (cherry picked from commit f6e904e) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent af66503 commit ac30e9b

4 files changed

Lines changed: 19 additions & 7 deletions

File tree

Lib/idlelib/News3.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Released on 2026-10-01
44
=========================
55

66

7+
gh-85320: IDLE now reads and writes its configuration files and the
8+
breakpoints file using UTF-8 instead of the locale encoding.
9+
Files with non-ASCII characters and non-UTF-8 encoding may need
10+
to be opened in an editor and resaved with UTF-8 encoding.
11+
712
gh-143774: Better explain the operation of Format / Format Paragraph.
813
Patch by Terry J. Reedy.
914

Lib/idlelib/config.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ def GetOptionList(self, section):
7373

7474
def Load(self):
7575
"Load the configuration file from disk."
76-
if self.file:
77-
self.read(self.file)
76+
if self.file and os.path.exists(self.file):
77+
with open(self.file, encoding='utf-8', errors='replace') as f:
78+
self.read_file(f)
7879

7980
class IdleUserConfParser(IdleConfParser):
8081
"""
@@ -133,10 +134,10 @@ def Save(self):
133134
if fname and fname[0] != '#':
134135
if not self.IsEmpty():
135136
try:
136-
cfgFile = open(fname, 'w')
137+
cfgFile = open(fname, 'w', encoding='utf-8')
137138
except OSError:
138139
os.unlink(fname)
139-
cfgFile = open(fname, 'w')
140+
cfgFile = open(fname, 'w', encoding='utf-8')
140141
with cfgFile:
141142
self.write(cfgFile)
142143
elif os.path.exists(self.file):

Lib/idlelib/pyshell.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,13 @@ def store_file_breaks(self):
242242
breaks = self.breakpoints
243243
filename = self.io.filename
244244
try:
245-
with open(self.breakpointPath) as fp:
245+
with open(self.breakpointPath,
246+
encoding='utf-8', errors='replace') as fp:
246247
lines = fp.readlines()
247248
except OSError:
248249
lines = []
249250
try:
250-
with open(self.breakpointPath, "w") as new_file:
251+
with open(self.breakpointPath, "w", encoding='utf-8') as new_file:
251252
for line in lines:
252253
if not line.startswith(filename + '='):
253254
new_file.write(line)
@@ -272,7 +273,8 @@ def restore_file_breaks(self):
272273
if filename is None:
273274
return
274275
if os.path.isfile(self.breakpointPath):
275-
with open(self.breakpointPath) as fp:
276+
with open(self.breakpointPath,
277+
encoding='utf-8', errors='replace') as fp:
276278
lines = fp.readlines()
277279
for line in lines:
278280
if line.startswith(filename + '='):
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
IDLE now reads and writes its configuration files and the breakpoints file
2+
using UTF-8 instead of the locale encoding. This keeps non-ASCII data (such
3+
as non-ASCII paths) from being corrupted and makes the files portable between
4+
environments.

0 commit comments

Comments
 (0)