blob: 6b439885b27cce463b675764226ce7be0bd17345 [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"
Terry Jan Reedyefc72582014-10-12 22:58:47 -0400154 if self.io is None:
155 # possible due to update in restore_file_breaks
156 return
Terry Jan Reedyda26cca2014-08-08 23:33:16 -0400157 if color:
158 theme = idleConf.GetOption('main','Theme','name')
159 cfg = idleConf.GetHighlight(theme, "break")
160 else:
161 cfg = {'foreground': '', 'background': ''}
162 self.text.tag_config('BREAK', cfg)
163
Chui Teya2adb0f2002-11-04 22:14:54 +0000164 def set_breakpoint(self, lineno):
165 text = self.text
166 filename = self.io.filename
167 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
168 try:
169 i = self.breakpoints.index(lineno)
170 except ValueError: # only add if missing, i.e. do once
171 self.breakpoints.append(lineno)
172 try: # update the subprocess debugger
173 debug = self.flist.pyshell.interp.debugger
174 debug.set_breakpoint_here(filename, lineno)
175 except: # but debugger may not be active right now....
176 pass
177
David Scherer7aced172000-08-15 01:13:23 +0000178 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000179 text = self.text
180 filename = self.io.filename
181 if not filename:
182 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000183 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000184 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000185 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000186
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000187 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000188 text = self.text
189 filename = self.io.filename
190 if not filename:
191 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000192 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000193 lineno = int(float(text.index("insert")))
194 try:
195 self.breakpoints.remove(lineno)
196 except:
197 pass
198 text.tag_remove("BREAK", "insert linestart",\
199 "insert lineend +1char")
200 try:
201 debug = self.flist.pyshell.interp.debugger
202 debug.clear_breakpoint_here(filename, lineno)
203 except:
204 pass
205
206 def clear_file_breaks(self):
207 if self.breakpoints:
208 text = self.text
209 filename = self.io.filename
210 if not filename:
211 text.bell()
212 return
213 self.breakpoints = []
214 text.tag_remove("BREAK", "1.0", END)
215 try:
216 debug = self.flist.pyshell.interp.debugger
217 debug.clear_file_breaks(filename)
218 except:
219 pass
220
Chui Teya2adb0f2002-11-04 22:14:54 +0000221 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000222 "Save breakpoints when file is saved"
223 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
224 # be run. The breaks are saved at that time. If we introduce
225 # a temporary file save feature the save breaks functionality
226 # needs to be re-verified, since the breaks at the time the
227 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000228 # permanent save of the file. Currently, a break introduced
229 # after a save will be effective, but not persistent.
230 # This is necessary to keep the saved breaks synched with the
231 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000232 #
Terry Jan Reedy6b04dc92014-10-12 01:11:05 -0400233 # Breakpoints are set as tagged ranges in the text.
234 # Since a modified file has to be saved before it is
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 # run, and since self.breakpoints (from which the subprocess
236 # debugger is loaded) is updated during the save, the visible
237 # breaks stay synched with the subprocess even if one of these
238 # unexpected breakpoint deletions occurs.
239 breaks = self.breakpoints
240 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000241 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200242 with open(self.breakpointPath, "r") as fp:
243 lines = fp.readlines()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200244 except OSError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000245 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800246 try:
247 with open(self.breakpointPath, "w") as new_file:
248 for line in lines:
249 if not line.startswith(filename + '='):
250 new_file.write(line)
251 self.update_breakpoints()
252 breaks = self.breakpoints
253 if breaks:
254 new_file.write(filename + '=' + str(breaks) + '\n')
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200255 except OSError as err:
Ned Deilyf505b742011-12-14 14:58:24 -0800256 if not getattr(self.root, "breakpoint_error_displayed", False):
257 self.root.breakpoint_error_displayed = True
258 tkMessageBox.showerror(title='IDLE Error',
259 message='Unable to update breakpoint list:\n%s'
260 % str(err),
261 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000262
263 def restore_file_breaks(self):
264 self.text.update() # this enables setting "BREAK" tags to be visible
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500265 if self.io is None:
266 # can happen if IDLE closes due to the .update() call
267 return
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000268 filename = self.io.filename
269 if filename is None:
270 return
Chui Tey69371d62002-11-04 23:39:45 +0000271 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200272 with open(self.breakpointPath, "r") as fp:
273 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000274 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000275 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000276 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000277 for breakpoint_linenumber in breakpoint_linenumbers:
278 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000279
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000280 def update_breakpoints(self):
281 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000282 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000283 ranges = text.tag_ranges("BREAK")
284 linenumber_list = self.ranges_to_linenumbers(ranges)
285 self.breakpoints = linenumber_list
286
287 def ranges_to_linenumbers(self, ranges):
288 lines = []
289 for index in range(0, len(ranges), 2):
Andrew Svetlov06c5c6d2012-07-31 19:48:00 +0300290 lineno = int(float(ranges[index].string))
291 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000292 while lineno < end:
293 lines.append(lineno)
294 lineno += 1
295 return lines
296
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000297# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000298# def saved_change_hook(self):
299# "Extend base method - clear breaks if module is modified"
300# if not self.get_saved():
301# self.clear_file_breaks()
302# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000303
304 def _close(self):
305 "Extend base method - clear breaks when module is closed"
306 self.clear_file_breaks()
307 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000308
David Scherer7aced172000-08-15 01:13:23 +0000309
310class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000311 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000312
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000313 # override FileList's class variable, instances return PyShellEditorWindow
314 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000315 EditorWindow = PyShellEditorWindow
316
317 pyshell = None
318
319 def open_shell(self, event=None):
320 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000321 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000322 else:
323 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000324 if self.pyshell:
325 if not self.pyshell.begin():
326 return None
David Scherer7aced172000-08-15 01:13:23 +0000327 return self.pyshell
328
329
330class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000331 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000332
Steven M. Gavab77d3432002-03-02 07:16:21 +0000333 def __init__(self):
334 ColorDelegator.__init__(self)
335 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000336
337 def recolorize_main(self):
338 self.tag_remove("TODO", "1.0", "iomark")
339 self.tag_add("SYNC", "1.0", "iomark")
340 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000341
Steven M. Gavab77d3432002-03-02 07:16:21 +0000342 def LoadTagDefs(self):
343 ColorDelegator.LoadTagDefs(self)
344 theme = idleConf.GetOption('main','Theme','name')
345 self.tagdefs.update({
346 "stdin": {'background':None,'foreground':None},
347 "stdout": idleConf.GetHighlight(theme, "stdout"),
348 "stderr": idleConf.GetHighlight(theme, "stderr"),
349 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000350 })
David Scherer7aced172000-08-15 01:13:23 +0000351
Ned Deily8b2a56b2012-05-31 09:17:29 -0700352 def removecolors(self):
353 # Don't remove shell color tags before "iomark"
354 for tag in self.tagdefs:
355 self.tag_remove(tag, "iomark", "end")
356
David Scherer7aced172000-08-15 01:13:23 +0000357class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000358 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000359
360 def insert(self, index, chars, tags=None):
361 try:
362 if self.delegate.compare(index, "<", "iomark"):
363 self.delegate.bell()
364 return
365 except TclError:
366 pass
367 UndoDelegator.insert(self, index, chars, tags)
368
369 def delete(self, index1, index2=None):
370 try:
371 if self.delegate.compare(index1, "<", "iomark"):
372 self.delegate.bell()
373 return
374 except TclError:
375 pass
376 UndoDelegator.delete(self, index1, index2)
377
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000378
379class MyRPCClient(rpc.RPCClient):
380
381 def handle_EOF(self):
382 "Override the base class - just re-raise EOFError"
383 raise EOFError
384
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000385
David Scherer7aced172000-08-15 01:13:23 +0000386class ModifiedInterpreter(InteractiveInterpreter):
387
388 def __init__(self, tkconsole):
389 self.tkconsole = tkconsole
390 locals = sys.modules['__main__'].__dict__
391 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000392 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000393 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000394 self.subprocess_arglist = None
395 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700396 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000397
Roger Serwy036e8492013-06-11 22:13:17 -0500398 _afterid = None
Chui Tey5d2af632002-05-26 13:36:41 +0000399 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700400 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000401
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000402 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000403 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000404 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700405 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000406
Tony Lowndsf53dec22002-12-20 04:24:43 +0000407 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000408 assert (self.port!=0), (
409 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000410 w = ['-W' + s for s in sys.warnoptions]
411 # Maybe IDLE is installed and is being accessed via sys.path,
412 # or maybe it's not installed and the idle.py script is being
413 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000414 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
415 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000416 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000417 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000418 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000419 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700420 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000421
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000422 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000423 addr = (HOST, self.port)
424 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000425 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000426 time.sleep(i)
427 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000428 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000429 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200430 except OSError as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000431 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000432 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000433 self.display_port_binding_error()
434 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000435 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
436 self.port = self.rpcclt.listening_sock.getsockname()[1]
437 # if PORT was not 0, probably working with a remote execution server
438 if PORT != 0:
439 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
440 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
441 # on Windows since the implementation allows two active sockets on
442 # the same address!
443 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
444 socket.SO_REUSEADDR, 1)
445 self.spawn_subprocess()
446 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000447 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000448 self.rpcclt.listening_sock.settimeout(10)
449 try:
450 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000451 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000452 self.display_no_subprocess_error()
453 return None
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200454 self.rpcclt.register("console", self.tkconsole)
455 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000456 self.rpcclt.register("stdout", self.tkconsole.stdout)
457 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000458 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000459 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000460 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500461 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000462 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000463 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000464
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500465 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000466 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000467 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000468 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000469 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000470 debug = self.getdebugger()
471 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000472 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000473 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000474 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
475 except:
476 pass
477 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000478 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700479 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000480 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000481 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000482 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000483 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000484 try:
485 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000486 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000487 self.display_no_subprocess_error()
488 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500489 self.transfer_path(with_cwd=with_cwd)
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500490 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000491 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000492 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000493 if was_executing:
494 console.write('\n')
495 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000496 halfbar = ((int(console.width) - 16) // 2) * '='
497 console.write(halfbar + ' RESTART ' + halfbar)
498 console.text.mark_set("restart", "end-1c")
499 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000500 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000501 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000502 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000503 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000504 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000505 # reload remote debugger breakpoints for all PyShellEditWindows
506 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700507 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000508 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000509 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000510
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000511 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000512 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000513
514 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000515 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000516
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000517 def kill_subprocess(self):
Roger Serwy036e8492013-06-11 22:13:17 -0500518 if self._afterid is not None:
519 self.tkconsole.text.after_cancel(self._afterid)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000520 try:
Ned Deily55f87572011-11-05 22:36:44 -0700521 self.rpcclt.listening_sock.close()
522 except AttributeError: # no socket
523 pass
524 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000525 self.rpcclt.close()
526 except AttributeError: # no socket
527 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700528 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000529 self.tkconsole.executing = False
530 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000531
Ned Deilye5cad232011-08-02 18:47:13 -0700532 def terminate_subprocess(self):
533 "Make sure subprocess is terminated"
534 try:
535 self.rpcsubproc.kill()
536 except OSError:
537 # process already terminated
538 return
539 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000540 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700541 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000542 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000543 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000544
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500545 def transfer_path(self, with_cwd=False):
546 if with_cwd: # Issue 13506
547 path = [''] # include Current Working Directory
548 path.extend(sys.path)
549 else:
550 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500551
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000552 self.runcommand("""if 1:
553 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000554 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000555 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500556 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000557
Chui Tey5d2af632002-05-26 13:36:41 +0000558 active_seq = None
559
560 def poll_subprocess(self):
561 clt = self.rpcclt
562 if clt is None:
563 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000564 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000565 response = clt.pollresponse(self.active_seq, wait=0.05)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200566 except (EOFError, OSError, KeyboardInterrupt):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000567 # lost connection or subprocess terminated itself, restart
568 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000569 if self.tkconsole.closing:
570 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000571 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000572 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000573 if response:
574 self.tkconsole.resetoutput()
575 self.active_seq = None
576 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000577 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000578 if how == "OK":
579 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000580 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000581 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000582 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
583 self.remote_stack_viewer()
584 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000585 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000586 print(errmsg, what, file=sys.__stderr__)
587 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000588 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000589 try:
590 self.tkconsole.endexecuting()
591 except AttributeError: # shell may have closed
592 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000593 # Reschedule myself
594 if not self.tkconsole.closing:
Roger Serwy036e8492013-06-11 22:13:17 -0500595 self._afterid = self.tkconsole.text.after(
596 self.tkconsole.pollinterval, self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000597
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000598 debugger = None
599
600 def setdebugger(self, debugger):
601 self.debugger = debugger
602
603 def getdebugger(self):
604 return self.debugger
605
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000606 def open_remote_stack_viewer(self):
607 """Initiate the remote stack viewer from a separate thread.
608
609 This method is called from the subprocess, and by returning from this
610 method we allow the subprocess to unblock. After a bit the shell
611 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000612 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000613 the RPC mechanism.
614
615 """
616 self.tkconsole.text.after(300, self.remote_stack_viewer)
617 return
618
Chui Tey5d2af632002-05-26 13:36:41 +0000619 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000620 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000621 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000622 if oid is None:
623 self.tkconsole.root.bell()
624 return
625 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000626 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000627 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000628 theme = idleConf.GetOption('main','Theme','name')
629 background = idleConf.GetHighlight(theme, 'normal')['background']
630 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000631 sc.frame.pack(expand=1, fill="both")
632 node = TreeNode(sc.canvas, None, item)
633 node.expand()
634 # XXX Should GC the remote tree when closing the window
635
David Scherer7aced172000-08-15 01:13:23 +0000636 gid = 0
637
638 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000639 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000640 filename = self.stuffsource(source)
641 self.execfile(filename, source)
642
643 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000644 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000645 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200646 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200647 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000648 try:
649 code = compile(source, filename, "exec")
650 except (OverflowError, SyntaxError):
651 self.tkconsole.resetoutput()
Terry Jan Reedy81b062f2014-09-19 22:38:41 -0400652 print('*** Error in script or command!\n'
653 'Traceback (most recent call last):',
654 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000655 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000656 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000657 else:
658 self.runcode(code)
659
660 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000661 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000662 filename = self.stuffsource(source)
663 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000664 self.save_warnings_filters = warnings.filters[:]
665 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000666 # at the moment, InteractiveInterpreter expects str
667 assert isinstance(source, str)
668 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000669 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000670 # try:
671 # source = source.encode(IOBinding.encoding)
672 # except UnicodeError:
673 # self.tkconsole.resetoutput()
674 # self.write("Unsupported characters in input\n")
675 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000676 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000677 # InteractiveInterpreter.runsource() calls its runcode() method,
678 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000679 return InteractiveInterpreter.runsource(self, source, filename)
680 finally:
681 if self.save_warnings_filters is not None:
682 warnings.filters[:] = self.save_warnings_filters
683 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000684
685 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000686 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000687 filename = "<pyshell#%d>" % self.gid
688 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000689 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000690 linecache.cache[filename] = len(source)+1, 0, lines, filename
691 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000692
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000693 def prepend_syspath(self, filename):
694 "Prepend sys.path with file's directory if not already included"
695 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000696 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000697 import sys as _sys
698 from os.path import dirname as _dirname
699 _dir = _dirname(_filename)
700 if not _dir in _sys.path:
701 _sys.path.insert(0, _dir)
702 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000703 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000704
David Scherer7aced172000-08-15 01:13:23 +0000705 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000706 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000707
708 Color the offending position instead of printing it and pointing at it
709 with a caret.
710
711 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000712 tkconsole = self.tkconsole
713 text = tkconsole.text
714 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000715 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700716 msg = getattr(value, 'msg', '') or value or "<no detail available>"
717 lineno = getattr(value, 'lineno', '') or 1
718 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000719 if offset == 0:
720 lineno += 1 #mark end of offending line
721 if lineno == 1:
722 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000723 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000724 pos = "iomark linestart + %d lines + %d chars" % \
725 (lineno-1, offset-1)
726 tkconsole.colorize_syntax_error(text, pos)
727 tkconsole.resetoutput()
728 self.write("SyntaxError: %s\n" % msg)
729 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000730
731 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000732 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000733 self.tkconsole.resetoutput()
734 self.checklinecache()
735 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000736 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
737 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000738
739 def checklinecache(self):
740 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000741 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000742 if key[:1] + key[-1:] != "<>":
743 del c[key]
744
Chui Tey5d2af632002-05-26 13:36:41 +0000745 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000746 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000747 # The code better not raise an exception!
748 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000749 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000750 return 0
751 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000752 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000753 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000754 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000755 return 1
756
David Scherer7aced172000-08-15 01:13:23 +0000757 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000758 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000759 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000760 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000761 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000762 if self.save_warnings_filters is not None:
763 warnings.filters[:] = self.save_warnings_filters
764 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000765 debugger = self.debugger
766 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000767 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000768 if not debugger and self.rpcclt is not None:
769 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
770 (code,), {})
771 elif debugger:
772 debugger.run(code, self.locals)
773 else:
774 exec(code, self.locals)
775 except SystemExit:
776 if not self.tkconsole.closing:
777 if tkMessageBox.askyesno(
778 "Exit?",
779 "Do you want to exit altogether?",
780 default="yes",
781 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000782 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000783 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000784 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000785 else:
786 raise
787 except:
788 if use_subprocess:
789 print("IDLE internal error in runcode()",
790 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000791 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000792 self.tkconsole.endexecuting()
793 else:
794 if self.tkconsole.canceled:
795 self.tkconsole.canceled = False
796 print("KeyboardInterrupt", file=self.tkconsole.stderr)
797 else:
798 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000799 finally:
800 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000801 try:
802 self.tkconsole.endexecuting()
803 except AttributeError: # shell may have closed
804 pass
David Scherer7aced172000-08-15 01:13:23 +0000805
806 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000807 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200808 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000809
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000810 def display_port_binding_error(self):
811 tkMessageBox.showerror(
812 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000813 "IDLE can't bind to a TCP/IP port, which is necessary to "
814 "communicate with its Python execution server. This might be "
815 "because no networking is installed on this computer. "
816 "Run IDLE with the -n command line switch to start without a "
817 "subprocess and refer to Help/IDLE Help 'Running without a "
818 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000819 master=self.tkconsole.text)
820
821 def display_no_subprocess_error(self):
822 tkMessageBox.showerror(
823 "Subprocess Startup Error",
824 "IDLE's subprocess didn't make connection. Either IDLE can't "
825 "start a subprocess or personal firewall software is blocking "
826 "the connection.",
827 master=self.tkconsole.text)
828
829 def display_executing_dialog(self):
830 tkMessageBox.showerror(
831 "Already executing",
832 "The Python Shell window is already executing a command; "
833 "please wait until it is finished.",
834 master=self.tkconsole.text)
835
836
David Scherer7aced172000-08-15 01:13:23 +0000837class PyShell(OutputWindow):
838
Terry Jan Reedy32622232013-03-30 18:32:19 -0400839 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000840
841 # Override classes
842 ColorDelegator = ModifiedColorDelegator
843 UndoDelegator = ModifiedUndoDelegator
844
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000845 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000846 menu_specs = [
847 ("file", "_File"),
848 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000849 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000850 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000851 ("windows", "_Windows"),
852 ("help", "_Help"),
853 ]
David Scherer7aced172000-08-15 01:13:23 +0000854
Ned Deilyb7601672014-03-27 20:49:14 -0700855 if sys.platform == "darwin":
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000856 menu_specs[-2] = ("windows", "_Window")
857
858
David Scherer7aced172000-08-15 01:13:23 +0000859 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000860 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000861
862 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000863 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000864 ms = self.menu_specs
865 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000866 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000867 self.interp = ModifiedInterpreter(self)
868 if flist is None:
869 root = Tk()
870 fixwordbreaks(root)
871 root.withdraw()
872 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000873 #
David Scherer7aced172000-08-15 01:13:23 +0000874 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000875 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000876## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
877 self.usetabs = True
878 # indentwidth must be 8 when using tabs. See note in EditorWindow:
879 self.indentwidth = 8
880 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000881 #
David Scherer7aced172000-08-15 01:13:23 +0000882 text = self.text
883 text.configure(wrap="char")
884 text.bind("<<newline-and-indent>>", self.enter_callback)
885 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
886 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000887 text.bind("<<end-of-file>>", self.eof_callback)
888 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000889 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000890 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000891 if use_subprocess:
892 text.bind("<<view-restart>>", self.view_restart_mark)
893 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000894 #
David Scherer7aced172000-08-15 01:13:23 +0000895 self.save_stdout = sys.stdout
896 self.save_stderr = sys.stderr
897 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000898 from idlelib import IOBinding
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200899 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
900 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
901 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
902 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000903 if not use_subprocess:
904 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000905 sys.stderr = self.stderr
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200906 sys.stdin = self.stdin
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000907 try:
908 # page help() text to shell.
909 import pydoc # import must be done here to capture i/o rebinding.
910 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
911 pydoc.pager = pydoc.plainpager
912 except:
913 sys.stderr = sys.__stderr__
914 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000915 #
David Scherer7aced172000-08-15 01:13:23 +0000916 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000917 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000918 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000919
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000920 def get_standard_extension_names(self):
921 return idleConf.GetExtensions(shell_only=True)
922
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000923 reading = False
924 executing = False
925 canceled = False
926 endoffile = False
927 closing = False
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500928 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000929
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000930 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000931 global warning_stream
932 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000933
934 def get_warning_stream(self):
935 return warning_stream
936
David Scherer7aced172000-08-15 01:13:23 +0000937 def toggle_debugger(self, event=None):
938 if self.executing:
939 tkMessageBox.showerror("Don't debug now",
940 "You can only toggle the debugger when idle",
941 master=self.text)
942 self.set_debugger_indicator()
943 return "break"
944 else:
945 db = self.interp.getdebugger()
946 if db:
947 self.close_debugger()
948 else:
949 self.open_debugger()
950
951 def set_debugger_indicator(self):
952 db = self.interp.getdebugger()
953 self.setvar("<<toggle-debugger>>", not not db)
954
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000955 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000956 pass # All we need is the variable
957
958 def close_debugger(self):
959 db = self.interp.getdebugger()
960 if db:
961 self.interp.setdebugger(None)
962 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000963 if self.interp.rpcclt:
964 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000965 self.resetoutput()
966 self.console.write("[DEBUG OFF]\n")
967 sys.ps1 = ">>> "
968 self.showprompt()
969 self.set_debugger_indicator()
970
971 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000972 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000973 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
974 self)
975 else:
976 dbg_gui = Debugger.Debugger(self)
977 self.interp.setdebugger(dbg_gui)
978 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000979 sys.ps1 = "[DEBUG ON]\n>>> "
980 self.showprompt()
981 self.set_debugger_indicator()
982
David Scherer7aced172000-08-15 01:13:23 +0000983 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000984 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000985 self.resetoutput()
986 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000987
988 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000989 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000990 self.executing = 0
991 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000992 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000993
994 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000995 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000996 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000997 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000998 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000999 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +00001000 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001001 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001002 if response is False:
David Scherer7aced172000-08-15 01:13:23 +00001003 return "cancel"
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001004 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001005 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001006 self.closing = True
Kurt B. Kaiser88957d82003-05-19 23:11:51 +00001007 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +00001008
1009 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001010 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +00001011 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001012 if use_subprocess:
1013 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001014 # Restore std streams
1015 sys.stdout = self.save_stdout
1016 sys.stderr = self.save_stderr
1017 sys.stdin = self.save_stdin
1018 # Break cycles
1019 self.interp = None
1020 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001021 self.flist.pyshell = None
1022 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001023 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001024
1025 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001026 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001027 return True
David Scherer7aced172000-08-15 01:13:23 +00001028
1029 def short_title(self):
1030 return self.shell_title
1031
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001032 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001033 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001034
David Scherer7aced172000-08-15 01:13:23 +00001035 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +00001036 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +00001037 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001038 if use_subprocess:
1039 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001040 client = self.interp.start_subprocess()
1041 if not client:
1042 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001043 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001044 else:
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001045 nosub = ("==== No Subprocess ====\n\n" +
Andrew Svetlov64478ac2012-10-05 22:16:55 +03001046 "WARNING: Running IDLE without a Subprocess is deprecated\n" +
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001047 "and will be removed in a later version. See Help/IDLE Help\n" +
1048 "for details.\n\n")
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001049 sys.displayhook = rpc.displayhook
1050
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001051 self.write("Python %s on %s\n%s\n%s" %
1052 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001053 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001054 import tkinter
1055 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001056 return True
David Scherer7aced172000-08-15 01:13:23 +00001057
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001058 def stop_readline(self):
1059 if not self.reading: # no nested mainloop to exit.
1060 return
1061 self._stop_readline_flag = True
1062 self.top.quit()
1063
David Scherer7aced172000-08-15 01:13:23 +00001064 def readline(self):
1065 save = self.reading
1066 try:
1067 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001068 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001069 finally:
1070 self.reading = save
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001071 if self._stop_readline_flag:
1072 self._stop_readline_flag = False
1073 return ""
David Scherer7aced172000-08-15 01:13:23 +00001074 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001075 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1076 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001077 self.resetoutput()
1078 if self.canceled:
1079 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001080 if not use_subprocess:
1081 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001082 if self.endoffile:
1083 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001084 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001085 return line
1086
1087 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001088 return True
David Scherer7aced172000-08-15 01:13:23 +00001089
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001090 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001091 try:
1092 if self.text.compare("sel.first", "!=", "sel.last"):
1093 return # Active selection -- always use default binding
1094 except:
1095 pass
1096 if not (self.executing or self.reading):
1097 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001098 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001099 self.showprompt()
1100 return "break"
1101 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001102 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001103 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001104 if self.interp.getdebugger():
1105 self.interp.restart_subprocess()
1106 else:
1107 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001108 if self.reading:
1109 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001110 return "break"
1111
1112 def eof_callback(self, event):
1113 if self.executing and not self.reading:
1114 return # Let the default binding (delete next char) take over
1115 if not (self.text.compare("iomark", "==", "insert") and
1116 self.text.compare("insert", "==", "end-1c")):
1117 return # Let the default binding (delete next char) take over
1118 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001119 self.resetoutput()
1120 self.close()
1121 else:
1122 self.canceled = 0
1123 self.endoffile = 1
1124 self.top.quit()
1125 return "break"
1126
David Scherer7aced172000-08-15 01:13:23 +00001127 def linefeed_callback(self, event):
1128 # Insert a linefeed without entering anything (still autoindented)
1129 if self.reading:
1130 self.text.insert("insert", "\n")
1131 self.text.see("insert")
1132 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001133 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001134 return "break"
1135
1136 def enter_callback(self, event):
1137 if self.executing and not self.reading:
1138 return # Let the default binding (insert '\n') take over
1139 # If some text is selected, recall the selection
1140 # (but only if this before the I/O mark)
1141 try:
1142 sel = self.text.get("sel.first", "sel.last")
1143 if sel:
1144 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001145 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001146 return "break"
1147 except:
1148 pass
1149 # If we're strictly before the line containing iomark, recall
1150 # the current line, less a leading prompt, less leading or
1151 # trailing whitespace
1152 if self.text.compare("insert", "<", "iomark linestart"):
1153 # Check if there's a relevant stdin range -- if so, use it
1154 prev = self.text.tag_prevrange("stdin", "insert")
1155 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001156 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001157 return "break"
1158 next = self.text.tag_nextrange("stdin", "insert")
1159 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001160 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001161 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001162 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001163 indices = self.text.tag_nextrange("console", "insert linestart")
1164 if indices and \
1165 self.text.compare(indices[0], "<=", "insert linestart"):
1166 self.recall(self.text.get(indices[1], "insert lineend"), event)
1167 else:
1168 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001169 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001170 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001171 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001172 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001173 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001174 # If we're in the current input and there's only whitespace
1175 # beyond the cursor, erase that whitespace first
1176 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001177 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001178 self.text.delete("insert", "end-1c")
1179 # If we're in the current input before its last line,
1180 # insert a newline right at the insert point
1181 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001182 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001183 return "break"
1184 # We're in the last line; append a newline and submit it
1185 self.text.mark_set("insert", "end-1c")
1186 if self.reading:
1187 self.text.insert("insert", "\n")
1188 self.text.see("insert")
1189 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001190 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001191 self.text.tag_add("stdin", "iomark", "end-1c")
1192 self.text.update_idletasks()
1193 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001194 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001195 else:
1196 self.runit()
1197 return "break"
1198
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001199 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001200 # remove leading and trailing empty or whitespace lines
1201 s = re.sub(r'^\s*\n', '' , s)
1202 s = re.sub(r'\n\s*$', '', s)
1203 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001204 self.text.undo_block_start()
1205 try:
1206 self.text.tag_remove("sel", "1.0", "end")
1207 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001208 prefix = self.text.get("insert linestart", "insert")
1209 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001210 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001211 prefix = self.text.get("insert linestart", "insert")
1212 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001213 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001214 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1215 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001216 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001217 if line.startswith(orig_base_indent):
1218 # replace orig base indentation with new indentation
1219 line = new_base_indent + line[len(orig_base_indent):]
1220 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001221 finally:
1222 self.text.see("insert")
1223 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001224
1225 def runit(self):
1226 line = self.text.get("iomark", "end-1c")
1227 # Strip off last newline and surrounding whitespace.
1228 # (To allow you to hit return twice to end a statement.)
1229 i = len(line)
1230 while i > 0 and line[i-1] in " \t":
1231 i = i-1
1232 if i > 0 and line[i-1] == "\n":
1233 i = i-1
1234 while i > 0 and line[i-1] in " \t":
1235 i = i-1
1236 line = line[:i]
1237 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001238
David Scherer7aced172000-08-15 01:13:23 +00001239 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001240 if self.interp.rpcclt:
1241 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001242 try:
1243 sys.last_traceback
1244 except:
1245 tkMessageBox.showerror("No stack trace",
1246 "There is no stack trace yet.\n"
1247 "(sys.last_traceback is not defined)",
1248 master=self.text)
1249 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001250 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001251 sv = StackBrowser(self.root, self.flist)
1252
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001253 def view_restart_mark(self, event=None):
1254 self.text.see("iomark")
1255 self.text.see("restart")
1256
1257 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001258 "Callback for Run/Restart Shell Cntl-F6"
1259 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001260
David Scherer7aced172000-08-15 01:13:23 +00001261 def showprompt(self):
1262 self.resetoutput()
1263 try:
1264 s = str(sys.ps1)
1265 except:
1266 s = ""
1267 self.console.write(s)
1268 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001269 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001270 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001271
1272 def resetoutput(self):
1273 source = self.text.get("iomark", "end-1c")
1274 if self.history:
Terry Jan Reedy0a01ac42013-08-13 19:51:04 -04001275 self.history.store(source)
David Scherer7aced172000-08-15 01:13:23 +00001276 if self.text.get("end-2c") != "\n":
1277 self.text.insert("end-1c", "\n")
1278 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001279 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001280
1281 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001282 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1283 # Tk doesn't support outputting non-BMP characters
1284 # Let's assume what printed string is not very long,
1285 # find first non-BMP character and construct informative
1286 # UnicodeEncodeError exception.
1287 for start, char in enumerate(s):
1288 if char > '\uffff':
1289 break
1290 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1291 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001292 try:
1293 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001294 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001295 self.text.mark_gravity("iomark", "left")
1296 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001297 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1298 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001299 if self.canceled:
1300 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001301 if not use_subprocess:
1302 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001303 return count
David Scherer7aced172000-08-15 01:13:23 +00001304
Andrew Svetlovd1837672012-11-01 22:41:19 +02001305 def rmenu_check_cut(self):
1306 try:
1307 if self.text.compare('sel.first', '<', 'iomark'):
1308 return 'disabled'
1309 except TclError: # no selection, so the index 'sel.first' doesn't exist
1310 return 'disabled'
1311 return super().rmenu_check_cut()
1312
1313 def rmenu_check_paste(self):
1314 if self.text.compare('insert','<','iomark'):
1315 return 'disabled'
1316 return super().rmenu_check_paste()
1317
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001318class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001319
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001320 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001321 self.shell = shell
1322 self.tags = tags
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001323 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001324
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001325 @property
1326 def encoding(self):
1327 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001328
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001329 @property
1330 def name(self):
1331 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001332
1333 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001334 return True
David Scherer7aced172000-08-15 01:13:23 +00001335
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001336
1337class PseudoOutputFile(PseudoFile):
1338
1339 def writable(self):
1340 return True
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001341
1342 def write(self, s):
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001343 if self.closed:
1344 raise ValueError("write to closed file")
Serhiy Storchaka9df8a1c2013-12-10 10:05:19 +02001345 if type(s) is not str:
1346 if not isinstance(s, str):
1347 raise TypeError('must be str, not ' + type(s).__name__)
1348 # See issue #19481
1349 s = str.__str__(s)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001350 return self.shell.write(s, self.tags)
1351
1352
1353class PseudoInputFile(PseudoFile):
1354
1355 def __init__(self, shell, tags, encoding=None):
1356 PseudoFile.__init__(self, shell, tags, encoding)
1357 self._line_buffer = ''
1358
1359 def readable(self):
1360 return True
1361
1362 def read(self, size=-1):
1363 if self.closed:
1364 raise ValueError("read from closed file")
1365 if size is None:
1366 size = -1
1367 elif not isinstance(size, int):
1368 raise TypeError('must be int, not ' + type(size).__name__)
1369 result = self._line_buffer
1370 self._line_buffer = ''
1371 if size < 0:
1372 while True:
1373 line = self.shell.readline()
1374 if not line: break
1375 result += line
1376 else:
1377 while len(result) < size:
1378 line = self.shell.readline()
1379 if not line: break
1380 result += line
1381 self._line_buffer = result[size:]
1382 result = result[:size]
1383 return result
1384
1385 def readline(self, size=-1):
1386 if self.closed:
1387 raise ValueError("read from closed file")
1388 if size is None:
1389 size = -1
1390 elif not isinstance(size, int):
1391 raise TypeError('must be int, not ' + type(size).__name__)
1392 line = self._line_buffer or self.shell.readline()
1393 if size < 0:
1394 size = len(line)
Serhiy Storchaka0fd55762013-12-25 14:24:35 +02001395 eol = line.find('\n', 0, size)
1396 if eol >= 0:
1397 size = eol + 1
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001398 self._line_buffer = line[size:]
1399 return line[:size]
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001400
Roger Serwy1eafd102013-04-11 19:16:44 -05001401 def close(self):
1402 self.shell.close()
1403
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001404
David Scherer7aced172000-08-15 01:13:23 +00001405usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001406
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001407USAGE: idle [-deins] [-t title] [file]*
1408 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1409 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001410
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001411 -h print this help message and exit
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001412 -n run IDLE without a subprocess (DEPRECATED,
1413 see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001414
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001415The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001416
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001417 -e open an edit window
1418 -i open a shell window
1419
1420The following options imply -i and will open a shell:
1421
1422 -c cmd run the command in a shell, or
1423 -r file run script from file
1424
1425 -d enable the debugger
1426 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1427 -t title set title of shell window
1428
1429A default edit window will be bypassed when -c, -r, or - are used.
1430
1431[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1432
1433Examples:
1434
1435idle
1436 Open an edit window or shell depending on IDLE's configuration.
1437
1438idle foo.py foobar.py
1439 Edit the files, also open a shell if configured to start with shell.
1440
1441idle -est "Baz" foo.py
1442 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1443 window with the title "Baz".
1444
Neal Norwitz752abd02008-05-13 04:55:24 +00001445idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001446 Open a shell window and run the command, passing "-c" in sys.argv[0]
1447 and "foo" in sys.argv[1].
1448
1449idle -d -s -r foo.py "Hello World"
1450 Open a shell window, run a startup script, enable the debugger, and
1451 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1452 sys.argv[1].
1453
Neal Norwitz752abd02008-05-13 04:55:24 +00001454echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001455 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1456 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001457"""
1458
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001459def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001460 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001461
Terry Jan Reedy95a3f112013-06-28 23:50:12 -04001462 capture_warnings(True)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001463 use_subprocess = True
Roger Serwyc35151c2013-03-31 23:28:55 -05001464 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001465 enable_edit = False
1466 debug = False
1467 cmd = None
1468 script = None
1469 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001470 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001471 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001472 except getopt.error as msg:
Terry Jan Reedy81b062f2014-09-19 22:38:41 -04001473 print("Error: %s\n%s" % (msg, usage_msg), file=sys.stderr)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001474 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001475 for o, a in opts:
1476 if o == '-c':
1477 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001478 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001479 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001480 debug = True
1481 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001482 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001483 enable_edit = True
1484 if o == '-h':
1485 sys.stdout.write(usage_msg)
1486 sys.exit()
1487 if o == '-i':
1488 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001489 if o == '-n':
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001490 print(" Warning: running IDLE without a subprocess is deprecated.",
1491 file=sys.stderr)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001492 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001493 if o == '-r':
1494 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001495 if os.path.isfile(script):
1496 pass
1497 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001498 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001499 sys.exit()
1500 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001501 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001502 startup = True
1503 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001504 if o == '-t':
1505 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001506 enable_shell = True
1507 if args and args[0] == '-':
1508 cmd = sys.stdin.read()
1509 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001510 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001511 for i in range(len(sys.path)):
1512 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001513 if args and args[0] == '-':
1514 sys.argv = [''] + args[1:]
1515 elif cmd:
1516 sys.argv = ['-c'] + args
1517 elif script:
1518 sys.argv = [script] + args
1519 elif args:
1520 enable_edit = True
1521 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001522 for filename in args:
1523 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001524 for dir in pathx:
1525 dir = os.path.abspath(dir)
1526 if not dir in sys.path:
1527 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001528 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001529 dir = os.getcwd()
1530 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001531 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001532 # check the IDLE settings configuration (but command line overrides)
1533 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001534 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001535 enable_edit = enable_edit or edit_start
Roger Serwyc35151c2013-03-31 23:28:55 -05001536 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001537 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001538 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001539
Terry Jan Reedya7c07d32014-02-08 09:02:26 -05001540 # set application icon
1541 icondir = os.path.join(os.path.dirname(__file__), 'Icons')
1542 if system() == 'Windows':
1543 iconfile = os.path.join(icondir, 'idle.ico')
1544 root.wm_iconbitmap(default=iconfile)
1545 elif TkVersion >= 8.5:
1546 ext = '.png' if TkVersion >= 8.6 else '.gif'
1547 iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
1548 for size in (16, 32, 48)]
1549 icons = [PhotoImage(file=iconfile) for iconfile in iconfiles]
1550 root.wm_iconphoto(True, *icons)
1551
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001552 fixwordbreaks(root)
1553 root.withdraw()
1554 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001555 macosxSupport.setupApp(root, flist)
1556
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001557 if enable_edit:
1558 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001559 for filename in args[:]:
1560 if flist.open(filename) is None:
1561 # filename is a directory actually, disconsider it
1562 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001563 if not args:
1564 flist.new()
Ned Deilyf3c65892013-12-10 16:24:01 -08001565
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001566 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001567 shell = flist.open_shell()
1568 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001569 return # couldn't open shell
Ned Deilyb7601672014-03-27 20:49:14 -07001570 if macosxSupport.isAquaTk() and flist.dict:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001571 # On OSX: when the user has double-clicked on a file that causes
1572 # IDLE to be launched the shell window will open just in front of
1573 # the file she wants to see. Lower the interpreter window when
1574 # there are open files.
1575 shell.top.lower()
Ned Deilyf3c65892013-12-10 16:24:01 -08001576 else:
1577 shell = flist.pyshell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001578
Ned Deilyf3c65892013-12-10 16:24:01 -08001579 # Handle remaining options. If any of these are set, enable_shell
1580 # was set also, so shell must be true to reach here.
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001581 if debug:
1582 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001583 if startup:
1584 filename = os.environ.get("IDLESTARTUP") or \
1585 os.environ.get("PYTHONSTARTUP")
1586 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001587 shell.interp.execfile(filename)
Ned Deilyf3c65892013-12-10 16:24:01 -08001588 if cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001589 shell.interp.runcommand("""if 1:
1590 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001591 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001592 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001593 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001594 if cmd:
1595 shell.interp.execsource(cmd)
1596 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001597 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001598 shell.interp.execfile(script)
Ned Deilyf3c65892013-12-10 16:24:01 -08001599 elif shell:
1600 # If there is a shell window and no cmd or script in progress,
1601 # check for problematic OS X Tk versions and print a warning
1602 # message in the IDLE shell window; this is less intrusive
1603 # than always opening a separate window.
1604 tkversionwarning = macosxSupport.tkVersionWarning(root)
1605 if tkversionwarning:
1606 shell.interp.runcommand("print('%s')" % tkversionwarning)
Ned Deily4ce92b22011-01-15 04:37:12 +00001607
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001608 while flist.inversedict: # keep IDLE running while files are open.
1609 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001610 root.destroy()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -04001611 capture_warnings(False)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001612
David Scherer7aced172000-08-15 01:13:23 +00001613if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001614 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001615 main()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -04001616
1617capture_warnings(False) # Make sure turned off; see issue 18081