blob: 388c384a115577ea3533281070549ec8359a3438 [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
Kurt B. Kaiser0930c432002-12-06 21:45:24 +000014import exceptions
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
18
19from Tkinter import *
20import tkMessageBox
21
22from EditorWindow import EditorWindow, fixwordbreaks
23from FileList import FileList
24from ColorDelegator import ColorDelegator
25from UndoDelegator import UndoDelegator
Kurt B. Kaiser969de452002-06-12 03:28:57 +000026from OutputWindow import OutputWindow
Steven M. Gava99300612001-11-04 07:03:08 +000027from configHandler import idleConf
David Scherer7aced172000-08-15 01:13:23 +000028import idlever
29
Chui Tey5d2af632002-05-26 13:36:41 +000030import rpc
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +000031import Debugger
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +000032import RemoteDebugger
Chui Tey5d2af632002-05-26 13:36:41 +000033
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000034IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000035LOCALHOST = '127.0.0.1'
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000036
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000037try:
38 from signal import SIGTERM
39except ImportError:
40 SIGTERM = 15
41
Chui Tey5d2af632002-05-26 13:36:41 +000042# Change warnings module to write to sys.__stderr__
43try:
44 import warnings
45except ImportError:
46 pass
47else:
48 def idle_showwarning(message, category, filename, lineno):
49 file = sys.__stderr__
50 file.write(warnings.formatwarning(message, category, filename, lineno))
51 warnings.showwarning = idle_showwarning
52
Kurt B. Kaiser81885592002-11-29 22:10:53 +000053def extended_linecache_checkcache(orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000054 """Extend linecache.checkcache to preserve the <pyshell#...> entries
55
Kurt B. Kaiser81885592002-11-29 22:10:53 +000056 Rather than repeating the linecache code, patch it to save the pyshell#
57 entries, call the original linecache.checkcache(), and then restore the
58 saved entries. Assigning the orig_checkcache keyword arg freezes its value
59 at definition time to the (original) method linecache.checkcache(), i.e.
60 makes orig_checkcache lexical.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000061
62 """
David Scherer7aced172000-08-15 01:13:23 +000063 cache = linecache.cache
64 save = {}
65 for filename in cache.keys():
66 if filename[:1] + filename[-1:] == '<>':
67 save[filename] = cache[filename]
68 orig_checkcache()
69 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000070
Kurt B. Kaiser81885592002-11-29 22:10:53 +000071# Patch linecache.checkcache():
72linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000073
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000074
David Scherer7aced172000-08-15 01:13:23 +000075class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +000076 "Regular text edit window when a shell is present"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000077
David Scherer7aced172000-08-15 01:13:23 +000078 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000079 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +000080 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +000081 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000082 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +000083 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
84
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +000085 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
86 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +000087 # whenever a file is changed, restore breakpoints
88 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +000089 def filename_changed_hook(old_hook=self.io.filename_change_hook,
90 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +000091 self.restore_file_breaks()
92 old_hook()
93 self.io.set_filename_change_hook(filename_changed_hook)
94
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000095 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
96 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +000097
Chui Teya2adb0f2002-11-04 22:14:54 +000098 def set_breakpoint(self, lineno):
99 text = self.text
100 filename = self.io.filename
101 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
102 try:
103 i = self.breakpoints.index(lineno)
104 except ValueError: # only add if missing, i.e. do once
105 self.breakpoints.append(lineno)
106 try: # update the subprocess debugger
107 debug = self.flist.pyshell.interp.debugger
108 debug.set_breakpoint_here(filename, lineno)
109 except: # but debugger may not be active right now....
110 pass
111
David Scherer7aced172000-08-15 01:13:23 +0000112 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000113 text = self.text
114 filename = self.io.filename
115 if not filename:
116 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000117 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000118 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000119 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000120
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000121 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000122 text = self.text
123 filename = self.io.filename
124 if not filename:
125 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000126 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000127 lineno = int(float(text.index("insert")))
128 try:
129 self.breakpoints.remove(lineno)
130 except:
131 pass
132 text.tag_remove("BREAK", "insert linestart",\
133 "insert lineend +1char")
134 try:
135 debug = self.flist.pyshell.interp.debugger
136 debug.clear_breakpoint_here(filename, lineno)
137 except:
138 pass
139
140 def clear_file_breaks(self):
141 if self.breakpoints:
142 text = self.text
143 filename = self.io.filename
144 if not filename:
145 text.bell()
146 return
147 self.breakpoints = []
148 text.tag_remove("BREAK", "1.0", END)
149 try:
150 debug = self.flist.pyshell.interp.debugger
151 debug.clear_file_breaks(filename)
152 except:
153 pass
154
Chui Teya2adb0f2002-11-04 22:14:54 +0000155 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000156 "Save breakpoints when file is saved"
157 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
158 # be run. The breaks are saved at that time. If we introduce
159 # a temporary file save feature the save breaks functionality
160 # needs to be re-verified, since the breaks at the time the
161 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000162 # permanent save of the file. Currently, a break introduced
163 # after a save will be effective, but not persistent.
164 # This is necessary to keep the saved breaks synched with the
165 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000166 #
167 # Breakpoints are set as tagged ranges in the text. Certain
168 # kinds of edits cause these ranges to be deleted: Inserting
169 # or deleting a line just before a breakpoint, and certain
170 # deletions prior to a breakpoint. These issues need to be
171 # investigated and understood. It's not clear if they are
172 # Tk issues or IDLE issues, or whether they can actually
173 # be fixed. Since a modified file has to be saved before it is
174 # run, and since self.breakpoints (from which the subprocess
175 # debugger is loaded) is updated during the save, the visible
176 # breaks stay synched with the subprocess even if one of these
177 # unexpected breakpoint deletions occurs.
178 breaks = self.breakpoints
179 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000180 try:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000181 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000182 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000183 lines = []
184 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000185 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000186 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000187 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000188 self.update_breakpoints()
189 breaks = self.breakpoints
190 if breaks:
191 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000192 new_file.close()
193
194 def restore_file_breaks(self):
195 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000196 filename = self.io.filename
197 if filename is None:
198 return
Chui Tey69371d62002-11-04 23:39:45 +0000199 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000200 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000201 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000202 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000203 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000204 for breakpoint_linenumber in breakpoint_linenumbers:
205 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000206
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000207 def update_breakpoints(self):
208 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000209 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000210 ranges = text.tag_ranges("BREAK")
211 linenumber_list = self.ranges_to_linenumbers(ranges)
212 self.breakpoints = linenumber_list
213
214 def ranges_to_linenumbers(self, ranges):
215 lines = []
216 for index in range(0, len(ranges), 2):
217 lineno = int(float(ranges[index]))
218 end = int(float(ranges[index+1]))
219 while lineno < end:
220 lines.append(lineno)
221 lineno += 1
222 return lines
223
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000224# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000225# def saved_change_hook(self):
226# "Extend base method - clear breaks if module is modified"
227# if not self.get_saved():
228# self.clear_file_breaks()
229# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000230
231 def _close(self):
232 "Extend base method - clear breaks when module is closed"
233 self.clear_file_breaks()
234 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000235
David Scherer7aced172000-08-15 01:13:23 +0000236
237class PyShellFileList(FileList):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000238 "Extend base class: file list when a shell is present"
David Scherer7aced172000-08-15 01:13:23 +0000239
240 EditorWindow = PyShellEditorWindow
241
242 pyshell = None
243
244 def open_shell(self, event=None):
245 if self.pyshell:
246 self.pyshell.wakeup()
247 else:
248 self.pyshell = PyShell(self)
249 self.pyshell.begin()
250 return self.pyshell
251
252
253class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000254 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000255
Steven M. Gavab77d3432002-03-02 07:16:21 +0000256 def __init__(self):
257 ColorDelegator.__init__(self)
258 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000259
260 def recolorize_main(self):
261 self.tag_remove("TODO", "1.0", "iomark")
262 self.tag_add("SYNC", "1.0", "iomark")
263 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000264
Steven M. Gavab77d3432002-03-02 07:16:21 +0000265 def LoadTagDefs(self):
266 ColorDelegator.LoadTagDefs(self)
267 theme = idleConf.GetOption('main','Theme','name')
268 self.tagdefs.update({
269 "stdin": {'background':None,'foreground':None},
270 "stdout": idleConf.GetHighlight(theme, "stdout"),
271 "stderr": idleConf.GetHighlight(theme, "stderr"),
272 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000273 None: idleConf.GetHighlight(theme, "normal"),
274 })
David Scherer7aced172000-08-15 01:13:23 +0000275
David Scherer7aced172000-08-15 01:13:23 +0000276class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000277 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000278
279 def insert(self, index, chars, tags=None):
280 try:
281 if self.delegate.compare(index, "<", "iomark"):
282 self.delegate.bell()
283 return
284 except TclError:
285 pass
286 UndoDelegator.insert(self, index, chars, tags)
287
288 def delete(self, index1, index2=None):
289 try:
290 if self.delegate.compare(index1, "<", "iomark"):
291 self.delegate.bell()
292 return
293 except TclError:
294 pass
295 UndoDelegator.delete(self, index1, index2)
296
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000297
298class MyRPCClient(rpc.RPCClient):
299
300 def handle_EOF(self):
301 "Override the base class - just re-raise EOFError"
302 raise EOFError
303
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000304
David Scherer7aced172000-08-15 01:13:23 +0000305class ModifiedInterpreter(InteractiveInterpreter):
306
307 def __init__(self, tkconsole):
308 self.tkconsole = tkconsole
309 locals = sys.modules['__main__'].__dict__
310 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000311 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000312 self.restarting = False
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000313 self.subprocess_arglist = self.build_subprocess_arglist()
David Scherer7aced172000-08-15 01:13:23 +0000314
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000315 port = 8833
Chui Tey5d2af632002-05-26 13:36:41 +0000316 rpcclt = None
317 rpcpid = None
318
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000319 def spawn_subprocess(self):
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000320 args = self.subprocess_arglist
Chui Tey5d2af632002-05-26 13:36:41 +0000321 self.rpcpid = os.spawnv(os.P_NOWAIT, args[0], args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000322
Tony Lowndsf53dec22002-12-20 04:24:43 +0000323 def build_subprocess_arglist(self):
Tony Lownds2398d572003-05-13 15:28:21 +0000324 w = ['-W' + s for s in sys.warnoptions]
325 # Maybe IDLE is installed and is being accessed via sys.path,
326 # or maybe it's not installed and the idle.py script is being
327 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000328 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
329 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000330 if __name__ == 'idlelib.PyShell':
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000331 command = "__import__('idlelib.run').run.main(" + `del_exitf` +")"
Tony Lowndsf2324b92002-09-29 00:34:10 +0000332 else:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000333 command = "__import__('run').main(" + `del_exitf` + ")"
Tony Lownds2398d572003-05-13 15:28:21 +0000334 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000335
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000336 def start_subprocess(self):
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000337 addr = (LOCALHOST, self.port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +0000338 # Idle starts listening for connection on localhost
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000339 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000340 time.sleep(i)
341 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000342 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000343 break
344 except socket.error, err:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000345 print>>sys.__stderr__,"IDLE socket error: " + err[1]\
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000346 + ", retrying..."
Chui Tey5d2af632002-05-26 13:36:41 +0000347 else:
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000348 display_port_binding_error()
Kurt B. Kaisera2a3cb22002-12-24 03:33:12 +0000349 sys.exit()
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000350 self.spawn_subprocess()
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000351 # Accept the connection from the Python execution server
352 self.rpcclt.accept()
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000353 self.rpcclt.register("stdin", self.tkconsole)
354 self.rpcclt.register("stdout", self.tkconsole.stdout)
355 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000356 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000357 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000358 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000359 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000360 self.poll_subprocess()
361
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000362 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000363 if self.restarting:
364 return
365 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000366 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000367 debug = self.getdebugger()
368 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000369 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000370 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000371 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
372 except:
373 pass
374 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000375 self.rpcclt.close()
376 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000377 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000378 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000379 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000380 self.spawn_subprocess()
381 self.rpcclt.accept()
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000382 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000383 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000384 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000385 if was_executing:
386 console.write('\n')
387 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000388 halfbar = ((int(console.width) - 16) // 2) * '='
389 console.write(halfbar + ' RESTART ' + halfbar)
390 console.text.mark_set("restart", "end-1c")
391 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000392 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000393 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000394 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000395 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000396 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000397 # reload remote debugger breakpoints for all PyShellEditWindows
398 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000399 self.restarting = False
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000400
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000401 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000402 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000403
404 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000405 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000406
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000407 def kill_subprocess(self):
408 self.rpcclt.close()
409 self.unix_terminate()
410 self.tkconsole.executing = False
411 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000412
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000413 def unix_terminate(self):
414 "UNIX: make sure subprocess is terminated and collect status"
415 if hasattr(os, 'kill'):
416 try:
417 os.kill(self.rpcpid, SIGTERM)
418 except OSError:
419 # process already terminated:
420 return
421 else:
422 try:
423 os.waitpid(self.rpcpid, 0)
424 except OSError:
425 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000426
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000427 def transfer_path(self):
428 self.runcommand("""if 1:
429 import sys as _sys
430 _sys.path = %s
431 del _sys
Kurt B. Kaiserb2487332003-03-04 04:03:45 +0000432 _msg = 'Use File/Exit or your end-of-file key to quit IDLE'
433 __builtins__.quit = __builtins__.exit = _msg
434 del _msg
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000435 \n""" % `sys.path`)
436
Chui Tey5d2af632002-05-26 13:36:41 +0000437 active_seq = None
438
439 def poll_subprocess(self):
440 clt = self.rpcclt
441 if clt is None:
442 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000443 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000444 response = clt.pollresponse(self.active_seq, wait=0.05)
445 except (EOFError, IOError, KeyboardInterrupt):
446 # lost connection or subprocess terminated itself, restart
447 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000448 if self.tkconsole.closing:
449 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000450 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000451 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000452 if response:
453 self.tkconsole.resetoutput()
454 self.active_seq = None
455 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000456 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000457 if how == "OK":
458 if what is not None:
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000459 print >>console, `what`
Chui Tey5d2af632002-05-26 13:36:41 +0000460 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000461 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
462 self.remote_stack_viewer()
463 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000464 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
465 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000466 print >>console, errmsg, what
467 # we received a response to the currently active seq number:
Chui Tey5d2af632002-05-26 13:36:41 +0000468 self.tkconsole.endexecuting()
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000469 # Reschedule myself
470 if not self.tkconsole.closing:
471 self.tkconsole.text.after(self.tkconsole.pollinterval,
472 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000473
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000474 debugger = None
475
476 def setdebugger(self, debugger):
477 self.debugger = debugger
478
479 def getdebugger(self):
480 return self.debugger
481
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000482 def open_remote_stack_viewer(self):
483 """Initiate the remote stack viewer from a separate thread.
484
485 This method is called from the subprocess, and by returning from this
486 method we allow the subprocess to unblock. After a bit the shell
487 requests the subprocess to open the remote stack viewer which returns a
488 static object looking at the last exceptiopn. It is queried through
489 the RPC mechanism.
490
491 """
492 self.tkconsole.text.after(300, self.remote_stack_viewer)
493 return
494
Chui Tey5d2af632002-05-26 13:36:41 +0000495 def remote_stack_viewer(self):
496 import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000497 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000498 if oid is None:
499 self.tkconsole.root.bell()
500 return
501 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
502 from TreeWidget import ScrolledCanvas, TreeNode
503 top = Toplevel(self.tkconsole.root)
504 sc = ScrolledCanvas(top, bg="white", highlightthickness=0)
505 sc.frame.pack(expand=1, fill="both")
506 node = TreeNode(sc.canvas, None, item)
507 node.expand()
508 # XXX Should GC the remote tree when closing the window
509
David Scherer7aced172000-08-15 01:13:23 +0000510 gid = 0
511
512 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000513 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000514 filename = self.stuffsource(source)
515 self.execfile(filename, source)
516
517 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000518 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000519 if source is None:
520 source = open(filename, "r").read()
521 try:
522 code = compile(source, filename, "exec")
523 except (OverflowError, SyntaxError):
524 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000525 tkerr = self.tkconsole.stderr
526 print>>tkerr, '*** Error in script or command!\n'
527 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000528 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000529 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000530 else:
531 self.runcode(code)
532
533 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000534 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000535 filename = self.stuffsource(source)
536 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000537 self.save_warnings_filters = warnings.filters[:]
538 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000539 if isinstance(source, types.UnicodeType):
540 import IOBinding
541 try:
542 source = source.encode(IOBinding.encoding)
543 except UnicodeError:
544 self.tkconsole.resetoutput()
545 self.write("Unsupported characters in input")
546 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000547 try:
548 return InteractiveInterpreter.runsource(self, source, filename)
549 finally:
550 if self.save_warnings_filters is not None:
551 warnings.filters[:] = self.save_warnings_filters
552 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000553
554 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000555 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000556 filename = "<pyshell#%d>" % self.gid
557 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000558 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000559 linecache.cache[filename] = len(source)+1, 0, lines, filename
560 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000561
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000562 def prepend_syspath(self, filename):
563 "Prepend sys.path with file's directory if not already included"
564 self.runcommand("""if 1:
565 _filename = %s
566 import sys as _sys
567 from os.path import dirname as _dirname
568 _dir = _dirname(_filename)
569 if not _dir in _sys.path:
570 _sys.path.insert(0, _dir)
571 del _filename, _sys, _dirname, _dir
572 \n""" % `filename`)
573
David Scherer7aced172000-08-15 01:13:23 +0000574 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000575 """Extend base class method: Add Colorizing
576
577 Color the offending position instead of printing it and pointing at it
578 with a caret.
579
580 """
David Scherer7aced172000-08-15 01:13:23 +0000581 text = self.tkconsole.text
582 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000583 if stuff:
584 msg, lineno, offset, line = stuff
585 if lineno == 1:
586 pos = "iomark + %d chars" % (offset-1)
587 else:
588 pos = "iomark linestart + %d lines + %d chars" % \
589 (lineno-1, offset-1)
590 text.tag_add("ERROR", pos)
591 text.see(pos)
592 char = text.get(pos)
593 if char and char in IDENTCHARS:
594 text.tag_add("ERROR", pos + " wordstart", pos)
595 self.tkconsole.resetoutput()
596 self.write("SyntaxError: %s\n" % str(msg))
597 else:
David Scherer7aced172000-08-15 01:13:23 +0000598 self.tkconsole.resetoutput()
599 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000600 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000601
602 def unpackerror(self):
603 type, value, tb = sys.exc_info()
604 ok = type is SyntaxError
605 if ok:
606 try:
607 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000608 if not offset:
609 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000610 except:
611 ok = 0
612 if ok:
613 return msg, lineno, offset, line
614 else:
615 return None
616
617 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000618 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000619 self.tkconsole.resetoutput()
620 self.checklinecache()
621 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000622 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
623 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000624
625 def checklinecache(self):
626 c = linecache.cache
627 for key in c.keys():
628 if key[:1] + key[-1:] != "<>":
629 del c[key]
630
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000631 def display_executing_dialog(self):
632 tkMessageBox.showerror(
633 "Already executing",
634 "The Python Shell window is already executing a command; "
635 "please wait until it is finished.",
636 master=self.tkconsole.text)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000637
Chui Tey5d2af632002-05-26 13:36:41 +0000638 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000639 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000640 # The code better not raise an exception!
641 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000642 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000643 return 0
644 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000645 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000646 else:
647 exec code in self.locals
648 return 1
649
David Scherer7aced172000-08-15 01:13:23 +0000650 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000651 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000652 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000653 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000654 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000655 if self.save_warnings_filters is not None:
656 warnings.filters[:] = self.save_warnings_filters
657 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000658 debugger = self.debugger
659 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000660 self.tkconsole.beginexecuting()
661 try:
662 if not debugger and self.rpcclt is not None:
663 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
664 (code,), {})
665 elif debugger:
666 debugger.run(code, self.locals)
667 else:
668 exec code in self.locals
669 except SystemExit:
670 if tkMessageBox.askyesno(
671 "Exit?",
672 "Do you want to exit altogether?",
673 default="yes",
674 master=self.tkconsole.text):
675 raise
676 else:
677 self.showtraceback()
678 except:
David Scherer7aced172000-08-15 01:13:23 +0000679 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000680 finally:
681 if not use_subprocess:
682 self.tkconsole.endexecuting()
David Scherer7aced172000-08-15 01:13:23 +0000683
684 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000685 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000686 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000687
David Scherer7aced172000-08-15 01:13:23 +0000688class PyShell(OutputWindow):
689
690 shell_title = "Python Shell"
691
692 # Override classes
693 ColorDelegator = ModifiedColorDelegator
694 UndoDelegator = ModifiedUndoDelegator
695
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000696 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000697 menu_specs = [
698 ("file", "_File"),
699 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000700 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000701 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000702 ("windows", "_Windows"),
703 ("help", "_Help"),
704 ]
David Scherer7aced172000-08-15 01:13:23 +0000705
706 # New classes
707 from IdleHistory import History
708
709 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000710 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000711 ms = self.menu_specs
712 if ms[2][0] != "shell":
713 ms.insert(2, ("shell", "_Shell"))
David Scherer7aced172000-08-15 01:13:23 +0000714 self.interp = ModifiedInterpreter(self)
715 if flist is None:
716 root = Tk()
717 fixwordbreaks(root)
718 root.withdraw()
719 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000720 #
David Scherer7aced172000-08-15 01:13:23 +0000721 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000722 #
David Scherer7aced172000-08-15 01:13:23 +0000723 import __builtin__
724 __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000725 #
Kurt B. Kaiseree7afca2002-09-14 02:50:56 +0000726 self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000727 #
David Scherer7aced172000-08-15 01:13:23 +0000728 text = self.text
729 text.configure(wrap="char")
730 text.bind("<<newline-and-indent>>", self.enter_callback)
731 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
732 text.bind("<<interrupt-execution>>", self.cancel_callback)
733 text.bind("<<beginning-of-line>>", self.home_callback)
734 text.bind("<<end-of-file>>", self.eof_callback)
735 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000736 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000737 text.bind("<<open-python-shell>>", self.flist.open_shell)
738 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000739 if use_subprocess:
740 text.bind("<<view-restart>>", self.view_restart_mark)
741 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000742 #
David Scherer7aced172000-08-15 01:13:23 +0000743 self.save_stdout = sys.stdout
744 self.save_stderr = sys.stderr
745 self.save_stdin = sys.stdin
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000746 import IOBinding
747 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
748 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
749 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000750 if not use_subprocess:
751 sys.stdout = self.stdout
752 sys.stderr = self.stderr
753 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000754 #
David Scherer7aced172000-08-15 01:13:23 +0000755 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000756 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000757 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000758 if use_subprocess:
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000759 self.interp.start_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000760
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000761 reading = False
762 executing = False
763 canceled = False
764 endoffile = False
765 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000766
767 def toggle_debugger(self, event=None):
768 if self.executing:
769 tkMessageBox.showerror("Don't debug now",
770 "You can only toggle the debugger when idle",
771 master=self.text)
772 self.set_debugger_indicator()
773 return "break"
774 else:
775 db = self.interp.getdebugger()
776 if db:
777 self.close_debugger()
778 else:
779 self.open_debugger()
780
781 def set_debugger_indicator(self):
782 db = self.interp.getdebugger()
783 self.setvar("<<toggle-debugger>>", not not db)
784
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000785 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000786 pass # All we need is the variable
787
788 def close_debugger(self):
789 db = self.interp.getdebugger()
790 if db:
791 self.interp.setdebugger(None)
792 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000793 if self.interp.rpcclt:
794 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000795 self.resetoutput()
796 self.console.write("[DEBUG OFF]\n")
797 sys.ps1 = ">>> "
798 self.showprompt()
799 self.set_debugger_indicator()
800
801 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000802 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000803 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
804 self)
805 else:
806 dbg_gui = Debugger.Debugger(self)
807 self.interp.setdebugger(dbg_gui)
808 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000809 sys.ps1 = "[DEBUG ON]\n>>> "
810 self.showprompt()
811 self.set_debugger_indicator()
812
David Scherer7aced172000-08-15 01:13:23 +0000813 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000814 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000815 self.resetoutput()
816 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000817
818 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000819 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000820 self.executing = 0
821 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000822 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000823
824 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000825 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000826 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000827 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000828 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000829 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000830 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000831 parent=self.text)
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000832 if response == False:
David Scherer7aced172000-08-15 01:13:23 +0000833 return "cancel"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000834 self.closing = True
835 # Wait for poll_subprocess() rescheduling to stop
836 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000837
838 def close2(self):
839 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000840
841 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000842 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000843 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000844 if use_subprocess:
845 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000846 # Restore std streams
847 sys.stdout = self.save_stdout
848 sys.stderr = self.save_stderr
849 sys.stdin = self.save_stdin
850 # Break cycles
851 self.interp = None
852 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000853 self.flist.pyshell = None
854 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000855 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000856
857 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000858 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000859 return True
David Scherer7aced172000-08-15 01:13:23 +0000860
861 def short_title(self):
862 return self.shell_title
863
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000864 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000865 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000866
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000867 firewallmessage = """
868 ****************************************************************
869 Personal firewall software may warn about the connection IDLE
870 makes to its subprocess using this computer's internal loopback
871 interface. This connection is not visible on any external
872 interface and no data is sent to or received from the Internet.
873 ****************************************************************
874 """
875
David Scherer7aced172000-08-15 01:13:23 +0000876 def begin(self):
877 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000878 if use_subprocess:
879 nosub = ''
880 else:
881 nosub = "==== No Subprocess ===="
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000882 self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000883 (sys.version, sys.platform, self.COPYRIGHT,
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000884 self.firewallmessage, idlever.IDLE_VERSION, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000885 self.showprompt()
886 import Tkinter
887 Tkinter._default_root = None
888
889 def interact(self):
890 self.begin()
891 self.top.mainloop()
892
893 def readline(self):
894 save = self.reading
895 try:
896 self.reading = 1
897 self.top.mainloop()
898 finally:
899 self.reading = save
900 line = self.text.get("iomark", "end-1c")
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000901 if isinstance(line, unicode):
902 import IOBinding
903 try:
904 line = line.encode(IOBinding.encoding)
905 except UnicodeError:
906 pass
David Scherer7aced172000-08-15 01:13:23 +0000907 self.resetoutput()
908 if self.canceled:
909 self.canceled = 0
910 raise KeyboardInterrupt
911 if self.endoffile:
912 self.endoffile = 0
913 return ""
914 return line
915
916 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000917 return True
David Scherer7aced172000-08-15 01:13:23 +0000918
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000919 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000920 try:
921 if self.text.compare("sel.first", "!=", "sel.last"):
922 return # Active selection -- always use default binding
923 except:
924 pass
925 if not (self.executing or self.reading):
926 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000927 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +0000928 self.showprompt()
929 return "break"
930 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000931 self.canceled = 1
David Scherer7aced172000-08-15 01:13:23 +0000932 if self.reading:
933 self.top.quit()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000934 elif (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000935 if self.interp.getdebugger():
936 self.interp.restart_subprocess()
937 else:
938 self.interp.interrupt_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000939 return "break"
940
941 def eof_callback(self, event):
942 if self.executing and not self.reading:
943 return # Let the default binding (delete next char) take over
944 if not (self.text.compare("iomark", "==", "insert") and
945 self.text.compare("insert", "==", "end-1c")):
946 return # Let the default binding (delete next char) take over
947 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +0000948 self.resetoutput()
949 self.close()
950 else:
951 self.canceled = 0
952 self.endoffile = 1
953 self.top.quit()
954 return "break"
955
956 def home_callback(self, event):
957 if event.state != 0 and event.keysym == "Home":
958 return # <Modifier-Home>; fall back to class binding
959 if self.text.compare("iomark", "<=", "insert") and \
960 self.text.compare("insert linestart", "<=", "iomark"):
961 self.text.mark_set("insert", "iomark")
962 self.text.tag_remove("sel", "1.0", "end")
963 self.text.see("insert")
964 return "break"
965
966 def linefeed_callback(self, event):
967 # Insert a linefeed without entering anything (still autoindented)
968 if self.reading:
969 self.text.insert("insert", "\n")
970 self.text.see("insert")
971 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +0000972 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +0000973 return "break"
974
975 def enter_callback(self, event):
976 if self.executing and not self.reading:
977 return # Let the default binding (insert '\n') take over
978 # If some text is selected, recall the selection
979 # (but only if this before the I/O mark)
980 try:
981 sel = self.text.get("sel.first", "sel.last")
982 if sel:
983 if self.text.compare("sel.last", "<=", "iomark"):
984 self.recall(sel)
985 return "break"
986 except:
987 pass
988 # If we're strictly before the line containing iomark, recall
989 # the current line, less a leading prompt, less leading or
990 # trailing whitespace
991 if self.text.compare("insert", "<", "iomark linestart"):
992 # Check if there's a relevant stdin range -- if so, use it
993 prev = self.text.tag_prevrange("stdin", "insert")
994 if prev and self.text.compare("insert", "<", prev[1]):
995 self.recall(self.text.get(prev[0], prev[1]))
996 return "break"
997 next = self.text.tag_nextrange("stdin", "insert")
998 if next and self.text.compare("insert lineend", ">=", next[0]):
999 self.recall(self.text.get(next[0], next[1]))
1000 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001001 # No stdin mark -- just get the current line, less any prompt
1002 line = self.text.get("insert linestart", "insert lineend")
1003 last_line_of_prompt = sys.ps1.split('\n')[-1]
1004 if line.startswith(last_line_of_prompt):
1005 line = line[len(last_line_of_prompt):]
1006 self.recall(line)
David Scherer7aced172000-08-15 01:13:23 +00001007 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001008 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001009 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001010 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001011 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001012 # If we're in the current input and there's only whitespace
1013 # beyond the cursor, erase that whitespace first
1014 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001015 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001016 self.text.delete("insert", "end-1c")
1017 # If we're in the current input before its last line,
1018 # insert a newline right at the insert point
1019 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001020 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001021 return "break"
1022 # We're in the last line; append a newline and submit it
1023 self.text.mark_set("insert", "end-1c")
1024 if self.reading:
1025 self.text.insert("insert", "\n")
1026 self.text.see("insert")
1027 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001028 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001029 self.text.tag_add("stdin", "iomark", "end-1c")
1030 self.text.update_idletasks()
1031 if self.reading:
1032 self.top.quit() # Break out of recursive mainloop() in raw_input()
1033 else:
1034 self.runit()
1035 return "break"
1036
1037 def recall(self, s):
1038 if self.history:
1039 self.history.recall(s)
1040
1041 def runit(self):
1042 line = self.text.get("iomark", "end-1c")
1043 # Strip off last newline and surrounding whitespace.
1044 # (To allow you to hit return twice to end a statement.)
1045 i = len(line)
1046 while i > 0 and line[i-1] in " \t":
1047 i = i-1
1048 if i > 0 and line[i-1] == "\n":
1049 i = i-1
1050 while i > 0 and line[i-1] in " \t":
1051 i = i-1
1052 line = line[:i]
1053 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001054
David Scherer7aced172000-08-15 01:13:23 +00001055 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001056 if self.interp.rpcclt:
1057 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001058 try:
1059 sys.last_traceback
1060 except:
1061 tkMessageBox.showerror("No stack trace",
1062 "There is no stack trace yet.\n"
1063 "(sys.last_traceback is not defined)",
1064 master=self.text)
1065 return
1066 from StackViewer import StackBrowser
1067 sv = StackBrowser(self.root, self.flist)
1068
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001069 def view_restart_mark(self, event=None):
1070 self.text.see("iomark")
1071 self.text.see("restart")
1072
1073 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001074 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001075
David Scherer7aced172000-08-15 01:13:23 +00001076 def showprompt(self):
1077 self.resetoutput()
1078 try:
1079 s = str(sys.ps1)
1080 except:
1081 s = ""
1082 self.console.write(s)
1083 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001084 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001085 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001086
1087 def resetoutput(self):
1088 source = self.text.get("iomark", "end-1c")
1089 if self.history:
1090 self.history.history_store(source)
1091 if self.text.get("end-2c") != "\n":
1092 self.text.insert("end-1c", "\n")
1093 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001094 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001095 sys.stdout.softspace = 0
1096
1097 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001098 try:
1099 self.text.mark_gravity("iomark", "right")
1100 OutputWindow.write(self, s, tags, "iomark")
1101 self.text.mark_gravity("iomark", "left")
1102 except:
1103 pass
David Scherer7aced172000-08-15 01:13:23 +00001104 if self.canceled:
1105 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001106 if not use_subprocess:
1107 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001108
1109class PseudoFile:
1110
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001111 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001112 self.shell = shell
1113 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001114 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001115 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001116
1117 def write(self, s):
1118 self.shell.write(s, self.tags)
1119
1120 def writelines(self, l):
1121 map(self.write, l)
1122
1123 def flush(self):
1124 pass
1125
1126 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001127 return True
David Scherer7aced172000-08-15 01:13:23 +00001128
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001129
David Scherer7aced172000-08-15 01:13:23 +00001130usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001131
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001132USAGE: idle [-deins] [-t title] [file]*
1133 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1134 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001135
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001136 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001137 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001138
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001139The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001140
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001141 -e open an edit window
1142 -i open a shell window
1143
1144The following options imply -i and will open a shell:
1145
1146 -c cmd run the command in a shell, or
1147 -r file run script from file
1148
1149 -d enable the debugger
1150 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1151 -t title set title of shell window
1152
1153A default edit window will be bypassed when -c, -r, or - are used.
1154
1155[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1156
1157Examples:
1158
1159idle
1160 Open an edit window or shell depending on IDLE's configuration.
1161
1162idle foo.py foobar.py
1163 Edit the files, also open a shell if configured to start with shell.
1164
1165idle -est "Baz" foo.py
1166 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1167 window with the title "Baz".
1168
1169idle -c "import sys; print sys.argv" "foo"
1170 Open a shell window and run the command, passing "-c" in sys.argv[0]
1171 and "foo" in sys.argv[1].
1172
1173idle -d -s -r foo.py "Hello World"
1174 Open a shell window, run a startup script, enable the debugger, and
1175 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1176 sys.argv[1].
1177
1178echo "import sys; print sys.argv" | idle - "foobar"
1179 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1180 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001181"""
1182
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001183def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001184 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001185
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001186 use_subprocess = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001187 enable_shell = False
1188 enable_edit = False
1189 debug = False
1190 cmd = None
1191 script = None
1192 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001193 try:
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001194 sys.ps1
1195 except AttributeError:
1196 sys.ps1 = '>>> '
1197 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001198 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001199 except getopt.error, msg:
1200 sys.stderr.write("Error: %s\n" % str(msg))
1201 sys.stderr.write(usage_msg)
1202 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001203 for o, a in opts:
1204 if o == '-c':
1205 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001206 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001207 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001208 debug = True
1209 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001210 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001211 enable_edit = True
1212 if o == '-h':
1213 sys.stdout.write(usage_msg)
1214 sys.exit()
1215 if o == '-i':
1216 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001217 if o == '-n':
1218 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001219 if o == '-r':
1220 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001221 if os.path.isfile(script):
1222 pass
1223 else:
1224 print "No script file: ", script
1225 sys.exit()
1226 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001227 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001228 startup = True
1229 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001230 if o == '-t':
1231 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001232 enable_shell = True
1233 if args and args[0] == '-':
1234 cmd = sys.stdin.read()
1235 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001236 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001237 for i in range(len(sys.path)):
1238 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001239 if args and args[0] == '-':
1240 sys.argv = [''] + args[1:]
1241 elif cmd:
1242 sys.argv = ['-c'] + args
1243 elif script:
1244 sys.argv = [script] + args
1245 elif args:
1246 enable_edit = True
1247 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001248 for filename in args:
1249 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001250 for dir in pathx:
1251 dir = os.path.abspath(dir)
1252 if not dir in sys.path:
1253 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001254 else:
1255 dir = os.getcwd()
1256 if not dir in sys.path:
1257 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001258 # check the IDLE settings configuration (but command line overrides)
1259 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001260 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001261 enable_edit = enable_edit or edit_start
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001262 enable_shell = enable_shell or not edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001263 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001264 root = Tk(className="Idle")
1265 fixwordbreaks(root)
1266 root.withdraw()
1267 flist = PyShellFileList(root)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001268 if enable_edit:
1269 if not (cmd or script):
1270 for filename in args:
1271 flist.open(filename)
1272 if not args:
1273 flist.new()
1274 if enable_shell:
1275 flist.open_shell()
1276 elif enable_shell:
1277 flist.pyshell = PyShell(flist)
1278 flist.pyshell.begin()
1279 shell = flist.pyshell
1280 # handle remaining options:
1281 if debug:
1282 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001283 if startup:
1284 filename = os.environ.get("IDLESTARTUP") or \
1285 os.environ.get("PYTHONSTARTUP")
1286 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001287 shell.interp.execfile(filename)
1288 if cmd or script:
1289 shell.interp.runcommand("""if 1:
1290 import sys as _sys
1291 _sys.argv = %s
1292 del _sys
1293 \n""" % `sys.argv`)
1294 if cmd:
1295 shell.interp.execsource(cmd)
1296 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001297 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001298 shell.interp.execfile(script)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001299 root.mainloop()
1300 root.destroy()
1301
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001302
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001303def display_port_binding_error():
1304 print """\
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001305\nIDLE cannot run.
Steven M. Gava1f733ba2001-10-07 11:44:49 +00001306
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001307IDLE needs to use a specific TCP/IP port (8833) in order to communicate with
1308its Python execution server. IDLE is unable to bind to this port, and so
1309cannot start. Here are some possible causes of this problem:
Steven M. Gava1f733ba2001-10-07 11:44:49 +00001310
1311 1. TCP/IP networking is not installed or not working on this computer
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001312 2. Another program (another IDLE?) is running that uses this port
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001313 3. Personal firewall software is preventing IDLE from using this port
Steven M. Gava1f733ba2001-10-07 11:44:49 +00001314
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001315Run IDLE with the -n command line switch to start without a subprocess
1316and refer to Help/IDLE Help "Running without a subprocess" for further
1317details.
Steven M. Gava1f733ba2001-10-07 11:44:49 +00001318"""
David Scherer7aced172000-08-15 01:13:23 +00001319
1320if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001321 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001322 main()