Skip to content

Commit 23a567c

Browse files
bpo-23544: Disable IDLE Stack Viewer when running user code (GH-17163)
Starting stack viewer when user code is running, including when Debugger is active, hangs or crashes IDLE. Co-authored-by: Terry Jan Reedy <[email protected]>
1 parent 64fc105 commit 23a567c

File tree

6 files changed

+37
-5
lines changed

6 files changed

+37
-5
lines changed

Lib/idlelib/NEWS.txt

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ Released on 2021-10-04?
33
======================================
44

55

6+
bpo-23544: Disable Debug=>Stack Viewer when user code is running or
7+
Debugger is active, to prevent hang or crash. Patch by Zackery Spytz.
8+
69
bpo-43008: Make IDLE invoke :func:`sys.excepthook` in normal,
710
2-process mode.
811

Lib/idlelib/codecontext.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def toggle_code_context_event(self, event=None):
142142
self.text.after_cancel(self.t1)
143143
self._reset()
144144
menu_status = 'Show'
145-
self.editwin.update_menu_label(menu='options', index='* Code Context',
145+
self.editwin.update_menu_label(menu='options', index='*ode*ontext',
146146
label=f'{menu_status} Code Context')
147147
return "break"
148148

Lib/idlelib/editor.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -339,15 +339,15 @@ def __init__(self, flist=None, filename=None, key=None, root=None):
339339
text.bind("<<toggle-code-context>>",
340340
self.code_context.toggle_code_context_event)
341341
else:
342-
self.update_menu_state('options', '*Code Context', 'disabled')
342+
self.update_menu_state('options', '*ode*ontext', 'disabled')
343343
if self.allow_line_numbers:
344344
self.line_numbers = self.LineNumbers(self)
345345
if idleConf.GetOption('main', 'EditorWindow',
346346
'line-numbers-default', type='bool'):
347347
self.toggle_line_numbers_event()
348348
text.bind("<<toggle-line-numbers>>", self.toggle_line_numbers_event)
349349
else:
350-
self.update_menu_state('options', '*Line Numbers', 'disabled')
350+
self.update_menu_state('options', '*ine*umbers', 'disabled')
351351

352352
def handle_winconfig(self, event=None):
353353
self.set_width()
@@ -450,7 +450,9 @@ def createmenubar(self):
450450
self.menudict = menudict = {}
451451
for name, label in self.menu_specs:
452452
underline, label = prepstr(label)
453-
menudict[name] = menu = Menu(mbar, name=name, tearoff=0)
453+
postcommand = getattr(self, f'{name}_menu_postcommand', None)
454+
menudict[name] = menu = Menu(mbar, name=name, tearoff=0,
455+
postcommand=postcommand)
454456
mbar.add_cascade(label=label, menu=menu, underline=underline)
455457
if macosx.isCarbonTk():
456458
# Insert the application menu
@@ -1527,7 +1529,7 @@ def toggle_line_numbers_event(self, event=None):
15271529
else:
15281530
self.line_numbers.show_sidebar()
15291531
menu_label = "Hide"
1530-
self.update_menu_label(menu='options', index='*Line Numbers',
1532+
self.update_menu_label(menu='options', index='*ine*umbers',
15311533
label=f'{menu_label} Line Numbers')
15321534

15331535
# "line.col" -> line, as an int

Lib/idlelib/idle_test/test_mainmenu.py

+21
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Reported as 88%; mocking turtledemo absence would have no point.
33

44
from idlelib import mainmenu
5+
import re
56
import unittest
67

78

@@ -16,6 +17,26 @@ def test_menudefs(self):
1617
def test_default_keydefs(self):
1718
self.assertGreaterEqual(len(mainmenu.default_keydefs), 50)
1819

20+
def test_tcl_indexes(self):
21+
# Test tcl patterns used to find menuitem to alter.
22+
# On failure, change pattern here and in function(s).
23+
# Patterns here have '.*' for re instead of '*' for tcl.
24+
for menu, pattern in (
25+
('debug', '.*tack.*iewer'), # PyShell.debug_menu_postcommand
26+
('options', '.*ode.*ontext'), # EW.__init__, CodeContext.toggle...
27+
('options', '.*ine.*umbers'), # EW.__init__, EW.toggle...event.
28+
):
29+
with self.subTest(menu=menu, pattern=pattern):
30+
for menutup in mainmenu.menudefs:
31+
if menutup[0] == menu:
32+
break
33+
else:
34+
self.assertTrue(0, f"{menu} not in menudefs")
35+
self.assertTrue(any(re.search(pattern, menuitem[0])
36+
for menuitem in menutup[1]
37+
if menuitem is not None), # Separator.
38+
f"{pattern} not in {menu}")
39+
1940

2041
if __name__ == '__main__':
2142
unittest.main(verbosity=2)

Lib/idlelib/pyshell.py

+4
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,10 @@ def open_debugger(self):
989989
self.showprompt()
990990
self.set_debugger_indicator()
991991

992+
def debug_menu_postcommand(self):
993+
state = 'disabled' if self.executing else 'normal'
994+
self.update_menu_state('debug', '*tack*iewer', state)
995+
992996
def beginexecuting(self):
993997
"Helper for ModifiedInterpreter"
994998
self.resetoutput()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Disable Debug=>Stack Viewer when user code is running or Debugger
2+
is active, to prevent hang or crash. Patch by Zackery Spytz.

0 commit comments

Comments
 (0)