blob: fe940cb9aa940abe7a2e18f55a0c2f1abf0b95ed [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
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019try:
20 from Tkinter import *
21except ImportError:
22 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
23 "Your Python may not be configured for Tk. **"
24 sys.exit(1)
David Scherer7aced172000-08-15 01:13:23 +000025import tkMessageBox
26
27from EditorWindow import EditorWindow, fixwordbreaks
28from FileList import FileList
29from ColorDelegator import ColorDelegator
30from UndoDelegator import UndoDelegator
Kurt B. Kaiser969de452002-06-12 03:28:57 +000031from OutputWindow import OutputWindow
Steven M. Gava99300612001-11-04 07:03:08 +000032from configHandler import idleConf
David Scherer7aced172000-08-15 01:13:23 +000033import idlever
34
Chui Tey5d2af632002-05-26 13:36:41 +000035import rpc
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +000036import Debugger
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +000037import RemoteDebugger
Chui Tey5d2af632002-05-26 13:36:41 +000038
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000039IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000040LOCALHOST = '127.0.0.1'
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000041
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000042try:
43 from signal import SIGTERM
44except ImportError:
45 SIGTERM = 15
46
Chui Tey5d2af632002-05-26 13:36:41 +000047# Change warnings module to write to sys.__stderr__
48try:
49 import warnings
50except ImportError:
51 pass
52else:
53 def idle_showwarning(message, category, filename, lineno):
54 file = sys.__stderr__
55 file.write(warnings.formatwarning(message, category, filename, lineno))
56 warnings.showwarning = idle_showwarning
57
Kurt B. Kaiser81885592002-11-29 22:10:53 +000058def extended_linecache_checkcache(orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000059 """Extend linecache.checkcache to preserve the <pyshell#...> entries
60
Kurt B. Kaiser81885592002-11-29 22:10:53 +000061 Rather than repeating the linecache code, patch it to save the pyshell#
62 entries, call the original linecache.checkcache(), and then restore the
63 saved entries. Assigning the orig_checkcache keyword arg freezes its value
64 at definition time to the (original) method linecache.checkcache(), i.e.
65 makes orig_checkcache lexical.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000066
67 """
David Scherer7aced172000-08-15 01:13:23 +000068 cache = linecache.cache
69 save = {}
70 for filename in cache.keys():
71 if filename[:1] + filename[-1:] == '<>':
72 save[filename] = cache[filename]
73 orig_checkcache()
74 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000075
Kurt B. Kaiser81885592002-11-29 22:10:53 +000076# Patch linecache.checkcache():
77linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000078
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000079
David Scherer7aced172000-08-15 01:13:23 +000080class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +000081 "Regular text edit window when a shell is present"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000082
David Scherer7aced172000-08-15 01:13:23 +000083 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000084 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +000085 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +000086 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000087 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +000088 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
89
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +000090 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
91 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +000092 # whenever a file is changed, restore breakpoints
93 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +000094 def filename_changed_hook(old_hook=self.io.filename_change_hook,
95 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +000096 self.restore_file_breaks()
97 old_hook()
98 self.io.set_filename_change_hook(filename_changed_hook)
99
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000100 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
101 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000102
Chui Teya2adb0f2002-11-04 22:14:54 +0000103 def set_breakpoint(self, lineno):
104 text = self.text
105 filename = self.io.filename
106 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
107 try:
108 i = self.breakpoints.index(lineno)
109 except ValueError: # only add if missing, i.e. do once
110 self.breakpoints.append(lineno)
111 try: # update the subprocess debugger
112 debug = self.flist.pyshell.interp.debugger
113 debug.set_breakpoint_here(filename, lineno)
114 except: # but debugger may not be active right now....
115 pass
116
David Scherer7aced172000-08-15 01:13:23 +0000117 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000118 text = self.text
119 filename = self.io.filename
120 if not filename:
121 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000122 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000123 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000124 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000125
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000126 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000127 text = self.text
128 filename = self.io.filename
129 if not filename:
130 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000131 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000132 lineno = int(float(text.index("insert")))
133 try:
134 self.breakpoints.remove(lineno)
135 except:
136 pass
137 text.tag_remove("BREAK", "insert linestart",\
138 "insert lineend +1char")
139 try:
140 debug = self.flist.pyshell.interp.debugger
141 debug.clear_breakpoint_here(filename, lineno)
142 except:
143 pass
144
145 def clear_file_breaks(self):
146 if self.breakpoints:
147 text = self.text
148 filename = self.io.filename
149 if not filename:
150 text.bell()
151 return
152 self.breakpoints = []
153 text.tag_remove("BREAK", "1.0", END)
154 try:
155 debug = self.flist.pyshell.interp.debugger
156 debug.clear_file_breaks(filename)
157 except:
158 pass
159
Chui Teya2adb0f2002-11-04 22:14:54 +0000160 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000161 "Save breakpoints when file is saved"
162 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
163 # be run. The breaks are saved at that time. If we introduce
164 # a temporary file save feature the save breaks functionality
165 # needs to be re-verified, since the breaks at the time the
166 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000167 # permanent save of the file. Currently, a break introduced
168 # after a save will be effective, but not persistent.
169 # This is necessary to keep the saved breaks synched with the
170 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000171 #
172 # Breakpoints are set as tagged ranges in the text. Certain
173 # kinds of edits cause these ranges to be deleted: Inserting
174 # or deleting a line just before a breakpoint, and certain
175 # deletions prior to a breakpoint. These issues need to be
176 # investigated and understood. It's not clear if they are
177 # Tk issues or IDLE issues, or whether they can actually
178 # be fixed. Since a modified file has to be saved before it is
179 # run, and since self.breakpoints (from which the subprocess
180 # debugger is loaded) is updated during the save, the visible
181 # breaks stay synched with the subprocess even if one of these
182 # unexpected breakpoint deletions occurs.
183 breaks = self.breakpoints
184 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000185 try:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000186 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000187 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000188 lines = []
189 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000190 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000191 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000192 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000193 self.update_breakpoints()
194 breaks = self.breakpoints
195 if breaks:
196 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000197 new_file.close()
198
199 def restore_file_breaks(self):
200 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000201 filename = self.io.filename
202 if filename is None:
203 return
Chui Tey69371d62002-11-04 23:39:45 +0000204 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000205 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000206 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000207 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000208 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000209 for breakpoint_linenumber in breakpoint_linenumbers:
210 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000211
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000212 def update_breakpoints(self):
213 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000214 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000215 ranges = text.tag_ranges("BREAK")
216 linenumber_list = self.ranges_to_linenumbers(ranges)
217 self.breakpoints = linenumber_list
218
219 def ranges_to_linenumbers(self, ranges):
220 lines = []
221 for index in range(0, len(ranges), 2):
222 lineno = int(float(ranges[index]))
223 end = int(float(ranges[index+1]))
224 while lineno < end:
225 lines.append(lineno)
226 lineno += 1
227 return lines
228
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000229# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000230# def saved_change_hook(self):
231# "Extend base method - clear breaks if module is modified"
232# if not self.get_saved():
233# self.clear_file_breaks()
234# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000235
236 def _close(self):
237 "Extend base method - clear breaks when module is closed"
238 self.clear_file_breaks()
239 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000240
David Scherer7aced172000-08-15 01:13:23 +0000241
242class PyShellFileList(FileList):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000243 "Extend base class: file list when a shell is present"
David Scherer7aced172000-08-15 01:13:23 +0000244
245 EditorWindow = PyShellEditorWindow
246
247 pyshell = None
248
249 def open_shell(self, event=None):
250 if self.pyshell:
251 self.pyshell.wakeup()
252 else:
253 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000254 if self.pyshell:
255 if not self.pyshell.begin():
256 return None
David Scherer7aced172000-08-15 01:13:23 +0000257 return self.pyshell
258
259
260class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000261 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000262
Steven M. Gavab77d3432002-03-02 07:16:21 +0000263 def __init__(self):
264 ColorDelegator.__init__(self)
265 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000266
267 def recolorize_main(self):
268 self.tag_remove("TODO", "1.0", "iomark")
269 self.tag_add("SYNC", "1.0", "iomark")
270 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000271
Steven M. Gavab77d3432002-03-02 07:16:21 +0000272 def LoadTagDefs(self):
273 ColorDelegator.LoadTagDefs(self)
274 theme = idleConf.GetOption('main','Theme','name')
275 self.tagdefs.update({
276 "stdin": {'background':None,'foreground':None},
277 "stdout": idleConf.GetHighlight(theme, "stdout"),
278 "stderr": idleConf.GetHighlight(theme, "stderr"),
279 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000280 None: idleConf.GetHighlight(theme, "normal"),
281 })
David Scherer7aced172000-08-15 01:13:23 +0000282
David Scherer7aced172000-08-15 01:13:23 +0000283class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000284 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000285
286 def insert(self, index, chars, tags=None):
287 try:
288 if self.delegate.compare(index, "<", "iomark"):
289 self.delegate.bell()
290 return
291 except TclError:
292 pass
293 UndoDelegator.insert(self, index, chars, tags)
294
295 def delete(self, index1, index2=None):
296 try:
297 if self.delegate.compare(index1, "<", "iomark"):
298 self.delegate.bell()
299 return
300 except TclError:
301 pass
302 UndoDelegator.delete(self, index1, index2)
303
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000304
305class MyRPCClient(rpc.RPCClient):
306
307 def handle_EOF(self):
308 "Override the base class - just re-raise EOFError"
309 raise EOFError
310
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000311
David Scherer7aced172000-08-15 01:13:23 +0000312class ModifiedInterpreter(InteractiveInterpreter):
313
314 def __init__(self, tkconsole):
315 self.tkconsole = tkconsole
316 locals = sys.modules['__main__'].__dict__
317 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000318 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000319 self.restarting = False
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000320 self.subprocess_arglist = self.build_subprocess_arglist()
David Scherer7aced172000-08-15 01:13:23 +0000321
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000322 port = 8833
Chui Tey5d2af632002-05-26 13:36:41 +0000323 rpcclt = None
324 rpcpid = None
325
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000326 def spawn_subprocess(self):
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000327 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000328 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000329
Tony Lowndsf53dec22002-12-20 04:24:43 +0000330 def build_subprocess_arglist(self):
Tony Lownds2398d572003-05-13 15:28:21 +0000331 w = ['-W' + s for s in sys.warnoptions]
332 # Maybe IDLE is installed and is being accessed via sys.path,
333 # or maybe it's not installed and the idle.py script is being
334 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000335 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
336 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000337 if __name__ == 'idlelib.PyShell':
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000338 command = "__import__('idlelib.run').run.main(" + `del_exitf` +")"
Tony Lowndsf2324b92002-09-29 00:34:10 +0000339 else:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000340 command = "__import__('run').main(" + `del_exitf` + ")"
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000341 if sys.platform[:3] == 'win' and ' ' in sys.executable:
342 # handle embedded space in path by quoting the argument
343 decorated_exec = '"%s"' % sys.executable
344 else:
345 decorated_exec = sys.executable
346 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000347
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000348 def start_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000349 # spawning first avoids passing a listening socket to the subprocess
350 self.spawn_subprocess()
351 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000352 addr = (LOCALHOST, self.port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +0000353 # Idle starts listening for connection on localhost
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000354 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000355 time.sleep(i)
356 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000357 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000358 break
359 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000360 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000361 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000362 self.display_port_binding_error()
363 return None
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000364 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000365 self.rpcclt.listening_sock.settimeout(10)
366 try:
367 self.rpcclt.accept()
368 except socket.timeout, err:
369 self.display_no_subprocess_error()
370 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000371 self.rpcclt.register("stdin", self.tkconsole)
372 self.rpcclt.register("stdout", self.tkconsole.stdout)
373 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000374 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000375 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000376 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000377 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000378 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000379 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000380
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000381 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000382 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000383 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000384 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000385 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000386 debug = self.getdebugger()
387 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000388 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000389 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000390 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
391 except:
392 pass
393 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000394 self.rpcclt.close()
395 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000396 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000397 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000398 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000399 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000400 try:
401 self.rpcclt.accept()
402 except socket.timeout, err:
403 self.display_no_subprocess_error()
404 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000405 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000406 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000407 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000408 if was_executing:
409 console.write('\n')
410 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000411 halfbar = ((int(console.width) - 16) // 2) * '='
412 console.write(halfbar + ' RESTART ' + halfbar)
413 console.text.mark_set("restart", "end-1c")
414 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000415 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000416 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000417 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000418 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000419 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000420 # reload remote debugger breakpoints for all PyShellEditWindows
421 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000422 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000423 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000424
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000425 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000426 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000427
428 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000429 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000430
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000431 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000432 try:
433 self.rpcclt.close()
434 except AttributeError: # no socket
435 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000436 self.unix_terminate()
437 self.tkconsole.executing = False
438 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000439
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000440 def unix_terminate(self):
441 "UNIX: make sure subprocess is terminated and collect status"
442 if hasattr(os, 'kill'):
443 try:
444 os.kill(self.rpcpid, SIGTERM)
445 except OSError:
446 # process already terminated:
447 return
448 else:
449 try:
450 os.waitpid(self.rpcpid, 0)
451 except OSError:
452 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000453
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000454 def transfer_path(self):
455 self.runcommand("""if 1:
456 import sys as _sys
457 _sys.path = %s
458 del _sys
Kurt B. Kaiserb2487332003-03-04 04:03:45 +0000459 _msg = 'Use File/Exit or your end-of-file key to quit IDLE'
460 __builtins__.quit = __builtins__.exit = _msg
461 del _msg
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000462 \n""" % `sys.path`)
463
Chui Tey5d2af632002-05-26 13:36:41 +0000464 active_seq = None
465
466 def poll_subprocess(self):
467 clt = self.rpcclt
468 if clt is None:
469 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000470 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000471 response = clt.pollresponse(self.active_seq, wait=0.05)
472 except (EOFError, IOError, KeyboardInterrupt):
473 # lost connection or subprocess terminated itself, restart
474 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000475 if self.tkconsole.closing:
476 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000477 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000478 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000479 if response:
480 self.tkconsole.resetoutput()
481 self.active_seq = None
482 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000483 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000484 if how == "OK":
485 if what is not None:
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000486 print >>console, `what`
Chui Tey5d2af632002-05-26 13:36:41 +0000487 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000488 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
489 self.remote_stack_viewer()
490 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000491 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
492 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000493 print >>console, errmsg, what
494 # we received a response to the currently active seq number:
Chui Tey5d2af632002-05-26 13:36:41 +0000495 self.tkconsole.endexecuting()
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000496 # Reschedule myself
497 if not self.tkconsole.closing:
498 self.tkconsole.text.after(self.tkconsole.pollinterval,
499 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000500
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000501 debugger = None
502
503 def setdebugger(self, debugger):
504 self.debugger = debugger
505
506 def getdebugger(self):
507 return self.debugger
508
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000509 def open_remote_stack_viewer(self):
510 """Initiate the remote stack viewer from a separate thread.
511
512 This method is called from the subprocess, and by returning from this
513 method we allow the subprocess to unblock. After a bit the shell
514 requests the subprocess to open the remote stack viewer which returns a
515 static object looking at the last exceptiopn. It is queried through
516 the RPC mechanism.
517
518 """
519 self.tkconsole.text.after(300, self.remote_stack_viewer)
520 return
521
Chui Tey5d2af632002-05-26 13:36:41 +0000522 def remote_stack_viewer(self):
523 import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000524 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000525 if oid is None:
526 self.tkconsole.root.bell()
527 return
528 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
529 from TreeWidget import ScrolledCanvas, TreeNode
530 top = Toplevel(self.tkconsole.root)
531 sc = ScrolledCanvas(top, bg="white", highlightthickness=0)
532 sc.frame.pack(expand=1, fill="both")
533 node = TreeNode(sc.canvas, None, item)
534 node.expand()
535 # XXX Should GC the remote tree when closing the window
536
David Scherer7aced172000-08-15 01:13:23 +0000537 gid = 0
538
539 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000540 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000541 filename = self.stuffsource(source)
542 self.execfile(filename, source)
543
544 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000545 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000546 if source is None:
547 source = open(filename, "r").read()
548 try:
549 code = compile(source, filename, "exec")
550 except (OverflowError, SyntaxError):
551 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000552 tkerr = self.tkconsole.stderr
553 print>>tkerr, '*** Error in script or command!\n'
554 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000555 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000556 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000557 else:
558 self.runcode(code)
559
560 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000561 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000562 filename = self.stuffsource(source)
563 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000564 self.save_warnings_filters = warnings.filters[:]
565 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000566 if isinstance(source, types.UnicodeType):
567 import IOBinding
568 try:
569 source = source.encode(IOBinding.encoding)
570 except UnicodeError:
571 self.tkconsole.resetoutput()
572 self.write("Unsupported characters in input")
573 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000574 try:
575 return InteractiveInterpreter.runsource(self, source, filename)
576 finally:
577 if self.save_warnings_filters is not None:
578 warnings.filters[:] = self.save_warnings_filters
579 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000580
581 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000582 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000583 filename = "<pyshell#%d>" % self.gid
584 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000585 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000586 linecache.cache[filename] = len(source)+1, 0, lines, filename
587 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000588
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000589 def prepend_syspath(self, filename):
590 "Prepend sys.path with file's directory if not already included"
591 self.runcommand("""if 1:
592 _filename = %s
593 import sys as _sys
594 from os.path import dirname as _dirname
595 _dir = _dirname(_filename)
596 if not _dir in _sys.path:
597 _sys.path.insert(0, _dir)
598 del _filename, _sys, _dirname, _dir
599 \n""" % `filename`)
600
David Scherer7aced172000-08-15 01:13:23 +0000601 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000602 """Extend base class method: Add Colorizing
603
604 Color the offending position instead of printing it and pointing at it
605 with a caret.
606
607 """
David Scherer7aced172000-08-15 01:13:23 +0000608 text = self.tkconsole.text
609 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000610 if stuff:
611 msg, lineno, offset, line = stuff
612 if lineno == 1:
613 pos = "iomark + %d chars" % (offset-1)
614 else:
615 pos = "iomark linestart + %d lines + %d chars" % \
616 (lineno-1, offset-1)
617 text.tag_add("ERROR", pos)
618 text.see(pos)
619 char = text.get(pos)
620 if char and char in IDENTCHARS:
621 text.tag_add("ERROR", pos + " wordstart", pos)
622 self.tkconsole.resetoutput()
623 self.write("SyntaxError: %s\n" % str(msg))
624 else:
David Scherer7aced172000-08-15 01:13:23 +0000625 self.tkconsole.resetoutput()
626 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000627 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000628
629 def unpackerror(self):
630 type, value, tb = sys.exc_info()
631 ok = type is SyntaxError
632 if ok:
633 try:
634 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000635 if not offset:
636 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000637 except:
638 ok = 0
639 if ok:
640 return msg, lineno, offset, line
641 else:
642 return None
643
644 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000645 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000646 self.tkconsole.resetoutput()
647 self.checklinecache()
648 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000649 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
650 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000651
652 def checklinecache(self):
653 c = linecache.cache
654 for key in c.keys():
655 if key[:1] + key[-1:] != "<>":
656 del c[key]
657
Chui Tey5d2af632002-05-26 13:36:41 +0000658 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000659 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000660 # The code better not raise an exception!
661 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000662 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000663 return 0
664 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000665 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000666 else:
667 exec code in self.locals
668 return 1
669
David Scherer7aced172000-08-15 01:13:23 +0000670 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000671 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000672 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000673 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000674 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000675 if self.save_warnings_filters is not None:
676 warnings.filters[:] = self.save_warnings_filters
677 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000678 debugger = self.debugger
679 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000680 self.tkconsole.beginexecuting()
681 try:
682 if not debugger and self.rpcclt is not None:
683 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
684 (code,), {})
685 elif debugger:
686 debugger.run(code, self.locals)
687 else:
688 exec code in self.locals
689 except SystemExit:
690 if tkMessageBox.askyesno(
691 "Exit?",
692 "Do you want to exit altogether?",
693 default="yes",
694 master=self.tkconsole.text):
695 raise
696 else:
697 self.showtraceback()
698 except:
David Scherer7aced172000-08-15 01:13:23 +0000699 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000700 finally:
701 if not use_subprocess:
702 self.tkconsole.endexecuting()
David Scherer7aced172000-08-15 01:13:23 +0000703
704 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000705 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000706 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000707
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000708 def display_port_binding_error(self):
709 tkMessageBox.showerror(
710 "Port Binding Error",
711 "IDLE can't bind TCP/IP port 8833, which is necessary to "
712 "communicate with its Python execution server. Either "
713 "no networking is installed on this computer or another "
714 "process (another IDLE?) is using the port. Run IDLE with the -n "
715 "command line switch to start without a subprocess and refer to "
716 "Help/IDLE Help 'Running without a subprocess' for further "
717 "details.",
718 master=self.tkconsole.text)
719
720 def display_no_subprocess_error(self):
721 tkMessageBox.showerror(
722 "Subprocess Startup Error",
723 "IDLE's subprocess didn't make connection. Either IDLE can't "
724 "start a subprocess or personal firewall software is blocking "
725 "the connection.",
726 master=self.tkconsole.text)
727
728 def display_executing_dialog(self):
729 tkMessageBox.showerror(
730 "Already executing",
731 "The Python Shell window is already executing a command; "
732 "please wait until it is finished.",
733 master=self.tkconsole.text)
734
735
David Scherer7aced172000-08-15 01:13:23 +0000736class PyShell(OutputWindow):
737
738 shell_title = "Python Shell"
739
740 # Override classes
741 ColorDelegator = ModifiedColorDelegator
742 UndoDelegator = ModifiedUndoDelegator
743
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000744 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000745 menu_specs = [
746 ("file", "_File"),
747 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000748 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000749 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000750 ("windows", "_Windows"),
751 ("help", "_Help"),
752 ]
David Scherer7aced172000-08-15 01:13:23 +0000753
754 # New classes
755 from IdleHistory import History
756
757 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000758 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000759 ms = self.menu_specs
760 if ms[2][0] != "shell":
761 ms.insert(2, ("shell", "_Shell"))
David Scherer7aced172000-08-15 01:13:23 +0000762 self.interp = ModifiedInterpreter(self)
763 if flist is None:
764 root = Tk()
765 fixwordbreaks(root)
766 root.withdraw()
767 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000768 #
David Scherer7aced172000-08-15 01:13:23 +0000769 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000770 #
David Scherer7aced172000-08-15 01:13:23 +0000771 import __builtin__
772 __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000773 #
Kurt B. Kaiseree7afca2002-09-14 02:50:56 +0000774 self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000775 #
David Scherer7aced172000-08-15 01:13:23 +0000776 text = self.text
777 text.configure(wrap="char")
778 text.bind("<<newline-and-indent>>", self.enter_callback)
779 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
780 text.bind("<<interrupt-execution>>", self.cancel_callback)
781 text.bind("<<beginning-of-line>>", self.home_callback)
782 text.bind("<<end-of-file>>", self.eof_callback)
783 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000784 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000785 text.bind("<<open-python-shell>>", self.flist.open_shell)
786 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000787 if use_subprocess:
788 text.bind("<<view-restart>>", self.view_restart_mark)
789 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000790 #
David Scherer7aced172000-08-15 01:13:23 +0000791 self.save_stdout = sys.stdout
792 self.save_stderr = sys.stderr
793 self.save_stdin = sys.stdin
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000794 import IOBinding
795 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
796 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
797 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000798 if not use_subprocess:
799 sys.stdout = self.stdout
800 sys.stderr = self.stderr
801 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000802 #
David Scherer7aced172000-08-15 01:13:23 +0000803 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000804 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000805 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000806
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000807 reading = False
808 executing = False
809 canceled = False
810 endoffile = False
811 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000812
813 def toggle_debugger(self, event=None):
814 if self.executing:
815 tkMessageBox.showerror("Don't debug now",
816 "You can only toggle the debugger when idle",
817 master=self.text)
818 self.set_debugger_indicator()
819 return "break"
820 else:
821 db = self.interp.getdebugger()
822 if db:
823 self.close_debugger()
824 else:
825 self.open_debugger()
826
827 def set_debugger_indicator(self):
828 db = self.interp.getdebugger()
829 self.setvar("<<toggle-debugger>>", not not db)
830
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000831 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000832 pass # All we need is the variable
833
834 def close_debugger(self):
835 db = self.interp.getdebugger()
836 if db:
837 self.interp.setdebugger(None)
838 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000839 if self.interp.rpcclt:
840 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000841 self.resetoutput()
842 self.console.write("[DEBUG OFF]\n")
843 sys.ps1 = ">>> "
844 self.showprompt()
845 self.set_debugger_indicator()
846
847 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000848 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000849 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
850 self)
851 else:
852 dbg_gui = Debugger.Debugger(self)
853 self.interp.setdebugger(dbg_gui)
854 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000855 sys.ps1 = "[DEBUG ON]\n>>> "
856 self.showprompt()
857 self.set_debugger_indicator()
858
David Scherer7aced172000-08-15 01:13:23 +0000859 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000860 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000861 self.resetoutput()
862 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000863
864 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000865 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000866 self.executing = 0
867 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000868 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000869
870 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000871 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000872 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000873 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000874 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000875 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000876 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000877 parent=self.text)
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000878 if response == False:
David Scherer7aced172000-08-15 01:13:23 +0000879 return "cancel"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000880 self.closing = True
881 # Wait for poll_subprocess() rescheduling to stop
882 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000883
884 def close2(self):
885 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000886
887 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000888 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000889 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000890 if use_subprocess:
891 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000892 # Restore std streams
893 sys.stdout = self.save_stdout
894 sys.stderr = self.save_stderr
895 sys.stdin = self.save_stdin
896 # Break cycles
897 self.interp = None
898 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000899 self.flist.pyshell = None
900 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000901 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000902
903 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000904 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000905 return True
David Scherer7aced172000-08-15 01:13:23 +0000906
907 def short_title(self):
908 return self.shell_title
909
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000910 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000911 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000912
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000913 firewallmessage = """
914 ****************************************************************
915 Personal firewall software may warn about the connection IDLE
916 makes to its subprocess using this computer's internal loopback
917 interface. This connection is not visible on any external
918 interface and no data is sent to or received from the Internet.
919 ****************************************************************
920 """
921
David Scherer7aced172000-08-15 01:13:23 +0000922 def begin(self):
923 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000924 if use_subprocess:
925 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000926 client = self.interp.start_subprocess()
927 if not client:
928 self.close()
929 return None
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000930 else:
931 nosub = "==== No Subprocess ===="
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000932 self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000933 (sys.version, sys.platform, self.COPYRIGHT,
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000934 self.firewallmessage, idlever.IDLE_VERSION, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000935 self.showprompt()
936 import Tkinter
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000937 Tkinter._default_root = None # 03Jan04 KBK What's this?
938 return client
David Scherer7aced172000-08-15 01:13:23 +0000939
940 def readline(self):
941 save = self.reading
942 try:
943 self.reading = 1
944 self.top.mainloop()
945 finally:
946 self.reading = save
947 line = self.text.get("iomark", "end-1c")
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000948 if isinstance(line, unicode):
949 import IOBinding
950 try:
951 line = line.encode(IOBinding.encoding)
952 except UnicodeError:
953 pass
David Scherer7aced172000-08-15 01:13:23 +0000954 self.resetoutput()
955 if self.canceled:
956 self.canceled = 0
957 raise KeyboardInterrupt
958 if self.endoffile:
959 self.endoffile = 0
960 return ""
961 return line
962
963 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000964 return True
David Scherer7aced172000-08-15 01:13:23 +0000965
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000966 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000967 try:
968 if self.text.compare("sel.first", "!=", "sel.last"):
969 return # Active selection -- always use default binding
970 except:
971 pass
972 if not (self.executing or self.reading):
973 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000974 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +0000975 self.showprompt()
976 return "break"
977 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000978 self.canceled = 1
David Scherer7aced172000-08-15 01:13:23 +0000979 if self.reading:
980 self.top.quit()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000981 elif (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000982 if self.interp.getdebugger():
983 self.interp.restart_subprocess()
984 else:
985 self.interp.interrupt_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000986 return "break"
987
988 def eof_callback(self, event):
989 if self.executing and not self.reading:
990 return # Let the default binding (delete next char) take over
991 if not (self.text.compare("iomark", "==", "insert") and
992 self.text.compare("insert", "==", "end-1c")):
993 return # Let the default binding (delete next char) take over
994 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +0000995 self.resetoutput()
996 self.close()
997 else:
998 self.canceled = 0
999 self.endoffile = 1
1000 self.top.quit()
1001 return "break"
1002
1003 def home_callback(self, event):
1004 if event.state != 0 and event.keysym == "Home":
1005 return # <Modifier-Home>; fall back to class binding
1006 if self.text.compare("iomark", "<=", "insert") and \
1007 self.text.compare("insert linestart", "<=", "iomark"):
1008 self.text.mark_set("insert", "iomark")
1009 self.text.tag_remove("sel", "1.0", "end")
1010 self.text.see("insert")
1011 return "break"
1012
1013 def linefeed_callback(self, event):
1014 # Insert a linefeed without entering anything (still autoindented)
1015 if self.reading:
1016 self.text.insert("insert", "\n")
1017 self.text.see("insert")
1018 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001019 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001020 return "break"
1021
1022 def enter_callback(self, event):
1023 if self.executing and not self.reading:
1024 return # Let the default binding (insert '\n') take over
1025 # If some text is selected, recall the selection
1026 # (but only if this before the I/O mark)
1027 try:
1028 sel = self.text.get("sel.first", "sel.last")
1029 if sel:
1030 if self.text.compare("sel.last", "<=", "iomark"):
1031 self.recall(sel)
1032 return "break"
1033 except:
1034 pass
1035 # If we're strictly before the line containing iomark, recall
1036 # the current line, less a leading prompt, less leading or
1037 # trailing whitespace
1038 if self.text.compare("insert", "<", "iomark linestart"):
1039 # Check if there's a relevant stdin range -- if so, use it
1040 prev = self.text.tag_prevrange("stdin", "insert")
1041 if prev and self.text.compare("insert", "<", prev[1]):
1042 self.recall(self.text.get(prev[0], prev[1]))
1043 return "break"
1044 next = self.text.tag_nextrange("stdin", "insert")
1045 if next and self.text.compare("insert lineend", ">=", next[0]):
1046 self.recall(self.text.get(next[0], next[1]))
1047 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001048 # No stdin mark -- just get the current line, less any prompt
1049 line = self.text.get("insert linestart", "insert lineend")
1050 last_line_of_prompt = sys.ps1.split('\n')[-1]
1051 if line.startswith(last_line_of_prompt):
1052 line = line[len(last_line_of_prompt):]
1053 self.recall(line)
David Scherer7aced172000-08-15 01:13:23 +00001054 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001055 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001056 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001057 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001058 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001059 # If we're in the current input and there's only whitespace
1060 # beyond the cursor, erase that whitespace first
1061 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001062 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001063 self.text.delete("insert", "end-1c")
1064 # If we're in the current input before its last line,
1065 # insert a newline right at the insert point
1066 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001067 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001068 return "break"
1069 # We're in the last line; append a newline and submit it
1070 self.text.mark_set("insert", "end-1c")
1071 if self.reading:
1072 self.text.insert("insert", "\n")
1073 self.text.see("insert")
1074 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001075 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001076 self.text.tag_add("stdin", "iomark", "end-1c")
1077 self.text.update_idletasks()
1078 if self.reading:
1079 self.top.quit() # Break out of recursive mainloop() in raw_input()
1080 else:
1081 self.runit()
1082 return "break"
1083
1084 def recall(self, s):
1085 if self.history:
1086 self.history.recall(s)
1087
1088 def runit(self):
1089 line = self.text.get("iomark", "end-1c")
1090 # Strip off last newline and surrounding whitespace.
1091 # (To allow you to hit return twice to end a statement.)
1092 i = len(line)
1093 while i > 0 and line[i-1] in " \t":
1094 i = i-1
1095 if i > 0 and line[i-1] == "\n":
1096 i = i-1
1097 while i > 0 and line[i-1] in " \t":
1098 i = i-1
1099 line = line[:i]
1100 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001101
David Scherer7aced172000-08-15 01:13:23 +00001102 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001103 if self.interp.rpcclt:
1104 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001105 try:
1106 sys.last_traceback
1107 except:
1108 tkMessageBox.showerror("No stack trace",
1109 "There is no stack trace yet.\n"
1110 "(sys.last_traceback is not defined)",
1111 master=self.text)
1112 return
1113 from StackViewer import StackBrowser
1114 sv = StackBrowser(self.root, self.flist)
1115
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001116 def view_restart_mark(self, event=None):
1117 self.text.see("iomark")
1118 self.text.see("restart")
1119
1120 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001121 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001122
David Scherer7aced172000-08-15 01:13:23 +00001123 def showprompt(self):
1124 self.resetoutput()
1125 try:
1126 s = str(sys.ps1)
1127 except:
1128 s = ""
1129 self.console.write(s)
1130 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001131 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001132 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001133
1134 def resetoutput(self):
1135 source = self.text.get("iomark", "end-1c")
1136 if self.history:
1137 self.history.history_store(source)
1138 if self.text.get("end-2c") != "\n":
1139 self.text.insert("end-1c", "\n")
1140 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001141 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001142 sys.stdout.softspace = 0
1143
1144 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001145 try:
1146 self.text.mark_gravity("iomark", "right")
1147 OutputWindow.write(self, s, tags, "iomark")
1148 self.text.mark_gravity("iomark", "left")
1149 except:
1150 pass
David Scherer7aced172000-08-15 01:13:23 +00001151 if self.canceled:
1152 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001153 if not use_subprocess:
1154 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001155
1156class PseudoFile:
1157
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001158 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001159 self.shell = shell
1160 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001161 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001162 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001163
1164 def write(self, s):
1165 self.shell.write(s, self.tags)
1166
1167 def writelines(self, l):
1168 map(self.write, l)
1169
1170 def flush(self):
1171 pass
1172
1173 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001174 return True
David Scherer7aced172000-08-15 01:13:23 +00001175
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001176
David Scherer7aced172000-08-15 01:13:23 +00001177usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001178
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001179USAGE: idle [-deins] [-t title] [file]*
1180 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1181 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001182
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001183 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001184 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001185
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001186The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001187
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001188 -e open an edit window
1189 -i open a shell window
1190
1191The following options imply -i and will open a shell:
1192
1193 -c cmd run the command in a shell, or
1194 -r file run script from file
1195
1196 -d enable the debugger
1197 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1198 -t title set title of shell window
1199
1200A default edit window will be bypassed when -c, -r, or - are used.
1201
1202[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1203
1204Examples:
1205
1206idle
1207 Open an edit window or shell depending on IDLE's configuration.
1208
1209idle foo.py foobar.py
1210 Edit the files, also open a shell if configured to start with shell.
1211
1212idle -est "Baz" foo.py
1213 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1214 window with the title "Baz".
1215
1216idle -c "import sys; print sys.argv" "foo"
1217 Open a shell window and run the command, passing "-c" in sys.argv[0]
1218 and "foo" in sys.argv[1].
1219
1220idle -d -s -r foo.py "Hello World"
1221 Open a shell window, run a startup script, enable the debugger, and
1222 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1223 sys.argv[1].
1224
1225echo "import sys; print sys.argv" | idle - "foobar"
1226 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1227 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001228"""
1229
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001230def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001231 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001232
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001233 use_subprocess = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001234 enable_shell = False
1235 enable_edit = False
1236 debug = False
1237 cmd = None
1238 script = None
1239 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001240 try:
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001241 sys.ps1
1242 except AttributeError:
1243 sys.ps1 = '>>> '
1244 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001245 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001246 except getopt.error, msg:
1247 sys.stderr.write("Error: %s\n" % str(msg))
1248 sys.stderr.write(usage_msg)
1249 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001250 for o, a in opts:
1251 if o == '-c':
1252 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001253 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001254 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001255 debug = True
1256 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001257 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001258 enable_edit = True
1259 if o == '-h':
1260 sys.stdout.write(usage_msg)
1261 sys.exit()
1262 if o == '-i':
1263 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001264 if o == '-n':
1265 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001266 if o == '-r':
1267 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001268 if os.path.isfile(script):
1269 pass
1270 else:
1271 print "No script file: ", script
1272 sys.exit()
1273 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001274 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001275 startup = True
1276 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001277 if o == '-t':
1278 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001279 enable_shell = True
1280 if args and args[0] == '-':
1281 cmd = sys.stdin.read()
1282 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001283 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001284 for i in range(len(sys.path)):
1285 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001286 if args and args[0] == '-':
1287 sys.argv = [''] + args[1:]
1288 elif cmd:
1289 sys.argv = ['-c'] + args
1290 elif script:
1291 sys.argv = [script] + args
1292 elif args:
1293 enable_edit = True
1294 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001295 for filename in args:
1296 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001297 for dir in pathx:
1298 dir = os.path.abspath(dir)
1299 if not dir in sys.path:
1300 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001301 else:
1302 dir = os.getcwd()
1303 if not dir in sys.path:
1304 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001305 # check the IDLE settings configuration (but command line overrides)
1306 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001307 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001308 enable_edit = enable_edit or edit_start
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001309 enable_shell = enable_shell or not edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001310 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001311 root = Tk(className="Idle")
1312 fixwordbreaks(root)
1313 root.withdraw()
1314 flist = PyShellFileList(root)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001315 if enable_edit:
1316 if not (cmd or script):
1317 for filename in args:
1318 flist.open(filename)
1319 if not args:
1320 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001321 if enable_shell:
1322 if not flist.open_shell():
1323 return # couldn't open shell
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001324 shell = flist.pyshell
1325 # handle remaining options:
1326 if debug:
1327 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001328 if startup:
1329 filename = os.environ.get("IDLESTARTUP") or \
1330 os.environ.get("PYTHONSTARTUP")
1331 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001332 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001333 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001334 shell.interp.runcommand("""if 1:
1335 import sys as _sys
1336 _sys.argv = %s
1337 del _sys
1338 \n""" % `sys.argv`)
1339 if cmd:
1340 shell.interp.execsource(cmd)
1341 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001342 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001343 shell.interp.execfile(script)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001344 root.mainloop()
1345 root.destroy()
1346
David Scherer7aced172000-08-15 01:13:23 +00001347if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001348 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001349 main()