diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 5e9f6aa86e81925..8e15319b5baab20 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -35,6 +35,7 @@ darwin = sys.platform == 'darwin' class EditorWindow: + is_shell = False # PyShell overrides. from idlelib.percolator import Percolator from idlelib.colorizer import ColorDelegator, color_config from idlelib.undo import UndoDelegator @@ -80,7 +81,6 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.recent_files_path = idleConf.userdir and os.path.join( idleConf.userdir, 'recent-files.lst') - self.prompt_last_line = '' # Override in PyShell self.text_frame = text_frame = Frame(top) self.vbar = vbar = Scrollbar(text_frame, name='vbar') width = idleConf.GetOption('main', 'EditorWindow', 'width', type='int') @@ -1434,7 +1434,7 @@ def newline_and_indent_event(self, event): # First need to find the last statement. lno = index2line(text.index('insert')) y = pyparse.Parser(self.indentwidth, self.tabwidth) - if not self.prompt_last_line: + if not self.is_shell: for context in self.num_context_lines: startat = max(lno - context, 1) startatindex = repr(startat) + ".0" diff --git a/Lib/idlelib/hyperparser.py b/Lib/idlelib/hyperparser.py index 76144ee8fb30f5e..d1a28b274a499ff 100644 --- a/Lib/idlelib/hyperparser.py +++ b/Lib/idlelib/hyperparser.py @@ -35,7 +35,7 @@ def index2line(index): return int(float(index)) lno = index2line(text.index(index)) - if not editwin.prompt_last_line: + if not editwin.is_shell: for context in editwin.num_context_lines: startat = max(lno - context, 1) startatindex = repr(startat) + ".0" diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py index 9086c31d2733b61..cd4664d21722bb5 100644 --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -19,7 +19,7 @@ def __init__(self, root, text): self.text = text self.indentwidth = 8 self.tabwidth = 8 - self.prompt_last_line = '>>>' # Currently not used by autocomplete. + self.is_shell = True class AutoCompleteTest(unittest.TestCase): diff --git a/Lib/idlelib/idle_test/test_calltip.py b/Lib/idlelib/idle_test/test_calltip.py index 28c196a42672fcd..e216ae67f68b4d1 100644 --- a/Lib/idlelib/idle_test/test_calltip.py +++ b/Lib/idlelib/idle_test/test_calltip.py @@ -282,7 +282,7 @@ class mock_Shell: def __init__(self, text): text.tag_prevrange = Mock(return_value=None) self.text = text - self.prompt_last_line = ">>> " + self.is_shell = True self.indentwidth = 4 self.tabwidth = 8 diff --git a/Lib/idlelib/idle_test/test_hyperparser.py b/Lib/idlelib/idle_test/test_hyperparser.py index 343843c4166e97d..df61d2641d3c7f2 100644 --- a/Lib/idlelib/idle_test/test_hyperparser.py +++ b/Lib/idlelib/idle_test/test_hyperparser.py @@ -11,7 +11,7 @@ def __init__(self, text): self.text = text self.indentwidth = 8 self.tabwidth = 8 - self.prompt_last_line = '>>>' + self.is_shell = True self.num_context_lines = 50, 500, 1000 _build_char_in_string_func = EditorWindow._build_char_in_string_func @@ -53,7 +53,7 @@ def setUp(self): def tearDown(self): self.text.delete('1.0', 'end') - self.editwin.prompt_last_line = '>>>' + self.editwin.is_shell = True def get_parser(self, index): """ @@ -70,8 +70,8 @@ def test_init(self): p = self.get_parser('1.5') self.assertIn('precedes', str(ve.exception)) - # test without ps1 - self.editwin.prompt_last_line = '' + # test an editor + self.editwin.is_shell = False # number of lines lesser than 50 p = self.get_parser('end') diff --git a/Lib/idlelib/idle_test/test_parenmatch.py b/Lib/idlelib/idle_test/test_parenmatch.py index 2e10d7cd36760ff..4907d77fff4c7c6 100644 --- a/Lib/idlelib/idle_test/test_parenmatch.py +++ b/Lib/idlelib/idle_test/test_parenmatch.py @@ -17,7 +17,7 @@ def __init__(self, text): self.text = text self.indentwidth = 8 self.tabwidth = 8 - self.prompt_last_line = '>>>' # Currently not used by parenmatch. + self.is_shell = True class ParenMatchTest(unittest.TestCase): diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index b69a5980bc5338b..997b91e53327d7b 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -852,6 +852,7 @@ def display_executing_dialog(self): class PyShell(OutputWindow): + is_shell = True from idlelib.squeezer import Squeezer shell_title = "IDLE Shell" @@ -909,7 +910,6 @@ def __init__(self, flist=None): self.indentwidth = 4 self.sys_ps1 = sys.ps1 if hasattr(sys, 'ps1') else '>>>\n' - self.prompt_last_line = self.sys_ps1.split('\n')[-1] self.prompt = self.sys_ps1 # Changes when debug active text = self.text diff --git a/Misc/NEWS.d/next/IDLE/2026-09-15-21-54-04.gh-issue-105689.ASoU37.rst b/Misc/NEWS.d/next/IDLE/2026-09-15-21-54-04.gh-issue-105689.ASoU37.rst new file mode 100644 index 000000000000000..7b4924fa0af2283 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2026-09-15-21-54-04.gh-issue-105689.ASoU37.rst @@ -0,0 +1,2 @@ +Fix calltips, parenthesis matching and auto-indent in the IDLE Shell after +output containing unbalanced quotes or parentheses.