PyShell.py revision 94bd77415fc44ada4ceba856a81fe029c12bf313
1#! /usr/bin/env python 2 3# changes by dscherer@cmu.edu 4 5# the main() function has been replaced by a whole class, in order to 6# address the constraint that only one process can sit on the port 7# hard-coded into the loader. 8 9# It attempts to load the RPC protocol server and publish itself. If 10# that fails, it assumes that some other copy of IDLE is already running 11# on the port and attempts to contact it. It then uses the RPC mechanism 12# to ask that copy to do whatever it was instructed (via the command 13# line) to do. (Think netscape -remote). The handling of command line 14# arguments for remotes is still very incomplete. 15 16# default behavior (no command line options) is to NOT start the Python 17# Shell. If files are specified, they are opened, otherwise a single 18# blank editor window opens. 19 20# If any command line -options are specified, a shell does appear. This 21# is necessary to make the current semantics of the options make sense. 22 23import os 24import spawn 25import sys 26import string 27import getopt 28import re 29import protocol 30import warnings 31 32import linecache 33from code import InteractiveInterpreter 34 35from Tkinter import * 36import tkMessageBox 37 38from EditorWindow import EditorWindow, fixwordbreaks 39from FileList import FileList 40from ColorDelegator import ColorDelegator 41from UndoDelegator import UndoDelegator 42from OutputWindow import OutputWindow, OnDemandOutputWindow 43from IdleConf import idleconf 44import idlever 45 46# We need to patch linecache.checkcache, because we don't want it 47# to throw away our <pyshell#...> entries. 48# Rather than repeating its code here, we save those entries, 49# then call the original function, and then restore the saved entries. 50def linecache_checkcache(orig_checkcache=linecache.checkcache): 51 cache = linecache.cache 52 save = {} 53 for filename in cache.keys(): 54 if filename[:1] + filename[-1:] == '<>': 55 save[filename] = cache[filename] 56 orig_checkcache() 57 cache.update(save) 58linecache.checkcache = linecache_checkcache 59 60 61# Note: <<newline-and-indent>> event is defined in AutoIndent.py 62 63#$ event <<plain-newline-and-indent>> 64#$ win <Control-j> 65#$ unix <Control-j> 66 67#$ event <<beginning-of-line>> 68#$ win <Control-a> 69#$ win <Home> 70#$ unix <Control-a> 71#$ unix <Home> 72 73#$ event <<history-next>> 74#$ win <Alt-n> 75#$ unix <Alt-n> 76 77#$ event <<history-previous>> 78#$ win <Alt-p> 79#$ unix <Alt-p> 80 81#$ event <<interrupt-execution>> 82#$ win <Control-c> 83#$ unix <Control-c> 84 85#$ event <<end-of-file>> 86#$ win <Control-d> 87#$ unix <Control-d> 88 89#$ event <<open-stack-viewer>> 90 91#$ event <<toggle-debugger>> 92 93 94class PyShellEditorWindow(EditorWindow): 95 96 # Regular text edit window when a shell is present 97 # XXX ought to merge with regular editor window 98 99 def __init__(self, *args): 100 apply(EditorWindow.__init__, (self,) + args) 101 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here) 102 self.text.bind("<<open-python-shell>>", self.flist.open_shell) 103 104 rmenu_specs = [ 105 ("Set breakpoint here", "<<set-breakpoint-here>>"), 106 ] 107 108 def set_breakpoint_here(self, event=None): 109 if not self.flist.pyshell or not self.flist.pyshell.interp.debugger: 110 self.text.bell() 111 return 112 self.flist.pyshell.interp.debugger.set_breakpoint_here(self) 113 114 115class PyShellFileList(FileList): 116 117 # File list when a shell is present 118 119 EditorWindow = PyShellEditorWindow 120 121 pyshell = None 122 123 def open_shell(self, event=None): 124 if self.pyshell: 125 self.pyshell.wakeup() 126 else: 127 self.pyshell = PyShell(self) 128 self.pyshell.begin() 129 return self.pyshell 130 131 132class ModifiedColorDelegator(ColorDelegator): 133 134 # Colorizer for the shell window itself 135 136 def recolorize_main(self): 137 self.tag_remove("TODO", "1.0", "iomark") 138 self.tag_add("SYNC", "1.0", "iomark") 139 ColorDelegator.recolorize_main(self) 140 141 tagdefs = ColorDelegator.tagdefs.copy() 142 cconf = idleconf.getsection('Colors') 143 144 tagdefs.update({ 145 "stdin": cconf.getcolor("stdin"), 146 "stdout": cconf.getcolor("stdout"), 147 "stderr": cconf.getcolor("stderr"), 148 "console": cconf.getcolor("console"), 149 "ERROR": cconf.getcolor("ERROR"), 150 None: cconf.getcolor("normal"), 151 }) 152 153 154class ModifiedUndoDelegator(UndoDelegator): 155 156 # Forbid insert/delete before the I/O mark 157 158 def insert(self, index, chars, tags=None): 159 try: 160 if self.delegate.compare(index, "<", "iomark"): 161 self.delegate.bell() 162 return 163 except TclError: 164 pass 165 UndoDelegator.insert(self, index, chars, tags) 166 167 def delete(self, index1, index2=None): 168 try: 169 if self.delegate.compare(index1, "<", "iomark"): 170 self.delegate.bell() 171 return 172 except TclError: 173 pass 174 UndoDelegator.delete(self, index1, index2) 175 176class ModifiedInterpreter(InteractiveInterpreter): 177 178 def __init__(self, tkconsole): 179 self.tkconsole = tkconsole 180 locals = sys.modules['__main__'].__dict__ 181 InteractiveInterpreter.__init__(self, locals=locals) 182 self.save_warnings_filters = None 183 184 gid = 0 185 186 def execsource(self, source): 187 # Like runsource() but assumes complete exec source 188 filename = self.stuffsource(source) 189 self.execfile(filename, source) 190 191 def execfile(self, filename, source=None): 192 # Execute an existing file 193 if source is None: 194 source = open(filename, "r").read() 195 try: 196 code = compile(source, filename, "exec") 197 except (OverflowError, SyntaxError): 198 self.tkconsole.resetoutput() 199 InteractiveInterpreter.showsyntaxerror(self, filename) 200 else: 201 self.runcode(code) 202 203 def runsource(self, source): 204 # Extend base class to stuff the source in the line cache first 205 filename = self.stuffsource(source) 206 self.more = 0 207 self.save_warnings_filters = warnings.filters[:] 208 warnings.filterwarnings(action="error", category=SyntaxWarning) 209 try: 210 return InteractiveInterpreter.runsource(self, source, filename) 211 finally: 212 if self.save_warnings_filters is not None: 213 warnings.filters[:] = self.save_warnings_filters 214 self.save_warnings_filters = None 215 216 def stuffsource(self, source): 217 # Stuff source in the filename cache 218 filename = "<pyshell#%d>" % self.gid 219 self.gid = self.gid + 1 220 lines = string.split(source, "\n") 221 linecache.cache[filename] = len(source)+1, 0, lines, filename 222 return filename 223 224 def showsyntaxerror(self, filename=None): 225 # Extend base class to color the offending position 226 # (instead of printing it and pointing at it with a caret) 227 text = self.tkconsole.text 228 stuff = self.unpackerror() 229 if not stuff: 230 self.tkconsole.resetoutput() 231 InteractiveInterpreter.showsyntaxerror(self, filename) 232 return 233 msg, lineno, offset, line = stuff 234 if lineno == 1: 235 pos = "iomark + %d chars" % (offset-1) 236 else: 237 pos = "iomark linestart + %d lines + %d chars" % (lineno-1, 238 offset-1) 239 text.tag_add("ERROR", pos) 240 text.see(pos) 241 char = text.get(pos) 242 if char and char in string.letters + string.digits + "_": 243 text.tag_add("ERROR", pos + " wordstart", pos) 244 self.tkconsole.resetoutput() 245 self.write("SyntaxError: %s\n" % str(msg)) 246 247 def unpackerror(self): 248 type, value, tb = sys.exc_info() 249 ok = type is SyntaxError 250 if ok: 251 try: 252 msg, (dummy_filename, lineno, offset, line) = value 253 except: 254 ok = 0 255 if ok: 256 return msg, lineno, offset, line 257 else: 258 return None 259 260 def showtraceback(self): 261 # Extend base class method to reset output properly 262 text = self.tkconsole.text 263 self.tkconsole.resetoutput() 264 self.checklinecache() 265 InteractiveInterpreter.showtraceback(self) 266 267 def checklinecache(self): 268 c = linecache.cache 269 for key in c.keys(): 270 if key[:1] + key[-1:] != "<>": 271 del c[key] 272 273 debugger = None 274 275 def setdebugger(self, debugger): 276 self.debugger = debugger 277 278 def getdebugger(self): 279 return self.debugger 280 281 def runcode(self, code): 282 # Override base class method 283 if self.save_warnings_filters is not None: 284 warnings.filters[:] = self.save_warnings_filters 285 self.save_warnings_filters = None 286 debugger = self.debugger 287 try: 288 self.tkconsole.beginexecuting() 289 try: 290 if debugger: 291 debugger.run(code, self.locals) 292 else: 293 exec code in self.locals 294 except SystemExit: 295 if tkMessageBox.askyesno( 296 "Exit?", 297 "Do you want to exit altogether?", 298 default="yes", 299 master=self.tkconsole.text): 300 raise 301 else: 302 self.showtraceback() 303 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"): 304 self.tkconsole.open_stack_viewer() 305 except: 306 self.showtraceback() 307 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"): 308 self.tkconsole.open_stack_viewer() 309 310 finally: 311 self.tkconsole.endexecuting() 312 313 def write(self, s): 314 # Override base class write 315 self.tkconsole.console.write(s) 316 317 318class PyShell(OutputWindow): 319 320 shell_title = "Python Shell" 321 322 # Override classes 323 ColorDelegator = ModifiedColorDelegator 324 UndoDelegator = ModifiedUndoDelegator 325 326 # Override menu bar specs 327 menu_specs = PyShellEditorWindow.menu_specs[:] 328 menu_specs.insert(len(menu_specs)-2, ("debug", "_Debug")) 329 330 # New classes 331 from IdleHistory import History 332 333 def __init__(self, flist=None): 334 self.interp = ModifiedInterpreter(self) 335 if flist is None: 336 root = Tk() 337 fixwordbreaks(root) 338 root.withdraw() 339 flist = PyShellFileList(root) 340 341 OutputWindow.__init__(self, flist, None, None) 342 343 import __builtin__ 344 __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D." 345 346 self.auto = self.extensions["AutoIndent"] # Required extension 347 self.auto.config(usetabs=1, indentwidth=8, context_use_ps1=1) 348 349 text = self.text 350 text.configure(wrap="char") 351 text.bind("<<newline-and-indent>>", self.enter_callback) 352 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback) 353 text.bind("<<interrupt-execution>>", self.cancel_callback) 354 text.bind("<<beginning-of-line>>", self.home_callback) 355 text.bind("<<end-of-file>>", self.eof_callback) 356 text.bind("<<open-stack-viewer>>", self.open_stack_viewer) 357 text.bind("<<toggle-debugger>>", self.toggle_debugger) 358 text.bind("<<open-python-shell>>", self.flist.open_shell) 359 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer) 360 361 self.save_stdout = sys.stdout 362 self.save_stderr = sys.stderr 363 self.save_stdin = sys.stdin 364 sys.stdout = PseudoFile(self, "stdout") 365 sys.stderr = PseudoFile(self, "stderr") 366 sys.stdin = self 367 self.console = PseudoFile(self, "console") 368 369 self.history = self.History(self.text) 370 371 reading = 0 372 executing = 0 373 canceled = 0 374 endoffile = 0 375 376 def toggle_debugger(self, event=None): 377 if self.executing: 378 tkMessageBox.showerror("Don't debug now", 379 "You can only toggle the debugger when idle", 380 master=self.text) 381 self.set_debugger_indicator() 382 return "break" 383 else: 384 db = self.interp.getdebugger() 385 if db: 386 self.close_debugger() 387 else: 388 self.open_debugger() 389 390 def set_debugger_indicator(self): 391 db = self.interp.getdebugger() 392 self.setvar("<<toggle-debugger>>", not not db) 393 394 def toggle_jit_stack_viewer( self, event=None): 395 pass # All we need is the variable 396 397 def close_debugger(self): 398 db = self.interp.getdebugger() 399 if db: 400 self.interp.setdebugger(None) 401 db.close() 402 self.resetoutput() 403 self.console.write("[DEBUG OFF]\n") 404 sys.ps1 = ">>> " 405 self.showprompt() 406 self.set_debugger_indicator() 407 408 def open_debugger(self): 409 import Debugger 410 self.interp.setdebugger(Debugger.Debugger(self)) 411 sys.ps1 = "[DEBUG ON]\n>>> " 412 self.showprompt() 413 self.set_debugger_indicator() 414 415 def beginexecuting(self): 416 # Helper for ModifiedInterpreter 417 self.resetoutput() 418 self.executing = 1 419 ##self._cancel_check = self.cancel_check 420 ##sys.settrace(self._cancel_check) 421 422 def endexecuting(self): 423 # Helper for ModifiedInterpreter 424 ##sys.settrace(None) 425 ##self._cancel_check = None 426 self.executing = 0 427 self.canceled = 0 428 429 def close(self): 430 # Extend base class method 431 if self.executing: 432 # XXX Need to ask a question here 433 if not tkMessageBox.askokcancel( 434 "Kill?", 435 "The program is still running; do you want to kill it?", 436 default="ok", 437 master=self.text): 438 return "cancel" 439 self.canceled = 1 440 if self.reading: 441 self.top.quit() 442 return "cancel" 443 return PyShellEditorWindow.close(self) 444 445 def _close(self): 446 self.close_debugger() 447 # Restore std streams 448 sys.stdout = self.save_stdout 449 sys.stderr = self.save_stderr 450 sys.stdin = self.save_stdin 451 # Break cycles 452 self.interp = None 453 self.console = None 454 self.auto = None 455 self.flist.pyshell = None 456 self.history = None 457 OutputWindow._close(self) # Really EditorWindow._close 458 459 def ispythonsource(self, filename): 460 # Override this so EditorWindow never removes the colorizer 461 return 1 462 463 def short_title(self): 464 return self.shell_title 465 466 COPYRIGHT = \ 467 'Type "copyright", "credits" or "license" for more information.' 468 469 def begin(self): 470 self.resetoutput() 471 self.write("Python %s on %s\n%s\nIDLE %s -- press F1 for help\n" % 472 (sys.version, sys.platform, self.COPYRIGHT, 473 idlever.IDLE_VERSION)) 474 try: 475 sys.ps1 476 except AttributeError: 477 sys.ps1 = ">>> " 478 self.showprompt() 479 import Tkinter 480 Tkinter._default_root = None 481 482 def interact(self): 483 self.begin() 484 self.top.mainloop() 485 486 def readline(self): 487 save = self.reading 488 try: 489 self.reading = 1 490 self.top.mainloop() 491 finally: 492 self.reading = save 493 line = self.text.get("iomark", "end-1c") 494 self.resetoutput() 495 if self.canceled: 496 self.canceled = 0 497 raise KeyboardInterrupt 498 if self.endoffile: 499 self.endoffile = 0 500 return "" 501 return line 502 503 def isatty(self): 504 return 1 505 506 def cancel_callback(self, event): 507 try: 508 if self.text.compare("sel.first", "!=", "sel.last"): 509 return # Active selection -- always use default binding 510 except: 511 pass 512 if not (self.executing or self.reading): 513 self.resetoutput() 514 self.write("KeyboardInterrupt\n") 515 self.showprompt() 516 return "break" 517 self.endoffile = 0 518 self.canceled = 1 519 if self.reading: 520 self.top.quit() 521 return "break" 522 523 def eof_callback(self, event): 524 if self.executing and not self.reading: 525 return # Let the default binding (delete next char) take over 526 if not (self.text.compare("iomark", "==", "insert") and 527 self.text.compare("insert", "==", "end-1c")): 528 return # Let the default binding (delete next char) take over 529 if not self.executing: 530## if not tkMessageBox.askokcancel( 531## "Exit?", 532## "Are you sure you want to exit?", 533## default="ok", master=self.text): 534## return "break" 535 self.resetoutput() 536 self.close() 537 else: 538 self.canceled = 0 539 self.endoffile = 1 540 self.top.quit() 541 return "break" 542 543 def home_callback(self, event): 544 if event.state != 0 and event.keysym == "Home": 545 return # <Modifier-Home>; fall back to class binding 546 if self.text.compare("iomark", "<=", "insert") and \ 547 self.text.compare("insert linestart", "<=", "iomark"): 548 self.text.mark_set("insert", "iomark") 549 self.text.tag_remove("sel", "1.0", "end") 550 self.text.see("insert") 551 return "break" 552 553 def linefeed_callback(self, event): 554 # Insert a linefeed without entering anything (still autoindented) 555 if self.reading: 556 self.text.insert("insert", "\n") 557 self.text.see("insert") 558 else: 559 self.auto.auto_indent(event) 560 return "break" 561 562 def enter_callback(self, event): 563 if self.executing and not self.reading: 564 return # Let the default binding (insert '\n') take over 565 # If some text is selected, recall the selection 566 # (but only if this before the I/O mark) 567 try: 568 sel = self.text.get("sel.first", "sel.last") 569 if sel: 570 if self.text.compare("sel.last", "<=", "iomark"): 571 self.recall(sel) 572 return "break" 573 except: 574 pass 575 # If we're strictly before the line containing iomark, recall 576 # the current line, less a leading prompt, less leading or 577 # trailing whitespace 578 if self.text.compare("insert", "<", "iomark linestart"): 579 # Check if there's a relevant stdin range -- if so, use it 580 prev = self.text.tag_prevrange("stdin", "insert") 581 if prev and self.text.compare("insert", "<", prev[1]): 582 self.recall(self.text.get(prev[0], prev[1])) 583 return "break" 584 next = self.text.tag_nextrange("stdin", "insert") 585 if next and self.text.compare("insert lineend", ">=", next[0]): 586 self.recall(self.text.get(next[0], next[1])) 587 return "break" 588 # No stdin mark -- just get the current line 589 self.recall(self.text.get("insert linestart", "insert lineend")) 590 return "break" 591 # If we're in the current input and there's only whitespace 592 # beyond the cursor, erase that whitespace first 593 s = self.text.get("insert", "end-1c") 594 if s and not string.strip(s): 595 self.text.delete("insert", "end-1c") 596 # If we're in the current input before its last line, 597 # insert a newline right at the insert point 598 if self.text.compare("insert", "<", "end-1c linestart"): 599 self.auto.auto_indent(event) 600 return "break" 601 # We're in the last line; append a newline and submit it 602 self.text.mark_set("insert", "end-1c") 603 if self.reading: 604 self.text.insert("insert", "\n") 605 self.text.see("insert") 606 else: 607 self.auto.auto_indent(event) 608 self.text.tag_add("stdin", "iomark", "end-1c") 609 self.text.update_idletasks() 610 if self.reading: 611 self.top.quit() # Break out of recursive mainloop() in raw_input() 612 else: 613 self.runit() 614 return "break" 615 616 def recall(self, s): 617 if self.history: 618 self.history.recall(s) 619 620 def runit(self): 621 line = self.text.get("iomark", "end-1c") 622 # Strip off last newline and surrounding whitespace. 623 # (To allow you to hit return twice to end a statement.) 624 i = len(line) 625 while i > 0 and line[i-1] in " \t": 626 i = i-1 627 if i > 0 and line[i-1] == "\n": 628 i = i-1 629 while i > 0 and line[i-1] in " \t": 630 i = i-1 631 line = line[:i] 632 more = self.interp.runsource(line) 633 if not more: 634 self.showprompt() 635 636 def cancel_check(self, frame, what, args, 637 dooneevent=tkinter.dooneevent, 638 dontwait=tkinter.DONT_WAIT): 639 # Hack -- use the debugger hooks to be able to handle events 640 # and interrupt execution at any time. 641 # This slows execution down quite a bit, so you may want to 642 # disable this (by not calling settrace() in runcode() above) 643 # for full-bore (uninterruptable) speed. 644 # XXX This should become a user option. 645 if self.canceled: 646 return 647 dooneevent(dontwait) 648 if self.canceled: 649 self.canceled = 0 650 raise KeyboardInterrupt 651 return self._cancel_check 652 653 def open_stack_viewer(self, event=None): 654 try: 655 sys.last_traceback 656 except: 657 tkMessageBox.showerror("No stack trace", 658 "There is no stack trace yet.\n" 659 "(sys.last_traceback is not defined)", 660 master=self.text) 661 return 662 from StackViewer import StackBrowser 663 sv = StackBrowser(self.root, self.flist) 664 665 def showprompt(self): 666 self.resetoutput() 667 try: 668 s = str(sys.ps1) 669 except: 670 s = "" 671 self.console.write(s) 672 self.text.mark_set("insert", "end-1c") 673 674 def resetoutput(self): 675 source = self.text.get("iomark", "end-1c") 676 if self.history: 677 self.history.history_store(source) 678 if self.text.get("end-2c") != "\n": 679 self.text.insert("end-1c", "\n") 680 self.text.mark_set("iomark", "end-1c") 681 sys.stdout.softspace = 0 682 683 def write(self, s, tags=()): 684 self.text.mark_gravity("iomark", "right") 685 OutputWindow.write(self, s, tags, "iomark") 686 self.text.mark_gravity("iomark", "left") 687 if self.canceled: 688 self.canceled = 0 689 raise KeyboardInterrupt 690 691class PseudoFile: 692 693 def __init__(self, shell, tags): 694 self.shell = shell 695 self.tags = tags 696 697 def write(self, s): 698 self.shell.write(s, self.tags) 699 700 def writelines(self, l): 701 map(self.write, l) 702 703 def flush(self): 704 pass 705 706 def isatty(self): 707 return 1 708 709usage_msg = """\ 710usage: idle.py [-c command] [-d] [-e] [-s] [-t title] [arg] ... 711 712-c command run this command 713-d enable debugger 714-e edit mode; arguments are files to be edited 715-s run $IDLESTARTUP or $PYTHONSTARTUP before anything else 716-t title set title of shell window 717 718When neither -c nor -e is used, and there are arguments, and the first 719argument is not '-', the first argument is run as a script. Remaining 720arguments are arguments to the script or to the command run by -c. 721""" 722 723class usageError: 724 def __init__(self, string): self.string = string 725 def __repr__(self): return self.string 726 727class main: 728 def __init__(self): 729 try: 730 self.server = protocol.Server(connection_hook = self.address_ok) 731 protocol.publish( 'IDLE', self.connect ) 732 self.main( sys.argv[1:] ) 733 return 734 except protocol.connectionLost: 735 try: 736 client = protocol.Client() 737 IDLE = client.getobject('IDLE') 738 if IDLE: 739 try: 740 IDLE.remote( sys.argv[1:] ) 741 except usageError, msg: 742 sys.stderr.write("Error: %s\n" % str(msg)) 743 sys.stderr.write(usage_msg) 744 return 745 except protocol.connectionLost: 746 pass 747 748 # xxx Should scream via Tk() 749 print "Something already has our socket, but it won't open a window for me!" 750 print "Unable to proceed." 751 752 def idle(self): 753 spawn.kill_zombies() 754 self.server.rpc_loop() 755 root.after(25, self.idle) 756 757 # We permit connections from localhost only 758 def address_ok(self, addr): 759 return addr[0] == '127.0.0.1' 760 761 def connect(self, client, addr): 762 return self 763 764 def remote( self, argv ): 765 # xxx Should make this behavior match the behavior in main, or redo 766 # command line options entirely. 767 768 try: 769 opts, args = getopt.getopt(argv, "c:deist:") 770 except getopt.error, msg: 771 raise usageError(msg) 772 773 for filename in args: 774 flist.open(filename) 775 if not args: 776 flist.new() 777 778 def main( self, argv ): 779 cmd = None 780 edit = 0 781 noshell = 1 782 783 debug = 0 784 startup = 0 785 786 try: 787 opts, args = getopt.getopt(argv, "c:deist:") 788 except getopt.error, msg: 789 sys.stderr.write("Error: %s\n" % str(msg)) 790 sys.stderr.write(usage_msg) 791 sys.exit(2) 792 793 for o, a in opts: 794 noshell = 0 795 if o == '-c': 796 cmd = a 797 if o == '-d': 798 debug = 1 799 if o == '-e': 800 edit = 1 801 if o == '-s': 802 startup = 1 803 if o == '-t': 804 PyShell.shell_title = a 805 806 if noshell: edit=1 807 808 for i in range(len(sys.path)): 809 sys.path[i] = os.path.abspath(sys.path[i]) 810 811 pathx = [] 812 if edit: 813 for filename in args: 814 pathx.append(os.path.dirname(filename)) 815 elif args and args[0] != "-": 816 pathx.append(os.path.dirname(args[0])) 817 else: 818 pathx.append(os.curdir) 819 for dir in pathx: 820 dir = os.path.abspath(dir) 821 if not dir in sys.path: 822 sys.path.insert(0, dir) 823 824 global flist, root 825 root = Tk(className="Idle") 826 fixwordbreaks(root) 827 root.withdraw() 828 flist = PyShellFileList(root) 829 830 if edit: 831 for filename in args: 832 flist.open(filename) 833 if not args: 834 flist.new() 835 else: 836 if cmd: 837 sys.argv = ["-c"] + args 838 else: 839 sys.argv = args or [""] 840 841 #dbg=OnDemandOutputWindow(flist) 842 #dbg.set_title('Internal IDLE Problem') 843 #sys.stdout = PseudoFile(dbg,['stdout']) 844 #sys.stderr = PseudoFile(dbg,['stderr']) 845 846 if noshell: 847 flist.pyshell = None 848 else: 849 shell = PyShell(flist) 850 interp = shell.interp 851 flist.pyshell = shell 852 853 if startup: 854 filename = os.environ.get("IDLESTARTUP") or \ 855 os.environ.get("PYTHONSTARTUP") 856 if filename and os.path.isfile(filename): 857 interp.execfile(filename) 858 859 if debug: 860 shell.open_debugger() 861 if cmd: 862 interp.execsource(cmd) 863 elif not edit and args and args[0] != "-": 864 interp.execfile(args[0]) 865 866 shell.begin() 867 868 self.idle() 869 root.mainloop() 870 root.destroy() 871 872 873if __name__ == "__main__": 874 main() 875