blob: 561993ce205644a0ded911ff02375cb63a8d351e [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001#! /usr/bin/env python
2
David Scherer7aced172000-08-15 01:13:23 +00003import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00004import os.path
David Scherer7aced172000-08-15 01:13:23 +00005import sys
6import string
7import getopt
8import re
Chui Tey5d2af632002-05-26 13:36:41 +00009import socket
10import time
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000011import threading
Chui Tey5d2af632002-05-26 13:36:41 +000012import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000013import types
Martin v. Löwise2b56242012-07-25 10:56:22 +020014import io
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -040018from platform import python_version
David Scherer7aced172000-08-15 01:13:23 +000019
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000020try:
Georg Brandl6634bf22008-05-20 07:13:37 +000021 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022except ImportError:
Georg Brandl6634bf22008-05-20 07:13:37 +000023 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000024 "Your Python may not be configured for Tk. **"
25 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000026import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000027
Florent Xiclunad630c042010-04-02 07:24:52 +000028from idlelib.EditorWindow import EditorWindow, fixwordbreaks
29from idlelib.FileList import FileList
30from idlelib.ColorDelegator import ColorDelegator
31from idlelib.UndoDelegator import UndoDelegator
32from idlelib.OutputWindow import OutputWindow
33from idlelib.configHandler import idleConf
34from idlelib import idlever
35from idlelib import rpc
36from idlelib import Debugger
37from idlelib import RemoteDebugger
38from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000039
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000040IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +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. Kaisera00050f2003-05-08 20:26:55 +000044try:
45 from signal import SIGTERM
46except ImportError:
47 SIGTERM = 15
48
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000049# Override warnings module to write to warning_stream. Initialize to send IDLE
50# internal warnings to the console. ScriptBinding.check_syntax() will
51# temporarily redirect the stream to the shell window to display warnings when
52# checking user's code.
53global warning_stream
54warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000055try:
56 import warnings
57except ImportError:
58 pass
59else:
Benjamin Petersonb76444b2008-10-16 19:40:14 +000060 def idle_showwarning(message, category, filename, lineno,
61 file=None, line=None):
Guilherme Polof198ac22009-08-14 14:03:07 +000062 if file is None:
63 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000064 try:
Guilherme Polof198ac22009-08-14 14:03:07 +000065 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaran13502b12011-07-03 17:38:53 -070066 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000067 except IOError:
68 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000069 warnings.showwarning = idle_showwarning
Guilherme Polof198ac22009-08-14 14:03:07 +000070 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000071 """Format warnings the IDLE way"""
72 s = "\nWarning (from warnings module):\n"
73 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polof198ac22009-08-14 14:03:07 +000074 if line is None:
75 line = linecache.getline(filename, lineno)
76 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000077 if line:
78 s += " %s\n" % line
79 s += "%s: %s\n>>> " % (category.__name__, message)
80 return s
81 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000082
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000083def extended_linecache_checkcache(filename=None,
84 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000085 """Extend linecache.checkcache to preserve the <pyshell#...> entries
86
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000087 Rather than repeating the linecache code, patch it to save the
88 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polof198ac22009-08-14 14:03:07 +000089 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000090
91 orig_checkcache is bound at definition time to the original
92 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000093 """
David Scherer7aced172000-08-15 01:13:23 +000094 cache = linecache.cache
95 save = {}
Guilherme Polof198ac22009-08-14 14:03:07 +000096 for key in list(cache):
97 if key[:1] + key[-1:] == '<>':
98 save[key] = cache.pop(key)
99 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +0000100 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000101
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000102# Patch linecache.checkcache():
103linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000104
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000105
David Scherer7aced172000-08-15 01:13:23 +0000106class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000107 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000108
David Scherer7aced172000-08-15 01:13:23 +0000109 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000110 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000111 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000112 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000113 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000114 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
115
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000116 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
117 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000118 # whenever a file is changed, restore breakpoints
119 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000120 def filename_changed_hook(old_hook=self.io.filename_change_hook,
121 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000122 self.restore_file_breaks()
123 old_hook()
124 self.io.set_filename_change_hook(filename_changed_hook)
125
Andrew Svetlov5018db72012-11-01 22:39:14 +0200126 rmenu_specs = [
127 ("Cut", "<<cut>>", "rmenu_check_cut"),
128 ("Copy", "<<copy>>", "rmenu_check_copy"),
129 ("Paste", "<<paste>>", "rmenu_check_paste"),
130 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
131 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
132 ]
David Scherer7aced172000-08-15 01:13:23 +0000133
Chui Teya2adb0f2002-11-04 22:14:54 +0000134 def set_breakpoint(self, lineno):
135 text = self.text
136 filename = self.io.filename
137 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
138 try:
139 i = self.breakpoints.index(lineno)
140 except ValueError: # only add if missing, i.e. do once
141 self.breakpoints.append(lineno)
142 try: # update the subprocess debugger
143 debug = self.flist.pyshell.interp.debugger
144 debug.set_breakpoint_here(filename, lineno)
145 except: # but debugger may not be active right now....
146 pass
147
David Scherer7aced172000-08-15 01:13:23 +0000148 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000149 text = self.text
150 filename = self.io.filename
151 if not filename:
152 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000153 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000154 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000155 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000156
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000157 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000158 text = self.text
159 filename = self.io.filename
160 if not filename:
161 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000162 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000163 lineno = int(float(text.index("insert")))
164 try:
165 self.breakpoints.remove(lineno)
166 except:
167 pass
168 text.tag_remove("BREAK", "insert linestart",\
169 "insert lineend +1char")
170 try:
171 debug = self.flist.pyshell.interp.debugger
172 debug.clear_breakpoint_here(filename, lineno)
173 except:
174 pass
175
176 def clear_file_breaks(self):
177 if self.breakpoints:
178 text = self.text
179 filename = self.io.filename
180 if not filename:
181 text.bell()
182 return
183 self.breakpoints = []
184 text.tag_remove("BREAK", "1.0", END)
185 try:
186 debug = self.flist.pyshell.interp.debugger
187 debug.clear_file_breaks(filename)
188 except:
189 pass
190
Chui Teya2adb0f2002-11-04 22:14:54 +0000191 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000192 "Save breakpoints when file is saved"
193 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
194 # be run. The breaks are saved at that time. If we introduce
195 # a temporary file save feature the save breaks functionality
196 # needs to be re-verified, since the breaks at the time the
197 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000198 # permanent save of the file. Currently, a break introduced
199 # after a save will be effective, but not persistent.
200 # This is necessary to keep the saved breaks synched with the
201 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000202 #
203 # Breakpoints are set as tagged ranges in the text. Certain
204 # kinds of edits cause these ranges to be deleted: Inserting
205 # or deleting a line just before a breakpoint, and certain
206 # deletions prior to a breakpoint. These issues need to be
207 # investigated and understood. It's not clear if they are
208 # Tk issues or IDLE issues, or whether they can actually
209 # be fixed. Since a modified file has to be saved before it is
210 # run, and since self.breakpoints (from which the subprocess
211 # debugger is loaded) is updated during the save, the visible
212 # breaks stay synched with the subprocess even if one of these
213 # unexpected breakpoint deletions occurs.
214 breaks = self.breakpoints
215 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000216 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800217 with open(self.breakpointPath,"r") as old_file:
218 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000219 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000220 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800221 try:
222 with open(self.breakpointPath,"w") as new_file:
223 for line in lines:
224 if not line.startswith(filename + '='):
225 new_file.write(line)
226 self.update_breakpoints()
227 breaks = self.breakpoints
228 if breaks:
229 new_file.write(filename + '=' + str(breaks) + '\n')
230 except IOError as err:
231 if not getattr(self.root, "breakpoint_error_displayed", False):
232 self.root.breakpoint_error_displayed = True
233 tkMessageBox.showerror(title='IDLE Error',
234 message='Unable to update breakpoint list:\n%s'
235 % str(err),
236 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000237
238 def restore_file_breaks(self):
239 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000240 filename = self.io.filename
241 if filename is None:
242 return
Chui Tey69371d62002-11-04 23:39:45 +0000243 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000244 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000245 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000246 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000247 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000248 for breakpoint_linenumber in breakpoint_linenumbers:
249 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000250
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000251 def update_breakpoints(self):
252 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000253 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000254 ranges = text.tag_ranges("BREAK")
255 linenumber_list = self.ranges_to_linenumbers(ranges)
256 self.breakpoints = linenumber_list
257
258 def ranges_to_linenumbers(self, ranges):
259 lines = []
260 for index in range(0, len(ranges), 2):
Andrew Svetlov8a15c372012-07-31 19:51:27 +0300261 lineno = int(float(ranges[index].string))
262 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000263 while lineno < end:
264 lines.append(lineno)
265 lineno += 1
266 return lines
267
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000268# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000269# def saved_change_hook(self):
270# "Extend base method - clear breaks if module is modified"
271# if not self.get_saved():
272# self.clear_file_breaks()
273# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000274
275 def _close(self):
276 "Extend base method - clear breaks when module is closed"
277 self.clear_file_breaks()
278 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000279
David Scherer7aced172000-08-15 01:13:23 +0000280
281class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000282 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000283
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000284 # override FileList's class variable, instances return PyShellEditorWindow
285 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000286 EditorWindow = PyShellEditorWindow
287
288 pyshell = None
289
290 def open_shell(self, event=None):
291 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000292 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000293 else:
294 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000295 if self.pyshell:
296 if not self.pyshell.begin():
297 return None
David Scherer7aced172000-08-15 01:13:23 +0000298 return self.pyshell
299
300
301class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000302 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000303
Steven M. Gavab77d3432002-03-02 07:16:21 +0000304 def __init__(self):
305 ColorDelegator.__init__(self)
306 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000307
308 def recolorize_main(self):
309 self.tag_remove("TODO", "1.0", "iomark")
310 self.tag_add("SYNC", "1.0", "iomark")
311 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000312
Steven M. Gavab77d3432002-03-02 07:16:21 +0000313 def LoadTagDefs(self):
314 ColorDelegator.LoadTagDefs(self)
315 theme = idleConf.GetOption('main','Theme','name')
316 self.tagdefs.update({
317 "stdin": {'background':None,'foreground':None},
318 "stdout": idleConf.GetHighlight(theme, "stdout"),
319 "stderr": idleConf.GetHighlight(theme, "stderr"),
320 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000321 })
David Scherer7aced172000-08-15 01:13:23 +0000322
Ned Deily5e247b72012-05-31 09:17:29 -0700323 def removecolors(self):
324 # Don't remove shell color tags before "iomark"
325 for tag in self.tagdefs:
326 self.tag_remove(tag, "iomark", "end")
327
David Scherer7aced172000-08-15 01:13:23 +0000328class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000329 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000330
331 def insert(self, index, chars, tags=None):
332 try:
333 if self.delegate.compare(index, "<", "iomark"):
334 self.delegate.bell()
335 return
336 except TclError:
337 pass
338 UndoDelegator.insert(self, index, chars, tags)
339
340 def delete(self, index1, index2=None):
341 try:
342 if self.delegate.compare(index1, "<", "iomark"):
343 self.delegate.bell()
344 return
345 except TclError:
346 pass
347 UndoDelegator.delete(self, index1, index2)
348
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000349
350class MyRPCClient(rpc.RPCClient):
351
352 def handle_EOF(self):
353 "Override the base class - just re-raise EOFError"
354 raise EOFError
355
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000356
David Scherer7aced172000-08-15 01:13:23 +0000357class ModifiedInterpreter(InteractiveInterpreter):
358
359 def __init__(self, tkconsole):
360 self.tkconsole = tkconsole
361 locals = sys.modules['__main__'].__dict__
362 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000363 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000364 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000365 self.subprocess_arglist = None
366 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700367 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000368
Chui Tey5d2af632002-05-26 13:36:41 +0000369 rpcclt = None
370 rpcpid = None
371
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000372 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000373 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000374 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000375 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000376 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000377
Tony Lowndsf53dec22002-12-20 04:24:43 +0000378 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000379 assert (self.port!=0), (
380 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000381 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000382 if 1/2 > 0: # account for new division
383 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000384 # Maybe IDLE is installed and is being accessed via sys.path,
385 # or maybe it's not installed and the idle.py script is being
386 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000387 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
388 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000389 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000390 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000391 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000392 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000393 if sys.platform[:3] == 'win' and ' ' in sys.executable:
394 # handle embedded space in path by quoting the argument
395 decorated_exec = '"%s"' % sys.executable
396 else:
397 decorated_exec = sys.executable
398 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000399
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000400 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000401 addr = (HOST, self.port)
402 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000403 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000404 time.sleep(i)
405 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000406 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000407 break
408 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000409 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000410 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000411 self.display_port_binding_error()
412 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000413 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
414 self.port = self.rpcclt.listening_sock.getsockname()[1]
415 # if PORT was not 0, probably working with a remote execution server
416 if PORT != 0:
417 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
418 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
419 # on Windows since the implementation allows two active sockets on
420 # the same address!
421 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
422 socket.SO_REUSEADDR, 1)
423 self.spawn_subprocess()
424 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000425 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000426 self.rpcclt.listening_sock.settimeout(10)
427 try:
428 self.rpcclt.accept()
429 except socket.timeout, err:
430 self.display_no_subprocess_error()
431 return None
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200432 self.rpcclt.register("console", self.tkconsole)
433 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000434 self.rpcclt.register("stdout", self.tkconsole.stdout)
435 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000436 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000437 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000438 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500439 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000440 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000441 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000442
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500443 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000444 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000445 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000446 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000447 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000448 debug = self.getdebugger()
449 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000450 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000451 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000452 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
453 except:
454 pass
455 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000456 self.rpcclt.close()
457 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000458 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000459 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000460 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000461 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000462 try:
463 self.rpcclt.accept()
464 except socket.timeout, err:
465 self.display_no_subprocess_error()
466 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500467 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000468 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000469 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000470 if was_executing:
471 console.write('\n')
472 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000473 halfbar = ((int(console.width) - 16) // 2) * '='
474 console.write(halfbar + ' RESTART ' + halfbar)
475 console.text.mark_set("restart", "end-1c")
476 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000477 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000478 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000479 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000480 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000481 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000482 # reload remote debugger breakpoints for all PyShellEditWindows
483 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700484 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000485 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000486 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000487
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000488 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000489 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000490
491 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000492 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000493
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000494 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000495 try:
496 self.rpcclt.close()
497 except AttributeError: # no socket
498 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000499 self.unix_terminate()
500 self.tkconsole.executing = False
501 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000502
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000503 def unix_terminate(self):
504 "UNIX: make sure subprocess is terminated and collect status"
505 if hasattr(os, 'kill'):
506 try:
507 os.kill(self.rpcpid, SIGTERM)
508 except OSError:
509 # process already terminated:
510 return
511 else:
512 try:
513 os.waitpid(self.rpcpid, 0)
514 except OSError:
515 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000516
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500517 def transfer_path(self, with_cwd=False):
518 if with_cwd: # Issue 13506
519 path = [''] # include Current Working Directory
520 path.extend(sys.path)
521 else:
522 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500523
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000524 self.runcommand("""if 1:
525 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000526 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000527 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500528 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000529
Chui Tey5d2af632002-05-26 13:36:41 +0000530 active_seq = None
531
532 def poll_subprocess(self):
533 clt = self.rpcclt
534 if clt is None:
535 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000536 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000537 response = clt.pollresponse(self.active_seq, wait=0.05)
538 except (EOFError, IOError, KeyboardInterrupt):
539 # lost connection or subprocess terminated itself, restart
540 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000541 if self.tkconsole.closing:
542 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000543 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000544 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000545 if response:
546 self.tkconsole.resetoutput()
547 self.active_seq = None
548 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000549 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000550 if how == "OK":
551 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000552 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000553 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000554 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
555 self.remote_stack_viewer()
556 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000557 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
558 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000559 print >>console, errmsg, what
560 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000561 try:
562 self.tkconsole.endexecuting()
563 except AttributeError: # shell may have closed
564 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000565 # Reschedule myself
566 if not self.tkconsole.closing:
567 self.tkconsole.text.after(self.tkconsole.pollinterval,
568 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000569
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000570 debugger = None
571
572 def setdebugger(self, debugger):
573 self.debugger = debugger
574
575 def getdebugger(self):
576 return self.debugger
577
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000578 def open_remote_stack_viewer(self):
579 """Initiate the remote stack viewer from a separate thread.
580
581 This method is called from the subprocess, and by returning from this
582 method we allow the subprocess to unblock. After a bit the shell
583 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000584 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000585 the RPC mechanism.
586
587 """
588 self.tkconsole.text.after(300, self.remote_stack_viewer)
589 return
590
Chui Tey5d2af632002-05-26 13:36:41 +0000591 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000592 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000593 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000594 if oid is None:
595 self.tkconsole.root.bell()
596 return
597 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000598 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000599 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000600 theme = idleConf.GetOption('main','Theme','name')
601 background = idleConf.GetHighlight(theme, 'normal')['background']
602 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000603 sc.frame.pack(expand=1, fill="both")
604 node = TreeNode(sc.canvas, None, item)
605 node.expand()
606 # XXX Should GC the remote tree when closing the window
607
David Scherer7aced172000-08-15 01:13:23 +0000608 gid = 0
609
610 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000611 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000612 filename = self.stuffsource(source)
613 self.execfile(filename, source)
614
615 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000616 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000617 if source is None:
618 source = open(filename, "r").read()
619 try:
620 code = compile(source, filename, "exec")
621 except (OverflowError, SyntaxError):
622 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000623 tkerr = self.tkconsole.stderr
624 print>>tkerr, '*** Error in script or command!\n'
625 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000626 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000627 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000628 else:
629 self.runcode(code)
630
631 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000632 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000633 filename = self.stuffsource(source)
634 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000635 self.save_warnings_filters = warnings.filters[:]
636 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000637 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000638 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000639 try:
640 source = source.encode(IOBinding.encoding)
641 except UnicodeError:
642 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000643 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000644 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000645 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000646 # InteractiveInterpreter.runsource() calls its runcode() method,
647 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000648 return InteractiveInterpreter.runsource(self, source, filename)
649 finally:
650 if self.save_warnings_filters is not None:
651 warnings.filters[:] = self.save_warnings_filters
652 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000653
654 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000655 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000656 filename = "<pyshell#%d>" % self.gid
657 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000658 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000659 linecache.cache[filename] = len(source)+1, 0, lines, filename
660 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000661
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000662 def prepend_syspath(self, filename):
663 "Prepend sys.path with file's directory if not already included"
664 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000665 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000666 import sys as _sys
667 from os.path import dirname as _dirname
668 _dir = _dirname(_filename)
669 if not _dir in _sys.path:
670 _sys.path.insert(0, _dir)
671 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000672 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000673
David Scherer7aced172000-08-15 01:13:23 +0000674 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000675 """Extend base class method: Add Colorizing
676
677 Color the offending position instead of printing it and pointing at it
678 with a caret.
679
680 """
David Scherer7aced172000-08-15 01:13:23 +0000681 text = self.tkconsole.text
682 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000683 if stuff:
684 msg, lineno, offset, line = stuff
685 if lineno == 1:
686 pos = "iomark + %d chars" % (offset-1)
687 else:
688 pos = "iomark linestart + %d lines + %d chars" % \
689 (lineno-1, offset-1)
690 text.tag_add("ERROR", pos)
691 text.see(pos)
692 char = text.get(pos)
693 if char and char in IDENTCHARS:
694 text.tag_add("ERROR", pos + " wordstart", pos)
695 self.tkconsole.resetoutput()
696 self.write("SyntaxError: %s\n" % str(msg))
697 else:
David Scherer7aced172000-08-15 01:13:23 +0000698 self.tkconsole.resetoutput()
699 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000700 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000701
702 def unpackerror(self):
703 type, value, tb = sys.exc_info()
704 ok = type is SyntaxError
705 if ok:
706 try:
707 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000708 if not offset:
709 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000710 except:
711 ok = 0
712 if ok:
713 return msg, lineno, offset, line
714 else:
715 return None
716
717 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000718 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000719 self.tkconsole.resetoutput()
720 self.checklinecache()
721 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000722 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
723 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000724
725 def checklinecache(self):
726 c = linecache.cache
727 for key in c.keys():
728 if key[:1] + key[-1:] != "<>":
729 del c[key]
730
Chui Tey5d2af632002-05-26 13:36:41 +0000731 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000732 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000733 # The code better not raise an exception!
734 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000735 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000736 return 0
737 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000738 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000739 else:
740 exec code in self.locals
741 return 1
742
David Scherer7aced172000-08-15 01:13:23 +0000743 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000744 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000745 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000746 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000747 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000748 if self.save_warnings_filters is not None:
749 warnings.filters[:] = self.save_warnings_filters
750 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000751 debugger = self.debugger
752 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000753 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000754 if not debugger and self.rpcclt is not None:
755 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
756 (code,), {})
757 elif debugger:
758 debugger.run(code, self.locals)
759 else:
760 exec code in self.locals
761 except SystemExit:
762 if not self.tkconsole.closing:
763 if tkMessageBox.askyesno(
764 "Exit?",
765 "Do you want to exit altogether?",
766 default="yes",
767 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000768 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000769 else:
770 self.showtraceback()
771 else:
772 raise
773 except:
774 if use_subprocess:
775 print >>self.tkconsole.stderr, \
776 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000777 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000778 self.tkconsole.endexecuting()
779 else:
780 if self.tkconsole.canceled:
781 self.tkconsole.canceled = False
782 print >>self.tkconsole.stderr, "KeyboardInterrupt"
783 else:
784 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000785 finally:
786 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000787 try:
788 self.tkconsole.endexecuting()
789 except AttributeError: # shell may have closed
790 pass
David Scherer7aced172000-08-15 01:13:23 +0000791
792 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000793 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000794 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000795
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000796 def display_port_binding_error(self):
797 tkMessageBox.showerror(
798 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000799 "IDLE can't bind to a TCP/IP port, which is necessary to "
800 "communicate with its Python execution server. This might be "
801 "because no networking is installed on this computer. "
802 "Run IDLE with the -n command line switch to start without a "
803 "subprocess and refer to Help/IDLE Help 'Running without a "
804 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000805 master=self.tkconsole.text)
806
807 def display_no_subprocess_error(self):
808 tkMessageBox.showerror(
809 "Subprocess Startup Error",
810 "IDLE's subprocess didn't make connection. Either IDLE can't "
811 "start a subprocess or personal firewall software is blocking "
812 "the connection.",
813 master=self.tkconsole.text)
814
815 def display_executing_dialog(self):
816 tkMessageBox.showerror(
817 "Already executing",
818 "The Python Shell window is already executing a command; "
819 "please wait until it is finished.",
820 master=self.tkconsole.text)
821
822
David Scherer7aced172000-08-15 01:13:23 +0000823class PyShell(OutputWindow):
824
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -0400825 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000826
827 # Override classes
828 ColorDelegator = ModifiedColorDelegator
829 UndoDelegator = ModifiedUndoDelegator
830
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000831 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000832 menu_specs = [
833 ("file", "_File"),
834 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000835 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000836 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000837 ("windows", "_Windows"),
838 ("help", "_Help"),
839 ]
David Scherer7aced172000-08-15 01:13:23 +0000840
Ronald Oussoren19302d92006-06-11 14:33:36 +0000841 if macosxSupport.runningAsOSXApp():
842 del menu_specs[-3]
843 menu_specs[-2] = ("windows", "_Window")
844
845
David Scherer7aced172000-08-15 01:13:23 +0000846 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000847 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000848
849 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000850 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000851 ms = self.menu_specs
852 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000853 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000854 self.interp = ModifiedInterpreter(self)
855 if flist is None:
856 root = Tk()
857 fixwordbreaks(root)
858 root.withdraw()
859 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000860 #
David Scherer7aced172000-08-15 01:13:23 +0000861 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000862 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000863## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
864 self.usetabs = True
865 # indentwidth must be 8 when using tabs. See note in EditorWindow:
866 self.indentwidth = 8
867 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000868 #
David Scherer7aced172000-08-15 01:13:23 +0000869 text = self.text
870 text.configure(wrap="char")
871 text.bind("<<newline-and-indent>>", self.enter_callback)
872 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
873 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000874 text.bind("<<end-of-file>>", self.eof_callback)
875 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000876 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000877 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000878 if use_subprocess:
879 text.bind("<<view-restart>>", self.view_restart_mark)
880 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000881 #
David Scherer7aced172000-08-15 01:13:23 +0000882 self.save_stdout = sys.stdout
883 self.save_stderr = sys.stderr
884 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000885 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200886 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
887 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
888 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
889 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000890 if not use_subprocess:
891 sys.stdout = self.stdout
892 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200893 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000894 #
David Scherer7aced172000-08-15 01:13:23 +0000895 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000896 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000897 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000898
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000899 def get_standard_extension_names(self):
900 return idleConf.GetExtensions(shell_only=True)
901
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000902 reading = False
903 executing = False
904 canceled = False
905 endoffile = False
906 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000907
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000908 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000909 global warning_stream
910 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000911
912 def get_warning_stream(self):
913 return warning_stream
914
David Scherer7aced172000-08-15 01:13:23 +0000915 def toggle_debugger(self, event=None):
916 if self.executing:
917 tkMessageBox.showerror("Don't debug now",
918 "You can only toggle the debugger when idle",
919 master=self.text)
920 self.set_debugger_indicator()
921 return "break"
922 else:
923 db = self.interp.getdebugger()
924 if db:
925 self.close_debugger()
926 else:
927 self.open_debugger()
928
929 def set_debugger_indicator(self):
930 db = self.interp.getdebugger()
931 self.setvar("<<toggle-debugger>>", not not db)
932
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000933 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000934 pass # All we need is the variable
935
936 def close_debugger(self):
937 db = self.interp.getdebugger()
938 if db:
939 self.interp.setdebugger(None)
940 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000941 if self.interp.rpcclt:
942 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000943 self.resetoutput()
944 self.console.write("[DEBUG OFF]\n")
945 sys.ps1 = ">>> "
946 self.showprompt()
947 self.set_debugger_indicator()
948
949 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000950 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000951 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
952 self)
953 else:
954 dbg_gui = Debugger.Debugger(self)
955 self.interp.setdebugger(dbg_gui)
956 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000957 sys.ps1 = "[DEBUG ON]\n>>> "
958 self.showprompt()
959 self.set_debugger_indicator()
960
David Scherer7aced172000-08-15 01:13:23 +0000961 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000962 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000963 self.resetoutput()
964 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000965
966 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000967 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000968 self.executing = 0
969 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000970 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000971
972 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000973 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000974 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000975 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000976 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000977 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000978 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000979 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000980 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000981 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000982 if self.reading:
983 self.top.quit()
984 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000985 self.closing = True
986 # Wait for poll_subprocess() rescheduling to stop
987 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000988
989 def close2(self):
990 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000991
992 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000993 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000994 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000995 if use_subprocess:
996 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000997 # Restore std streams
998 sys.stdout = self.save_stdout
999 sys.stderr = self.save_stderr
1000 sys.stdin = self.save_stdin
1001 # Break cycles
1002 self.interp = None
1003 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001004 self.flist.pyshell = None
1005 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001006 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001007
1008 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001009 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001010 return True
David Scherer7aced172000-08-15 01:13:23 +00001011
1012 def short_title(self):
1013 return self.shell_title
1014
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001015 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001016 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001017
David Scherer7aced172000-08-15 01:13:23 +00001018 def begin(self):
1019 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001020 if use_subprocess:
1021 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001022 client = self.interp.start_subprocess()
1023 if not client:
1024 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001025 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001026 else:
1027 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001028 self.write("Python %s on %s\n%s\n%s" %
1029 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001030 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001031 import Tkinter
1032 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001033 return True
David Scherer7aced172000-08-15 01:13:23 +00001034
1035 def readline(self):
1036 save = self.reading
1037 try:
1038 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001039 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001040 finally:
1041 self.reading = save
1042 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001043 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1044 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001045 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001046 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001047 try:
1048 line = line.encode(IOBinding.encoding)
1049 except UnicodeError:
1050 pass
David Scherer7aced172000-08-15 01:13:23 +00001051 self.resetoutput()
1052 if self.canceled:
1053 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001054 if not use_subprocess:
1055 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001056 if self.endoffile:
1057 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001058 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001059 return line
1060
1061 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001062 return True
David Scherer7aced172000-08-15 01:13:23 +00001063
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001064 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001065 try:
1066 if self.text.compare("sel.first", "!=", "sel.last"):
1067 return # Active selection -- always use default binding
1068 except:
1069 pass
1070 if not (self.executing or self.reading):
1071 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001072 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001073 self.showprompt()
1074 return "break"
1075 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001076 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001077 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001078 if self.interp.getdebugger():
1079 self.interp.restart_subprocess()
1080 else:
1081 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001082 if self.reading:
1083 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001084 return "break"
1085
1086 def eof_callback(self, event):
1087 if self.executing and not self.reading:
1088 return # Let the default binding (delete next char) take over
1089 if not (self.text.compare("iomark", "==", "insert") and
1090 self.text.compare("insert", "==", "end-1c")):
1091 return # Let the default binding (delete next char) take over
1092 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001093 self.resetoutput()
1094 self.close()
1095 else:
1096 self.canceled = 0
1097 self.endoffile = 1
1098 self.top.quit()
1099 return "break"
1100
David Scherer7aced172000-08-15 01:13:23 +00001101 def linefeed_callback(self, event):
1102 # Insert a linefeed without entering anything (still autoindented)
1103 if self.reading:
1104 self.text.insert("insert", "\n")
1105 self.text.see("insert")
1106 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001107 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001108 return "break"
1109
1110 def enter_callback(self, event):
1111 if self.executing and not self.reading:
1112 return # Let the default binding (insert '\n') take over
1113 # If some text is selected, recall the selection
1114 # (but only if this before the I/O mark)
1115 try:
1116 sel = self.text.get("sel.first", "sel.last")
1117 if sel:
1118 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001119 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001120 return "break"
1121 except:
1122 pass
1123 # If we're strictly before the line containing iomark, recall
1124 # the current line, less a leading prompt, less leading or
1125 # trailing whitespace
1126 if self.text.compare("insert", "<", "iomark linestart"):
1127 # Check if there's a relevant stdin range -- if so, use it
1128 prev = self.text.tag_prevrange("stdin", "insert")
1129 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001130 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001131 return "break"
1132 next = self.text.tag_nextrange("stdin", "insert")
1133 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001134 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001135 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001136 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001137 indices = self.text.tag_nextrange("console", "insert linestart")
1138 if indices and \
1139 self.text.compare(indices[0], "<=", "insert linestart"):
1140 self.recall(self.text.get(indices[1], "insert lineend"), event)
1141 else:
1142 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001143 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001144 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001145 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001146 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001147 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001148 # If we're in the current input and there's only whitespace
1149 # beyond the cursor, erase that whitespace first
1150 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001151 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001152 self.text.delete("insert", "end-1c")
1153 # If we're in the current input before its last line,
1154 # insert a newline right at the insert point
1155 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001156 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001157 return "break"
1158 # We're in the last line; append a newline and submit it
1159 self.text.mark_set("insert", "end-1c")
1160 if self.reading:
1161 self.text.insert("insert", "\n")
1162 self.text.see("insert")
1163 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001164 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001165 self.text.tag_add("stdin", "iomark", "end-1c")
1166 self.text.update_idletasks()
1167 if self.reading:
1168 self.top.quit() # Break out of recursive mainloop() in raw_input()
1169 else:
1170 self.runit()
1171 return "break"
1172
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001173 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001174 # remove leading and trailing empty or whitespace lines
1175 s = re.sub(r'^\s*\n', '' , s)
1176 s = re.sub(r'\n\s*$', '', s)
1177 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001178 self.text.undo_block_start()
1179 try:
1180 self.text.tag_remove("sel", "1.0", "end")
1181 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001182 prefix = self.text.get("insert linestart", "insert")
1183 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001184 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001185 prefix = self.text.get("insert linestart", "insert")
1186 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001187 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001188 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1189 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001190 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001191 if line.startswith(orig_base_indent):
1192 # replace orig base indentation with new indentation
1193 line = new_base_indent + line[len(orig_base_indent):]
1194 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001195 finally:
1196 self.text.see("insert")
1197 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001198
1199 def runit(self):
1200 line = self.text.get("iomark", "end-1c")
1201 # Strip off last newline and surrounding whitespace.
1202 # (To allow you to hit return twice to end a statement.)
1203 i = len(line)
1204 while i > 0 and line[i-1] in " \t":
1205 i = i-1
1206 if i > 0 and line[i-1] == "\n":
1207 i = i-1
1208 while i > 0 and line[i-1] in " \t":
1209 i = i-1
1210 line = line[:i]
1211 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001212
David Scherer7aced172000-08-15 01:13:23 +00001213 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001214 if self.interp.rpcclt:
1215 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001216 try:
1217 sys.last_traceback
1218 except:
1219 tkMessageBox.showerror("No stack trace",
1220 "There is no stack trace yet.\n"
1221 "(sys.last_traceback is not defined)",
1222 master=self.text)
1223 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001224 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001225 sv = StackBrowser(self.root, self.flist)
1226
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001227 def view_restart_mark(self, event=None):
1228 self.text.see("iomark")
1229 self.text.see("restart")
1230
1231 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001232 "Callback for Run/Restart Shell Cntl-F6"
1233 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001234
David Scherer7aced172000-08-15 01:13:23 +00001235 def showprompt(self):
1236 self.resetoutput()
1237 try:
1238 s = str(sys.ps1)
1239 except:
1240 s = ""
1241 self.console.write(s)
1242 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001243 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001244 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001245
1246 def resetoutput(self):
1247 source = self.text.get("iomark", "end-1c")
1248 if self.history:
1249 self.history.history_store(source)
1250 if self.text.get("end-2c") != "\n":
1251 self.text.insert("end-1c", "\n")
1252 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001253 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001254 sys.stdout.softspace = 0
1255
1256 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001257 try:
1258 self.text.mark_gravity("iomark", "right")
1259 OutputWindow.write(self, s, tags, "iomark")
1260 self.text.mark_gravity("iomark", "left")
1261 except:
1262 pass
David Scherer7aced172000-08-15 01:13:23 +00001263 if self.canceled:
1264 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001265 if not use_subprocess:
1266 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001267
Andrew Svetlov5018db72012-11-01 22:39:14 +02001268 def rmenu_check_cut(self):
1269 try:
1270 if self.text.compare('sel.first', '<', 'iomark'):
1271 return 'disabled'
1272 except TclError: # no selection, so the index 'sel.first' doesn't exist
1273 return 'disabled'
1274 return super(PyShell, self).rmenu_check_cut()
1275
1276 def rmenu_check_paste(self):
1277 if self.text.compare('insert', '<', 'iomark'):
1278 return 'disabled'
1279 return super(PyShell, self).rmenu_check_paste()
1280
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001281class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001282
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001283 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001284 self.shell = shell
1285 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001286 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001287 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001288
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001289 @property
1290 def encoding(self):
1291 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001292
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001293 @property
1294 def name(self):
1295 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001296
1297 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001298 return True
David Scherer7aced172000-08-15 01:13:23 +00001299
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001300
1301class PseudoOutputFile(PseudoFile):
1302
1303 def writable(self):
1304 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001305
1306 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001307 if self.closed:
1308 raise ValueError("write to closed file")
1309 if not isinstance(s, (basestring, bytearray)):
1310 raise TypeError('must be string, not ' + type(s).__name__)
1311 return self.shell.write(s, self.tags)
1312
1313
1314class PseudoInputFile(PseudoFile):
1315
1316 def __init__(self, shell, tags, encoding=None):
1317 PseudoFile.__init__(self, shell, tags, encoding)
1318 self._line_buffer = ''
1319
1320 def readable(self):
1321 return True
1322
1323 def read(self, size=-1):
1324 if self.closed:
1325 raise ValueError("read from closed file")
1326 if size is None:
1327 size = -1
1328 elif not isinstance(size, int):
1329 raise TypeError('must be int, not ' + type(size).__name__)
1330 result = self._line_buffer
1331 self._line_buffer = ''
1332 if size < 0:
1333 while True:
1334 line = self.shell.readline()
1335 if not line: break
1336 result += line
1337 else:
1338 while len(result) < size:
1339 line = self.shell.readline()
1340 if not line: break
1341 result += line
1342 self._line_buffer = result[size:]
1343 result = result[:size]
1344 return result
1345
1346 def readline(self, size=-1):
1347 if self.closed:
1348 raise ValueError("read from closed file")
1349 if size is None:
1350 size = -1
1351 elif not isinstance(size, int):
1352 raise TypeError('must be int, not ' + type(size).__name__)
1353 line = self._line_buffer or self.shell.readline()
1354 if size < 0:
1355 size = len(line)
1356 self._line_buffer = line[size:]
1357 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001358
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001359
David Scherer7aced172000-08-15 01:13:23 +00001360usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001361
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001362USAGE: idle [-deins] [-t title] [file]*
1363 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1364 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001365
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001366 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001367 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001368
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001369The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001370
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001371 -e open an edit window
1372 -i open a shell window
1373
1374The following options imply -i and will open a shell:
1375
1376 -c cmd run the command in a shell, or
1377 -r file run script from file
1378
1379 -d enable the debugger
1380 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1381 -t title set title of shell window
1382
1383A default edit window will be bypassed when -c, -r, or - are used.
1384
1385[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1386
1387Examples:
1388
1389idle
1390 Open an edit window or shell depending on IDLE's configuration.
1391
1392idle foo.py foobar.py
1393 Edit the files, also open a shell if configured to start with shell.
1394
1395idle -est "Baz" foo.py
1396 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1397 window with the title "Baz".
1398
1399idle -c "import sys; print sys.argv" "foo"
1400 Open a shell window and run the command, passing "-c" in sys.argv[0]
1401 and "foo" in sys.argv[1].
1402
1403idle -d -s -r foo.py "Hello World"
1404 Open a shell window, run a startup script, enable the debugger, and
1405 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1406 sys.argv[1].
1407
1408echo "import sys; print sys.argv" | idle - "foobar"
1409 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1410 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001411"""
1412
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001413def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001414 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001415
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001416 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001417 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001418 enable_edit = False
1419 debug = False
1420 cmd = None
1421 script = None
1422 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001423 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001424 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001425 except getopt.error, msg:
1426 sys.stderr.write("Error: %s\n" % str(msg))
1427 sys.stderr.write(usage_msg)
1428 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001429 for o, a in opts:
1430 if o == '-c':
1431 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001432 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001433 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001434 debug = True
1435 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001436 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001437 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001438 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001439 if o == '-h':
1440 sys.stdout.write(usage_msg)
1441 sys.exit()
1442 if o == '-i':
1443 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001444 if o == '-n':
1445 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001446 if o == '-r':
1447 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001448 if os.path.isfile(script):
1449 pass
1450 else:
1451 print "No script file: ", script
1452 sys.exit()
1453 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001454 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001455 startup = True
1456 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001457 if o == '-t':
1458 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001459 enable_shell = True
1460 if args and args[0] == '-':
1461 cmd = sys.stdin.read()
1462 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001463 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001464 for i in range(len(sys.path)):
1465 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001466 if args and args[0] == '-':
1467 sys.argv = [''] + args[1:]
1468 elif cmd:
1469 sys.argv = ['-c'] + args
1470 elif script:
1471 sys.argv = [script] + args
1472 elif args:
1473 enable_edit = True
1474 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001475 for filename in args:
1476 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001477 for dir in pathx:
1478 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001479 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001480 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001481 else:
1482 dir = os.getcwd()
1483 if not dir in sys.path:
1484 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001485 # check the IDLE settings configuration (but command line overrides)
1486 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001487 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001488 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001489 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001490 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001491
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001492 fixwordbreaks(root)
1493 root.withdraw()
1494 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001495 macosxSupport.setupApp(root, flist)
1496
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001497 if enable_edit:
1498 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001499 for filename in args[:]:
1500 if flist.open(filename) is None:
1501 # filename is a directory actually, disconsider it
1502 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001503 if not args:
1504 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001505 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001506 shell = flist.open_shell()
1507 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001508 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001509
1510 if macosxSupport.runningAsOSXApp() and flist.dict:
1511 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001512 # IDLE to be launched the shell window will open just in front of
1513 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001514 # there are open files.
1515 shell.top.lower()
1516
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001517 shell = flist.pyshell
1518 # handle remaining options:
1519 if debug:
1520 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001521 if startup:
1522 filename = os.environ.get("IDLESTARTUP") or \
1523 os.environ.get("PYTHONSTARTUP")
1524 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001525 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001526 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001527 shell.interp.runcommand("""if 1:
1528 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001529 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001530 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001531 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001532 if cmd:
1533 shell.interp.execsource(cmd)
1534 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001535 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001536 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001537
Ned Deily2a6f4b32011-01-30 00:18:47 +00001538 # Check for problematic OS X Tk versions and print a warning message
1539 # in the IDLE shell window; this is less intrusive than always opening
1540 # a separate window.
1541 tkversionwarning = macosxSupport.tkVersionWarning(root)
1542 if tkversionwarning:
1543 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1544
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001545 while flist.inversedict: # keep IDLE running while files are open.
1546 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001547 root.destroy()
1548
David Scherer7aced172000-08-15 01:13:23 +00001549if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001550 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001551 main()