blob: 7eab8d01c023efbed1b7f47d64f818f575d200e6 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#! /usr/bin/env python3
David Scherer7aced172000-08-15 01:13:23 +00002
Victor Stinner979482a2011-09-02 01:00:40 +02003import getopt
David Scherer7aced172000-08-15 01:13:23 +00004import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00005import os.path
David Scherer7aced172000-08-15 01:13:23 +00006import re
Chui Tey5d2af632002-05-26 13:36:41 +00007import socket
Victor Stinner979482a2011-09-02 01:00:40 +02008import subprocess
9import sys
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000010import threading
Victor Stinner979482a2011-09-02 01:00:40 +020011import time
12import tokenize
Chui Tey5d2af632002-05-26 13:36:41 +000013import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000014import types
Martin v. Löwisc882b7c2012-07-25 10:47:20 +020015import io
David Scherer7aced172000-08-15 01:13:23 +000016
17import linecache
18from code import InteractiveInterpreter
Terry Jan Reedya7c07d32014-02-08 09:02:26 -050019from platform import python_version, system
David Scherer7aced172000-08-15 01:13:23 +000020
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000021try:
Georg Brandl14fc4272008-05-17 18:39:55 +000022 from tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000023except ImportError:
Terry Jan Reedy81b062f2014-09-19 22:38:41 -040024 print("** IDLE can't import Tkinter.\n"
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000025 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000026 sys.exit(1)
Georg Brandl14fc4272008-05-17 18:39:55 +000027import tkinter.messagebox as tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000028
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000029from idlelib.EditorWindow import EditorWindow, fixwordbreaks
30from idlelib.FileList import FileList
31from idlelib.ColorDelegator import ColorDelegator
32from idlelib.UndoDelegator import UndoDelegator
33from idlelib.OutputWindow import OutputWindow
34from idlelib.configHandler import idleConf
35from idlelib import idlever
36from idlelib import rpc
37from idlelib import Debugger
38from idlelib import RemoteDebugger
39from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000040
Kurt B. Kaisere866c812009-04-04 21:07:39 +000041HOST = '127.0.0.1' # python execution server on localhost loopback
42PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000043
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000044# Override warnings module to write to warning_stream. Initialize to send IDLE
45# internal warnings to the console. ScriptBinding.check_syntax() will
46# temporarily redirect the stream to the shell window to display warnings when
47# checking user's code.
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040048warning_stream = sys.__stderr__ # None, at least on Windows, if no console.
49import warnings
50
51def idle_formatwarning(message, category, filename, lineno, line=None):
52 """Format warnings the IDLE way."""
53
54 s = "\nWarning (from warnings module):\n"
55 s += ' File \"%s\", line %s\n' % (filename, lineno)
56 if line is None:
57 line = linecache.getline(filename, lineno)
58 line = line.strip()
59 if line:
60 s += " %s\n" % line
61 s += "%s: %s\n" % (category.__name__, message)
62 return s
63
64def idle_showwarning(
65 message, category, filename, lineno, file=None, line=None):
66 """Show Idle-format warning (after replacing warnings.showwarning).
67
68 The differences are the formatter called, the file=None replacement,
69 which can be None, the capture of the consequence AttributeError,
70 and the output of a hard-coded prompt.
71 """
72 if file is None:
73 file = warning_stream
74 try:
75 file.write(idle_formatwarning(
76 message, category, filename, lineno, line=line))
77 file.write(">>> ")
78 except (AttributeError, OSError):
79 pass # if file (probably __stderr__) is invalid, skip warning.
80
81_warnings_showwarning = None
82
83def capture_warnings(capture):
84 "Replace warning.showwarning with idle_showwarning, or reverse."
85
86 global _warnings_showwarning
87 if capture:
88 if _warnings_showwarning is None:
89 _warnings_showwarning = warnings.showwarning
90 warnings.showwarning = idle_showwarning
91 else:
92 if _warnings_showwarning is not None:
93 warnings.showwarning = _warnings_showwarning
94 _warnings_showwarning = None
95
96capture_warnings(True)
Chui Tey5d2af632002-05-26 13:36:41 +000097
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000098def extended_linecache_checkcache(filename=None,
99 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000100 """Extend linecache.checkcache to preserve the <pyshell#...> entries
101
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000102 Rather than repeating the linecache code, patch it to save the
103 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polo1fff0082009-08-14 15:05:30 +0000104 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000105
106 orig_checkcache is bound at definition time to the original
107 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000108 """
David Scherer7aced172000-08-15 01:13:23 +0000109 cache = linecache.cache
110 save = {}
Guilherme Polo1fff0082009-08-14 15:05:30 +0000111 for key in list(cache):
112 if key[:1] + key[-1:] == '<>':
113 save[key] = cache.pop(key)
114 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +0000115 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000116
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000117# Patch linecache.checkcache():
118linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000119
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000120
David Scherer7aced172000-08-15 01:13:23 +0000121class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000122 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000123
David Scherer7aced172000-08-15 01:13:23 +0000124 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000125 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000126 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000127 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000128 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000129 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
130
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000131 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
132 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000133 # whenever a file is changed, restore breakpoints
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000134 def filename_changed_hook(old_hook=self.io.filename_change_hook,
135 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000136 self.restore_file_breaks()
137 old_hook()
138 self.io.set_filename_change_hook(filename_changed_hook)
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500139 if self.io.filename:
140 self.restore_file_breaks()
Terry Jan Reedyda26cca2014-08-08 23:33:16 -0400141 self.color_breakpoint_text()
Chui Teya2adb0f2002-11-04 22:14:54 +0000142
Andrew Svetlovd1837672012-11-01 22:41:19 +0200143 rmenu_specs = [
144 ("Cut", "<<cut>>", "rmenu_check_cut"),
145 ("Copy", "<<copy>>", "rmenu_check_copy"),
146 ("Paste", "<<paste>>", "rmenu_check_paste"),
147 (None, None, None),
148 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
149 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
150 ]
David Scherer7aced172000-08-15 01:13:23 +0000151
Terry Jan Reedyda26cca2014-08-08 23:33:16 -0400152 def color_breakpoint_text(self, color=True):
153 "Turn colorizing of breakpoint text on or off"
154 if color:
155 theme = idleConf.GetOption('main','Theme','name')
156 cfg = idleConf.GetHighlight(theme, "break")
157 else:
158 cfg = {'foreground': '', 'background': ''}
159 self.text.tag_config('BREAK', cfg)
160
Chui Teya2adb0f2002-11-04 22:14:54 +0000161 def set_breakpoint(self, lineno):
162 text = self.text
163 filename = self.io.filename
164 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
165 try:
166 i = self.breakpoints.index(lineno)
167 except ValueError: # only add if missing, i.e. do once
168 self.breakpoints.append(lineno)
169 try: # update the subprocess debugger
170 debug = self.flist.pyshell.interp.debugger
171 debug.set_breakpoint_here(filename, lineno)
172 except: # but debugger may not be active right now....
173 pass
174
David Scherer7aced172000-08-15 01:13:23 +0000175 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000176 text = self.text
177 filename = self.io.filename
178 if not filename:
179 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000180 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000181 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000182 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000183
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000184 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000185 text = self.text
186 filename = self.io.filename
187 if not filename:
188 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000189 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000190 lineno = int(float(text.index("insert")))
191 try:
192 self.breakpoints.remove(lineno)
193 except:
194 pass
195 text.tag_remove("BREAK", "insert linestart",\
196 "insert lineend +1char")
197 try:
198 debug = self.flist.pyshell.interp.debugger
199 debug.clear_breakpoint_here(filename, lineno)
200 except:
201 pass
202
203 def clear_file_breaks(self):
204 if self.breakpoints:
205 text = self.text
206 filename = self.io.filename
207 if not filename:
208 text.bell()
209 return
210 self.breakpoints = []
211 text.tag_remove("BREAK", "1.0", END)
212 try:
213 debug = self.flist.pyshell.interp.debugger
214 debug.clear_file_breaks(filename)
215 except:
216 pass
217
Chui Teya2adb0f2002-11-04 22:14:54 +0000218 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000219 "Save breakpoints when file is saved"
220 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
221 # be run. The breaks are saved at that time. If we introduce
222 # a temporary file save feature the save breaks functionality
223 # needs to be re-verified, since the breaks at the time the
224 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000225 # permanent save of the file. Currently, a break introduced
226 # after a save will be effective, but not persistent.
227 # This is necessary to keep the saved breaks synched with the
228 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000229 #
230 # Breakpoints are set as tagged ranges in the text. Certain
231 # kinds of edits cause these ranges to be deleted: Inserting
232 # or deleting a line just before a breakpoint, and certain
233 # deletions prior to a breakpoint. These issues need to be
234 # investigated and understood. It's not clear if they are
235 # Tk issues or IDLE issues, or whether they can actually
236 # be fixed. Since a modified file has to be saved before it is
237 # run, and since self.breakpoints (from which the subprocess
238 # debugger is loaded) is updated during the save, the visible
239 # breaks stay synched with the subprocess even if one of these
240 # unexpected breakpoint deletions occurs.
241 breaks = self.breakpoints
242 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000243 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200244 with open(self.breakpointPath, "r") as fp:
245 lines = fp.readlines()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200246 except OSError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000247 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800248 try:
249 with open(self.breakpointPath, "w") as new_file:
250 for line in lines:
251 if not line.startswith(filename + '='):
252 new_file.write(line)
253 self.update_breakpoints()
254 breaks = self.breakpoints
255 if breaks:
256 new_file.write(filename + '=' + str(breaks) + '\n')
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200257 except OSError as err:
Ned Deilyf505b742011-12-14 14:58:24 -0800258 if not getattr(self.root, "breakpoint_error_displayed", False):
259 self.root.breakpoint_error_displayed = True
260 tkMessageBox.showerror(title='IDLE Error',
261 message='Unable to update breakpoint list:\n%s'
262 % str(err),
263 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000264
265 def restore_file_breaks(self):
266 self.text.update() # this enables setting "BREAK" tags to be visible
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500267 if self.io is None:
268 # can happen if IDLE closes due to the .update() call
269 return
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000270 filename = self.io.filename
271 if filename is None:
272 return
Chui Tey69371d62002-11-04 23:39:45 +0000273 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200274 with open(self.breakpointPath, "r") as fp:
275 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000276 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000277 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000278 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000279 for breakpoint_linenumber in breakpoint_linenumbers:
280 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000281
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000282 def update_breakpoints(self):
283 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000284 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000285 ranges = text.tag_ranges("BREAK")
286 linenumber_list = self.ranges_to_linenumbers(ranges)
287 self.breakpoints = linenumber_list
288
289 def ranges_to_linenumbers(self, ranges):
290 lines = []
291 for index in range(0, len(ranges), 2):
Andrew Svetlov06c5c6d2012-07-31 19:48:00 +0300292 lineno = int(float(ranges[index].string))
293 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000294 while lineno < end:
295 lines.append(lineno)
296 lineno += 1
297 return lines
298
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000299# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000300# def saved_change_hook(self):
301# "Extend base method - clear breaks if module is modified"
302# if not self.get_saved():
303# self.clear_file_breaks()
304# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000305
306 def _close(self):
307 "Extend base method - clear breaks when module is closed"
308 self.clear_file_breaks()
309 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000310
David Scherer7aced172000-08-15 01:13:23 +0000311
312class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000313 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000314
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000315 # override FileList's class variable, instances return PyShellEditorWindow
316 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000317 EditorWindow = PyShellEditorWindow
318
319 pyshell = None
320
321 def open_shell(self, event=None):
322 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000323 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000324 else:
325 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000326 if self.pyshell:
327 if not self.pyshell.begin():
328 return None
David Scherer7aced172000-08-15 01:13:23 +0000329 return self.pyshell
330
331
332class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000333 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000334
Steven M. Gavab77d3432002-03-02 07:16:21 +0000335 def __init__(self):
336 ColorDelegator.__init__(self)
337 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000338
339 def recolorize_main(self):
340 self.tag_remove("TODO", "1.0", "iomark")
341 self.tag_add("SYNC", "1.0", "iomark")
342 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000343
Steven M. Gavab77d3432002-03-02 07:16:21 +0000344 def LoadTagDefs(self):
345 ColorDelegator.LoadTagDefs(self)
346 theme = idleConf.GetOption('main','Theme','name')
347 self.tagdefs.update({
348 "stdin": {'background':None,'foreground':None},
349 "stdout": idleConf.GetHighlight(theme, "stdout"),
350 "stderr": idleConf.GetHighlight(theme, "stderr"),
351 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000352 })
David Scherer7aced172000-08-15 01:13:23 +0000353
Ned Deily8b2a56b2012-05-31 09:17:29 -0700354 def removecolors(self):
355 # Don't remove shell color tags before "iomark"
356 for tag in self.tagdefs:
357 self.tag_remove(tag, "iomark", "end")
358
David Scherer7aced172000-08-15 01:13:23 +0000359class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000360 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000361
362 def insert(self, index, chars, tags=None):
363 try:
364 if self.delegate.compare(index, "<", "iomark"):
365 self.delegate.bell()
366 return
367 except TclError:
368 pass
369 UndoDelegator.insert(self, index, chars, tags)
370
371 def delete(self, index1, index2=None):
372 try:
373 if self.delegate.compare(index1, "<", "iomark"):
374 self.delegate.bell()
375 return
376 except TclError:
377 pass
378 UndoDelegator.delete(self, index1, index2)
379
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000380
381class MyRPCClient(rpc.RPCClient):
382
383 def handle_EOF(self):
384 "Override the base class - just re-raise EOFError"
385 raise EOFError
386
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000387
David Scherer7aced172000-08-15 01:13:23 +0000388class ModifiedInterpreter(InteractiveInterpreter):
389
390 def __init__(self, tkconsole):
391 self.tkconsole = tkconsole
392 locals = sys.modules['__main__'].__dict__
393 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000394 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000395 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000396 self.subprocess_arglist = None
397 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700398 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000399
Roger Serwy036e8492013-06-11 22:13:17 -0500400 _afterid = None
Chui Tey5d2af632002-05-26 13:36:41 +0000401 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700402 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000403
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000404 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000405 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000406 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700407 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000408
Tony Lowndsf53dec22002-12-20 04:24:43 +0000409 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000410 assert (self.port!=0), (
411 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000412 w = ['-W' + s for s in sys.warnoptions]
413 # Maybe IDLE is installed and is being accessed via sys.path,
414 # or maybe it's not installed and the idle.py script is being
415 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000416 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
417 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000418 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000419 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000420 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000421 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700422 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000423
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000424 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000425 addr = (HOST, self.port)
426 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000427 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000428 time.sleep(i)
429 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000430 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000431 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200432 except OSError as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000433 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000434 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000435 self.display_port_binding_error()
436 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000437 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
438 self.port = self.rpcclt.listening_sock.getsockname()[1]
439 # if PORT was not 0, probably working with a remote execution server
440 if PORT != 0:
441 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
442 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
443 # on Windows since the implementation allows two active sockets on
444 # the same address!
445 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
446 socket.SO_REUSEADDR, 1)
447 self.spawn_subprocess()
448 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000449 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000450 self.rpcclt.listening_sock.settimeout(10)
451 try:
452 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000453 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000454 self.display_no_subprocess_error()
455 return None
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200456 self.rpcclt.register("console", self.tkconsole)
457 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000458 self.rpcclt.register("stdout", self.tkconsole.stdout)
459 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000460 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000461 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000462 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500463 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000464 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000465 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000466
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500467 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000468 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000469 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000470 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000471 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000472 debug = self.getdebugger()
473 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000474 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000475 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000476 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
477 except:
478 pass
479 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000480 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700481 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000482 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000483 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000484 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000485 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000486 try:
487 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000488 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000489 self.display_no_subprocess_error()
490 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500491 self.transfer_path(with_cwd=with_cwd)
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500492 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000493 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000494 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000495 if was_executing:
496 console.write('\n')
497 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000498 halfbar = ((int(console.width) - 16) // 2) * '='
499 console.write(halfbar + ' RESTART ' + halfbar)
500 console.text.mark_set("restart", "end-1c")
501 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000502 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000503 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000504 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000505 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000506 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000507 # reload remote debugger breakpoints for all PyShellEditWindows
508 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700509 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000510 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000511 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000512
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000513 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000514 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000515
516 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000517 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000518
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000519 def kill_subprocess(self):
Roger Serwy036e8492013-06-11 22:13:17 -0500520 if self._afterid is not None:
521 self.tkconsole.text.after_cancel(self._afterid)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000522 try:
Ned Deily55f87572011-11-05 22:36:44 -0700523 self.rpcclt.listening_sock.close()
524 except AttributeError: # no socket
525 pass
526 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000527 self.rpcclt.close()
528 except AttributeError: # no socket
529 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700530 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000531 self.tkconsole.executing = False
532 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000533
Ned Deilye5cad232011-08-02 18:47:13 -0700534 def terminate_subprocess(self):
535 "Make sure subprocess is terminated"
536 try:
537 self.rpcsubproc.kill()
538 except OSError:
539 # process already terminated
540 return
541 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000542 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700543 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000544 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000545 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000546
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500547 def transfer_path(self, with_cwd=False):
548 if with_cwd: # Issue 13506
549 path = [''] # include Current Working Directory
550 path.extend(sys.path)
551 else:
552 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500553
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000554 self.runcommand("""if 1:
555 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000556 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000557 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500558 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000559
Chui Tey5d2af632002-05-26 13:36:41 +0000560 active_seq = None
561
562 def poll_subprocess(self):
563 clt = self.rpcclt
564 if clt is None:
565 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000566 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000567 response = clt.pollresponse(self.active_seq, wait=0.05)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200568 except (EOFError, OSError, KeyboardInterrupt):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000569 # lost connection or subprocess terminated itself, restart
570 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000571 if self.tkconsole.closing:
572 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000573 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000574 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000575 if response:
576 self.tkconsole.resetoutput()
577 self.active_seq = None
578 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000579 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000580 if how == "OK":
581 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000582 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000583 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000584 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
585 self.remote_stack_viewer()
586 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000587 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000588 print(errmsg, what, file=sys.__stderr__)
589 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000590 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000591 try:
592 self.tkconsole.endexecuting()
593 except AttributeError: # shell may have closed
594 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000595 # Reschedule myself
596 if not self.tkconsole.closing:
Roger Serwy036e8492013-06-11 22:13:17 -0500597 self._afterid = self.tkconsole.text.after(
598 self.tkconsole.pollinterval, self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000599
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000600 debugger = None
601
602 def setdebugger(self, debugger):
603 self.debugger = debugger
604
605 def getdebugger(self):
606 return self.debugger
607
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000608 def open_remote_stack_viewer(self):
609 """Initiate the remote stack viewer from a separate thread.
610
611 This method is called from the subprocess, and by returning from this
612 method we allow the subprocess to unblock. After a bit the shell
613 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000614 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000615 the RPC mechanism.
616
617 """
618 self.tkconsole.text.after(300, self.remote_stack_viewer)
619 return
620
Chui Tey5d2af632002-05-26 13:36:41 +0000621 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000622 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000623 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000624 if oid is None:
625 self.tkconsole.root.bell()
626 return
627 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000628 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000629 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000630 theme = idleConf.GetOption('main','Theme','name')
631 background = idleConf.GetHighlight(theme, 'normal')['background']
632 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000633 sc.frame.pack(expand=1, fill="both")
634 node = TreeNode(sc.canvas, None, item)
635 node.expand()
636 # XXX Should GC the remote tree when closing the window
637
David Scherer7aced172000-08-15 01:13:23 +0000638 gid = 0
639
640 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000641 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000642 filename = self.stuffsource(source)
643 self.execfile(filename, source)
644
645 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000646 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000647 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200648 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200649 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000650 try:
651 code = compile(source, filename, "exec")
652 except (OverflowError, SyntaxError):
653 self.tkconsole.resetoutput()
Terry Jan Reedy81b062f2014-09-19 22:38:41 -0400654 print('*** Error in script or command!\n'
655 'Traceback (most recent call last):',
656 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000657 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000658 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000659 else:
660 self.runcode(code)
661
662 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000663 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000664 filename = self.stuffsource(source)
665 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000666 self.save_warnings_filters = warnings.filters[:]
667 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000668 # at the moment, InteractiveInterpreter expects str
669 assert isinstance(source, str)
670 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000671 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000672 # try:
673 # source = source.encode(IOBinding.encoding)
674 # except UnicodeError:
675 # self.tkconsole.resetoutput()
676 # self.write("Unsupported characters in input\n")
677 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000678 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000679 # InteractiveInterpreter.runsource() calls its runcode() method,
680 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000681 return InteractiveInterpreter.runsource(self, source, filename)
682 finally:
683 if self.save_warnings_filters is not None:
684 warnings.filters[:] = self.save_warnings_filters
685 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000686
687 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000688 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000689 filename = "<pyshell#%d>" % self.gid
690 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000691 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000692 linecache.cache[filename] = len(source)+1, 0, lines, filename
693 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000694
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000695 def prepend_syspath(self, filename):
696 "Prepend sys.path with file's directory if not already included"
697 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000698 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000699 import sys as _sys
700 from os.path import dirname as _dirname
701 _dir = _dirname(_filename)
702 if not _dir in _sys.path:
703 _sys.path.insert(0, _dir)
704 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000705 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000706
David Scherer7aced172000-08-15 01:13:23 +0000707 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000708 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000709
710 Color the offending position instead of printing it and pointing at it
711 with a caret.
712
713 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000714 tkconsole = self.tkconsole
715 text = tkconsole.text
716 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000717 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700718 msg = getattr(value, 'msg', '') or value or "<no detail available>"
719 lineno = getattr(value, 'lineno', '') or 1
720 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000721 if offset == 0:
722 lineno += 1 #mark end of offending line
723 if lineno == 1:
724 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000725 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000726 pos = "iomark linestart + %d lines + %d chars" % \
727 (lineno-1, offset-1)
728 tkconsole.colorize_syntax_error(text, pos)
729 tkconsole.resetoutput()
730 self.write("SyntaxError: %s\n" % msg)
731 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000732
733 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000734 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000735 self.tkconsole.resetoutput()
736 self.checklinecache()
737 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000738 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
739 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000740
741 def checklinecache(self):
742 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000743 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000744 if key[:1] + key[-1:] != "<>":
745 del c[key]
746
Chui Tey5d2af632002-05-26 13:36:41 +0000747 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000748 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000749 # The code better not raise an exception!
750 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000751 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000752 return 0
753 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000754 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000755 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000756 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000757 return 1
758
David Scherer7aced172000-08-15 01:13:23 +0000759 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000760 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000761 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000762 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000763 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000764 if self.save_warnings_filters is not None:
765 warnings.filters[:] = self.save_warnings_filters
766 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000767 debugger = self.debugger
768 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000769 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000770 if not debugger and self.rpcclt is not None:
771 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
772 (code,), {})
773 elif debugger:
774 debugger.run(code, self.locals)
775 else:
776 exec(code, self.locals)
777 except SystemExit:
778 if not self.tkconsole.closing:
779 if tkMessageBox.askyesno(
780 "Exit?",
781 "Do you want to exit altogether?",
782 default="yes",
783 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000784 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000785 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000786 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000787 else:
788 raise
789 except:
790 if use_subprocess:
791 print("IDLE internal error in runcode()",
792 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000793 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000794 self.tkconsole.endexecuting()
795 else:
796 if self.tkconsole.canceled:
797 self.tkconsole.canceled = False
798 print("KeyboardInterrupt", file=self.tkconsole.stderr)
799 else:
800 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000801 finally:
802 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000803 try:
804 self.tkconsole.endexecuting()
805 except AttributeError: # shell may have closed
806 pass
David Scherer7aced172000-08-15 01:13:23 +0000807
808 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000809 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200810 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000811
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000812 def display_port_binding_error(self):
813 tkMessageBox.showerror(
814 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000815 "IDLE can't bind to a TCP/IP port, which is necessary to "
816 "communicate with its Python execution server. This might be "
817 "because no networking is installed on this computer. "
818 "Run IDLE with the -n command line switch to start without a "
819 "subprocess and refer to Help/IDLE Help 'Running without a "
820 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000821 master=self.tkconsole.text)
822
823 def display_no_subprocess_error(self):
824 tkMessageBox.showerror(
825 "Subprocess Startup Error",
826 "IDLE's subprocess didn't make connection. Either IDLE can't "
827 "start a subprocess or personal firewall software is blocking "
828 "the connection.",
829 master=self.tkconsole.text)
830
831 def display_executing_dialog(self):
832 tkMessageBox.showerror(
833 "Already executing",
834 "The Python Shell window is already executing a command; "
835 "please wait until it is finished.",
836 master=self.tkconsole.text)
837
838
David Scherer7aced172000-08-15 01:13:23 +0000839class PyShell(OutputWindow):
840
Terry Jan Reedy32622232013-03-30 18:32:19 -0400841 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000842
843 # Override classes
844 ColorDelegator = ModifiedColorDelegator
845 UndoDelegator = ModifiedUndoDelegator
846
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000847 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000848 menu_specs = [
849 ("file", "_File"),
850 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000851 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000852 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000853 ("windows", "_Windows"),
854 ("help", "_Help"),
855 ]
David Scherer7aced172000-08-15 01:13:23 +0000856
Ned Deilyb7601672014-03-27 20:49:14 -0700857 if sys.platform == "darwin":
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000858 menu_specs[-2] = ("windows", "_Window")
859
860
David Scherer7aced172000-08-15 01:13:23 +0000861 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000862 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000863
864 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000865 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000866 ms = self.menu_specs
867 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000868 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000869 self.interp = ModifiedInterpreter(self)
870 if flist is None:
871 root = Tk()
872 fixwordbreaks(root)
873 root.withdraw()
874 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000875 #
David Scherer7aced172000-08-15 01:13:23 +0000876 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000877 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000878## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
879 self.usetabs = True
880 # indentwidth must be 8 when using tabs. See note in EditorWindow:
881 self.indentwidth = 8
882 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000883 #
David Scherer7aced172000-08-15 01:13:23 +0000884 text = self.text
885 text.configure(wrap="char")
886 text.bind("<<newline-and-indent>>", self.enter_callback)
887 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
888 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000889 text.bind("<<end-of-file>>", self.eof_callback)
890 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000891 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000892 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000893 if use_subprocess:
894 text.bind("<<view-restart>>", self.view_restart_mark)
895 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000896 #
David Scherer7aced172000-08-15 01:13:23 +0000897 self.save_stdout = sys.stdout
898 self.save_stderr = sys.stderr
899 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000900 from idlelib import IOBinding
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200901 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
902 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
903 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
904 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000905 if not use_subprocess:
906 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000907 sys.stderr = self.stderr
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200908 sys.stdin = self.stdin
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000909 try:
910 # page help() text to shell.
911 import pydoc # import must be done here to capture i/o rebinding.
912 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
913 pydoc.pager = pydoc.plainpager
914 except:
915 sys.stderr = sys.__stderr__
916 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000917 #
David Scherer7aced172000-08-15 01:13:23 +0000918 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000919 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000920 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000921
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000922 def get_standard_extension_names(self):
923 return idleConf.GetExtensions(shell_only=True)
924
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000925 reading = False
926 executing = False
927 canceled = False
928 endoffile = False
929 closing = False
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500930 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000931
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000932 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000933 global warning_stream
934 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000935
936 def get_warning_stream(self):
937 return warning_stream
938
David Scherer7aced172000-08-15 01:13:23 +0000939 def toggle_debugger(self, event=None):
940 if self.executing:
941 tkMessageBox.showerror("Don't debug now",
942 "You can only toggle the debugger when idle",
943 master=self.text)
944 self.set_debugger_indicator()
945 return "break"
946 else:
947 db = self.interp.getdebugger()
948 if db:
949 self.close_debugger()
950 else:
951 self.open_debugger()
952
953 def set_debugger_indicator(self):
954 db = self.interp.getdebugger()
955 self.setvar("<<toggle-debugger>>", not not db)
956
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000957 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000958 pass # All we need is the variable
959
960 def close_debugger(self):
961 db = self.interp.getdebugger()
962 if db:
963 self.interp.setdebugger(None)
964 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000965 if self.interp.rpcclt:
966 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000967 self.resetoutput()
968 self.console.write("[DEBUG OFF]\n")
969 sys.ps1 = ">>> "
970 self.showprompt()
971 self.set_debugger_indicator()
972
973 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000974 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000975 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
976 self)
977 else:
978 dbg_gui = Debugger.Debugger(self)
979 self.interp.setdebugger(dbg_gui)
980 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000981 sys.ps1 = "[DEBUG ON]\n>>> "
982 self.showprompt()
983 self.set_debugger_indicator()
984
David Scherer7aced172000-08-15 01:13:23 +0000985 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000986 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000987 self.resetoutput()
988 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000989
990 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000991 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000992 self.executing = 0
993 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000994 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000995
996 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000997 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000998 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000999 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +00001000 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001001 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +00001002 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001003 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001004 if response is False:
David Scherer7aced172000-08-15 01:13:23 +00001005 return "cancel"
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001006 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001007 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001008 self.closing = True
Kurt B. Kaiser88957d82003-05-19 23:11:51 +00001009 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +00001010
1011 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001012 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +00001013 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001014 if use_subprocess:
1015 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001016 # Restore std streams
1017 sys.stdout = self.save_stdout
1018 sys.stderr = self.save_stderr
1019 sys.stdin = self.save_stdin
1020 # Break cycles
1021 self.interp = None
1022 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001023 self.flist.pyshell = None
1024 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001025 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001026
1027 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001028 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001029 return True
David Scherer7aced172000-08-15 01:13:23 +00001030
1031 def short_title(self):
1032 return self.shell_title
1033
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001034 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001035 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001036
David Scherer7aced172000-08-15 01:13:23 +00001037 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +00001038 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +00001039 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001040 if use_subprocess:
1041 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001042 client = self.interp.start_subprocess()
1043 if not client:
1044 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001045 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001046 else:
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001047 nosub = ("==== No Subprocess ====\n\n" +
Andrew Svetlov64478ac2012-10-05 22:16:55 +03001048 "WARNING: Running IDLE without a Subprocess is deprecated\n" +
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001049 "and will be removed in a later version. See Help/IDLE Help\n" +
1050 "for details.\n\n")
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001051 sys.displayhook = rpc.displayhook
1052
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001053 self.write("Python %s on %s\n%s\n%s" %
1054 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001055 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001056 import tkinter
1057 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001058 return True
David Scherer7aced172000-08-15 01:13:23 +00001059
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001060 def stop_readline(self):
1061 if not self.reading: # no nested mainloop to exit.
1062 return
1063 self._stop_readline_flag = True
1064 self.top.quit()
1065
David Scherer7aced172000-08-15 01:13:23 +00001066 def readline(self):
1067 save = self.reading
1068 try:
1069 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001070 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001071 finally:
1072 self.reading = save
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001073 if self._stop_readline_flag:
1074 self._stop_readline_flag = False
1075 return ""
David Scherer7aced172000-08-15 01:13:23 +00001076 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001077 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1078 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001079 self.resetoutput()
1080 if self.canceled:
1081 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001082 if not use_subprocess:
1083 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001084 if self.endoffile:
1085 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001086 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001087 return line
1088
1089 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001090 return True
David Scherer7aced172000-08-15 01:13:23 +00001091
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001092 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001093 try:
1094 if self.text.compare("sel.first", "!=", "sel.last"):
1095 return # Active selection -- always use default binding
1096 except:
1097 pass
1098 if not (self.executing or self.reading):
1099 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001100 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001101 self.showprompt()
1102 return "break"
1103 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001104 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001105 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001106 if self.interp.getdebugger():
1107 self.interp.restart_subprocess()
1108 else:
1109 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001110 if self.reading:
1111 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001112 return "break"
1113
1114 def eof_callback(self, event):
1115 if self.executing and not self.reading:
1116 return # Let the default binding (delete next char) take over
1117 if not (self.text.compare("iomark", "==", "insert") and
1118 self.text.compare("insert", "==", "end-1c")):
1119 return # Let the default binding (delete next char) take over
1120 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001121 self.resetoutput()
1122 self.close()
1123 else:
1124 self.canceled = 0
1125 self.endoffile = 1
1126 self.top.quit()
1127 return "break"
1128
David Scherer7aced172000-08-15 01:13:23 +00001129 def linefeed_callback(self, event):
1130 # Insert a linefeed without entering anything (still autoindented)
1131 if self.reading:
1132 self.text.insert("insert", "\n")
1133 self.text.see("insert")
1134 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001135 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001136 return "break"
1137
1138 def enter_callback(self, event):
1139 if self.executing and not self.reading:
1140 return # Let the default binding (insert '\n') take over
1141 # If some text is selected, recall the selection
1142 # (but only if this before the I/O mark)
1143 try:
1144 sel = self.text.get("sel.first", "sel.last")
1145 if sel:
1146 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001147 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001148 return "break"
1149 except:
1150 pass
1151 # If we're strictly before the line containing iomark, recall
1152 # the current line, less a leading prompt, less leading or
1153 # trailing whitespace
1154 if self.text.compare("insert", "<", "iomark linestart"):
1155 # Check if there's a relevant stdin range -- if so, use it
1156 prev = self.text.tag_prevrange("stdin", "insert")
1157 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001158 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001159 return "break"
1160 next = self.text.tag_nextrange("stdin", "insert")
1161 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001162 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001163 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001164 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001165 indices = self.text.tag_nextrange("console", "insert linestart")
1166 if indices and \
1167 self.text.compare(indices[0], "<=", "insert linestart"):
1168 self.recall(self.text.get(indices[1], "insert lineend"), event)
1169 else:
1170 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001171 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001172 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001173 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001174 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001175 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001176 # If we're in the current input and there's only whitespace
1177 # beyond the cursor, erase that whitespace first
1178 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001179 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001180 self.text.delete("insert", "end-1c")
1181 # If we're in the current input before its last line,
1182 # insert a newline right at the insert point
1183 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001184 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001185 return "break"
1186 # We're in the last line; append a newline and submit it
1187 self.text.mark_set("insert", "end-1c")
1188 if self.reading:
1189 self.text.insert("insert", "\n")
1190 self.text.see("insert")
1191 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001192 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001193 self.text.tag_add("stdin", "iomark", "end-1c")
1194 self.text.update_idletasks()
1195 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001196 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001197 else:
1198 self.runit()
1199 return "break"
1200
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001201 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001202 # remove leading and trailing empty or whitespace lines
1203 s = re.sub(r'^\s*\n', '' , s)
1204 s = re.sub(r'\n\s*$', '', s)
1205 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001206 self.text.undo_block_start()
1207 try:
1208 self.text.tag_remove("sel", "1.0", "end")
1209 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001210 prefix = self.text.get("insert linestart", "insert")
1211 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001212 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001213 prefix = self.text.get("insert linestart", "insert")
1214 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001215 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001216 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1217 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001218 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001219 if line.startswith(orig_base_indent):
1220 # replace orig base indentation with new indentation
1221 line = new_base_indent + line[len(orig_base_indent):]
1222 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001223 finally:
1224 self.text.see("insert")
1225 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001226
1227 def runit(self):
1228 line = self.text.get("iomark", "end-1c")
1229 # Strip off last newline and surrounding whitespace.
1230 # (To allow you to hit return twice to end a statement.)
1231 i = len(line)
1232 while i > 0 and line[i-1] in " \t":
1233 i = i-1
1234 if i > 0 and line[i-1] == "\n":
1235 i = i-1
1236 while i > 0 and line[i-1] in " \t":
1237 i = i-1
1238 line = line[:i]
1239 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001240
David Scherer7aced172000-08-15 01:13:23 +00001241 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001242 if self.interp.rpcclt:
1243 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001244 try:
1245 sys.last_traceback
1246 except:
1247 tkMessageBox.showerror("No stack trace",
1248 "There is no stack trace yet.\n"
1249 "(sys.last_traceback is not defined)",
1250 master=self.text)
1251 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001252 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001253 sv = StackBrowser(self.root, self.flist)
1254
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001255 def view_restart_mark(self, event=None):
1256 self.text.see("iomark")
1257 self.text.see("restart")
1258
1259 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001260 "Callback for Run/Restart Shell Cntl-F6"
1261 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001262
David Scherer7aced172000-08-15 01:13:23 +00001263 def showprompt(self):
1264 self.resetoutput()
1265 try:
1266 s = str(sys.ps1)
1267 except:
1268 s = ""
1269 self.console.write(s)
1270 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001271 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001272 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001273
1274 def resetoutput(self):
1275 source = self.text.get("iomark", "end-1c")
1276 if self.history:
Terry Jan Reedy0a01ac42013-08-13 19:51:04 -04001277 self.history.store(source)
David Scherer7aced172000-08-15 01:13:23 +00001278 if self.text.get("end-2c") != "\n":
1279 self.text.insert("end-1c", "\n")
1280 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001281 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001282
1283 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001284 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1285 # Tk doesn't support outputting non-BMP characters
1286 # Let's assume what printed string is not very long,
1287 # find first non-BMP character and construct informative
1288 # UnicodeEncodeError exception.
1289 for start, char in enumerate(s):
1290 if char > '\uffff':
1291 break
1292 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1293 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001294 try:
1295 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001296 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001297 self.text.mark_gravity("iomark", "left")
1298 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001299 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1300 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001301 if self.canceled:
1302 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001303 if not use_subprocess:
1304 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001305 return count
David Scherer7aced172000-08-15 01:13:23 +00001306
Andrew Svetlovd1837672012-11-01 22:41:19 +02001307 def rmenu_check_cut(self):
1308 try:
1309 if self.text.compare('sel.first', '<', 'iomark'):
1310 return 'disabled'
1311 except TclError: # no selection, so the index 'sel.first' doesn't exist
1312 return 'disabled'
1313 return super().rmenu_check_cut()
1314
1315 def rmenu_check_paste(self):
1316 if self.text.compare('insert','<','iomark'):
1317 return 'disabled'
1318 return super().rmenu_check_paste()
1319
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001320class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001321
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001322 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001323 self.shell = shell
1324 self.tags = tags
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001325 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001326
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001327 @property
1328 def encoding(self):
1329 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001330
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001331 @property
1332 def name(self):
1333 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001334
1335 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001336 return True
David Scherer7aced172000-08-15 01:13:23 +00001337
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001338
1339class PseudoOutputFile(PseudoFile):
1340
1341 def writable(self):
1342 return True
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001343
1344 def write(self, s):
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001345 if self.closed:
1346 raise ValueError("write to closed file")
Serhiy Storchaka9df8a1c2013-12-10 10:05:19 +02001347 if type(s) is not str:
1348 if not isinstance(s, str):
1349 raise TypeError('must be str, not ' + type(s).__name__)
1350 # See issue #19481
1351 s = str.__str__(s)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001352 return self.shell.write(s, self.tags)
1353
1354
1355class PseudoInputFile(PseudoFile):
1356
1357 def __init__(self, shell, tags, encoding=None):
1358 PseudoFile.__init__(self, shell, tags, encoding)
1359 self._line_buffer = ''
1360
1361 def readable(self):
1362 return True
1363
1364 def read(self, size=-1):
1365 if self.closed:
1366 raise ValueError("read from closed file")
1367 if size is None:
1368 size = -1
1369 elif not isinstance(size, int):
1370 raise TypeError('must be int, not ' + type(size).__name__)
1371 result = self._line_buffer
1372 self._line_buffer = ''
1373 if size < 0:
1374 while True:
1375 line = self.shell.readline()
1376 if not line: break
1377 result += line
1378 else:
1379 while len(result) < size:
1380 line = self.shell.readline()
1381 if not line: break
1382 result += line
1383 self._line_buffer = result[size:]
1384 result = result[:size]
1385 return result
1386
1387 def readline(self, size=-1):
1388 if self.closed:
1389 raise ValueError("read from closed file")
1390 if size is None:
1391 size = -1
1392 elif not isinstance(size, int):
1393 raise TypeError('must be int, not ' + type(size).__name__)
1394 line = self._line_buffer or self.shell.readline()
1395 if size < 0:
1396 size = len(line)
Serhiy Storchaka0fd55762013-12-25 14:24:35 +02001397 eol = line.find('\n', 0, size)
1398 if eol >= 0:
1399 size = eol + 1
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001400 self._line_buffer = line[size:]
1401 return line[:size]
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001402
Roger Serwy1eafd102013-04-11 19:16:44 -05001403 def close(self):
1404 self.shell.close()
1405
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001406
David Scherer7aced172000-08-15 01:13:23 +00001407usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001408
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001409USAGE: idle [-deins] [-t title] [file]*
1410 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1411 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001412
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001413 -h print this help message and exit
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001414 -n run IDLE without a subprocess (DEPRECATED,
1415 see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001416
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001417The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001418
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001419 -e open an edit window
1420 -i open a shell window
1421
1422The following options imply -i and will open a shell:
1423
1424 -c cmd run the command in a shell, or
1425 -r file run script from file
1426
1427 -d enable the debugger
1428 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1429 -t title set title of shell window
1430
1431A default edit window will be bypassed when -c, -r, or - are used.
1432
1433[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1434
1435Examples:
1436
1437idle
1438 Open an edit window or shell depending on IDLE's configuration.
1439
1440idle foo.py foobar.py
1441 Edit the files, also open a shell if configured to start with shell.
1442
1443idle -est "Baz" foo.py
1444 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1445 window with the title "Baz".
1446
Neal Norwitz752abd02008-05-13 04:55:24 +00001447idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001448 Open a shell window and run the command, passing "-c" in sys.argv[0]
1449 and "foo" in sys.argv[1].
1450
1451idle -d -s -r foo.py "Hello World"
1452 Open a shell window, run a startup script, enable the debugger, and
1453 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1454 sys.argv[1].
1455
Neal Norwitz752abd02008-05-13 04:55:24 +00001456echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001457 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1458 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001459"""
1460
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001461def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001462 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001463
Terry Jan Reedy95a3f112013-06-28 23:50:12 -04001464 capture_warnings(True)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001465 use_subprocess = True
Roger Serwyc35151c2013-03-31 23:28:55 -05001466 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001467 enable_edit = False
1468 debug = False
1469 cmd = None
1470 script = None
1471 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001472 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001473 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001474 except getopt.error as msg:
Terry Jan Reedy81b062f2014-09-19 22:38:41 -04001475 print("Error: %s\n%s" % (msg, usage_msg), file=sys.stderr)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001476 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001477 for o, a in opts:
1478 if o == '-c':
1479 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001480 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001481 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001482 debug = True
1483 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001484 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001485 enable_edit = True
1486 if o == '-h':
1487 sys.stdout.write(usage_msg)
1488 sys.exit()
1489 if o == '-i':
1490 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001491 if o == '-n':
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001492 print(" Warning: running IDLE without a subprocess is deprecated.",
1493 file=sys.stderr)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001494 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001495 if o == '-r':
1496 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001497 if os.path.isfile(script):
1498 pass
1499 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001500 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001501 sys.exit()
1502 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001503 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001504 startup = True
1505 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001506 if o == '-t':
1507 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001508 enable_shell = True
1509 if args and args[0] == '-':
1510 cmd = sys.stdin.read()
1511 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001512 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001513 for i in range(len(sys.path)):
1514 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001515 if args and args[0] == '-':
1516 sys.argv = [''] + args[1:]
1517 elif cmd:
1518 sys.argv = ['-c'] + args
1519 elif script:
1520 sys.argv = [script] + args
1521 elif args:
1522 enable_edit = True
1523 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001524 for filename in args:
1525 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001526 for dir in pathx:
1527 dir = os.path.abspath(dir)
1528 if not dir in sys.path:
1529 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001530 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001531 dir = os.getcwd()
1532 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001533 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001534 # check the IDLE settings configuration (but command line overrides)
1535 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001536 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001537 enable_edit = enable_edit or edit_start
Roger Serwyc35151c2013-03-31 23:28:55 -05001538 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001539 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001540 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001541
Terry Jan Reedya7c07d32014-02-08 09:02:26 -05001542 # set application icon
1543 icondir = os.path.join(os.path.dirname(__file__), 'Icons')
1544 if system() == 'Windows':
1545 iconfile = os.path.join(icondir, 'idle.ico')
1546 root.wm_iconbitmap(default=iconfile)
1547 elif TkVersion >= 8.5:
1548 ext = '.png' if TkVersion >= 8.6 else '.gif'
1549 iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
1550 for size in (16, 32, 48)]
1551 icons = [PhotoImage(file=iconfile) for iconfile in iconfiles]
1552 root.wm_iconphoto(True, *icons)
1553
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001554 fixwordbreaks(root)
1555 root.withdraw()
1556 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001557 macosxSupport.setupApp(root, flist)
1558
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001559 if enable_edit:
1560 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001561 for filename in args[:]:
1562 if flist.open(filename) is None:
1563 # filename is a directory actually, disconsider it
1564 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001565 if not args:
1566 flist.new()
Ned Deilyf3c65892013-12-10 16:24:01 -08001567
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001568 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001569 shell = flist.open_shell()
1570 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001571 return # couldn't open shell
Ned Deilyb7601672014-03-27 20:49:14 -07001572 if macosxSupport.isAquaTk() and flist.dict:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001573 # On OSX: when the user has double-clicked on a file that causes
1574 # IDLE to be launched the shell window will open just in front of
1575 # the file she wants to see. Lower the interpreter window when
1576 # there are open files.
1577 shell.top.lower()
Ned Deilyf3c65892013-12-10 16:24:01 -08001578 else:
1579 shell = flist.pyshell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001580
Ned Deilyf3c65892013-12-10 16:24:01 -08001581 # Handle remaining options. If any of these are set, enable_shell
1582 # was set also, so shell must be true to reach here.
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001583 if debug:
1584 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001585 if startup:
1586 filename = os.environ.get("IDLESTARTUP") or \
1587 os.environ.get("PYTHONSTARTUP")
1588 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001589 shell.interp.execfile(filename)
Ned Deilyf3c65892013-12-10 16:24:01 -08001590 if cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001591 shell.interp.runcommand("""if 1:
1592 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001593 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001594 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001595 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001596 if cmd:
1597 shell.interp.execsource(cmd)
1598 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001599 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001600 shell.interp.execfile(script)
Ned Deilyf3c65892013-12-10 16:24:01 -08001601 elif shell:
1602 # If there is a shell window and no cmd or script in progress,
1603 # check for problematic OS X Tk versions and print a warning
1604 # message in the IDLE shell window; this is less intrusive
1605 # than always opening a separate window.
1606 tkversionwarning = macosxSupport.tkVersionWarning(root)
1607 if tkversionwarning:
1608 shell.interp.runcommand("print('%s')" % tkversionwarning)
Ned Deily4ce92b22011-01-15 04:37:12 +00001609
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001610 while flist.inversedict: # keep IDLE running while files are open.
1611 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001612 root.destroy()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -04001613 capture_warnings(False)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001614
David Scherer7aced172000-08-15 01:13:23 +00001615if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001616 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001617 main()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -04001618
1619capture_warnings(False) # Make sure turned off; see issue 18081