Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
gh-85604: Check IDLE theme colors at startup
An invalid color in a user highlight theme crashed the Settings dialog.
Now it is ignored with a warning and the default color is used instead.
  • Loading branch information
serhiy-storchaka committed Sep 16, 2026
commit fd6f990b0ddf153494ca47c106e905b619960346
45 changes: 44 additions & 1 deletion Lib/idlelib/idle_test/test_pyshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
from idlelib import pyshell
import os
import unittest
from test.support import requires
from unittest import mock
from test.support import requires, captured_stderr
from tkinter import Tk
from idlelib import config


class FunctionTest(unittest.TestCase):
Expand Down Expand Up @@ -38,6 +40,47 @@ def test_fix_user_path(self):
eq(pyshell.fix_user_path([idlelib_dir]), [])


class CheckThemeColorsTest(unittest.TestCase):

@classmethod
def setUpClass(cls):
requires('gui')
cls.root = Tk()
cls.root.withdraw()

@classmethod
def tearDownClass(cls):
cls.root.update_idletasks()
cls.root.destroy()
del cls.root

def test_check_theme_colors(self):
# gh-85604: invalid colors are reported and removed.
cfg = config.IdleUserConfParser('')
cfg.SetOption('Good', 'keyword-foreground', '#ff7700')
cfg.SetOption('Bad', 'keyword-foreground', 'bpo-00224')
cfg.SetOption('Bad', 'keyword-background', 'white')
cfg.SetOption('Bad', 'comment-background', '#12345')
with (mock.patch.dict(pyshell.idleConf.userCfg, {'highlight': cfg}),
captured_stderr() as stderr):
pyshell.check_theme_colors(self.root)
msg = stderr.getvalue()
self.assertIn("invalid color 'bpo-00224' for 'keyword-foreground' "
"in theme 'Bad'", msg)
self.assertIn("invalid color '#12345'", msg)
self.assertNotIn('Good', msg)
self.assertNotIn('white', msg)
self.assertFalse(cfg.has_option('Bad', 'keyword-foreground'))
self.assertFalse(cfg.has_option('Bad', 'comment-background'))
self.assertTrue(cfg.has_option('Bad', 'keyword-background'))
self.assertTrue(cfg.has_option('Good', 'keyword-foreground'))
# Nothing left to report.
with (mock.patch.dict(pyshell.idleConf.userCfg, {'highlight': cfg}),
captured_stderr() as stderr):
pyshell.check_theme_colors(self.root)
self.assertEqual(stderr.getvalue(), '')


class PyShellFileListTest(unittest.TestCase):

@classmethod
Expand Down
21 changes: 21 additions & 0 deletions Lib/idlelib/pyshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,26 @@ def restart_line(width, filename): # See bpo-38141.
return tag[:-2] # Remove ' ='.


def check_theme_colors(root):
"""Warn about invalid colors in user themes and remove them.

The default colors are then used instead (gh-85604). The user
files are not changed until the settings are saved.
"""
cfg = idleConf.userCfg['highlight']
for theme in cfg.sections():
for element in cfg.options(theme):
color = cfg.Get(theme, element)
try:
root.winfo_rgb(color)
except TclError as err:
print(f'Warning: ignoring invalid color {color!r} '
f'for {element!r} in theme {theme!r}: {err}. '
f'Please reconfigure it in the IDLE Settings dialog.',
file=sys.stderr)
cfg.RemoveOption(theme, element)


def fix_user_path(path):
"""Return path without the idlelib directory (gh-134300).

Expand Down Expand Up @@ -1617,6 +1637,7 @@ def main():
if config_error:
messagebox.showwarning('IDLE Configuration Warning', config_error,
parent=root)
check_theme_colors(root)

# set application icon
icondir = os.path.join(os.path.dirname(__file__), 'Icons')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Invalid colors in user highlight themes no longer crash the IDLE Settings
dialog. They are now reported at IDLE startup and replaced with the default
colors.
Loading