PageRenderTime 369ms CodeModel.GetById 101ms app.highlight 210ms RepoModel.GetById 41ms app.codeStats 1ms

/lib-python/2/idlelib/PyShell.py

https://bitbucket.org/kcr/pypy
Python | 1464 lines | 1343 code | 54 blank | 67 comment | 70 complexity | 0a1434b2023859f5893cb70345bbd707 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1#! /usr/bin/env python
   2
   3import os
   4import os.path
   5import sys
   6import string
   7import getopt
   8import re
   9import socket
  10import time
  11import threading
  12import traceback
  13import types
  14
  15import linecache
  16from code import InteractiveInterpreter
  17
  18try:
  19    from Tkinter import *
  20except ImportError:
  21    print>>sys.__stderr__, "** IDLE can't import Tkinter.  " \
  22                           "Your Python may not be configured for Tk. **"
  23    sys.exit(1)
  24import tkMessageBox
  25
  26from idlelib.EditorWindow import EditorWindow, fixwordbreaks
  27from idlelib.FileList import FileList
  28from idlelib.ColorDelegator import ColorDelegator
  29from idlelib.UndoDelegator import UndoDelegator
  30from idlelib.OutputWindow import OutputWindow
  31from idlelib.configHandler import idleConf
  32from idlelib import idlever
  33from idlelib import rpc
  34from idlelib import Debugger
  35from idlelib import RemoteDebugger
  36from idlelib import macosxSupport
  37
  38IDENTCHARS = string.ascii_letters + string.digits + "_"
  39HOST = '127.0.0.1' # python execution server on localhost loopback
  40PORT = 0  # someday pass in host, port for remote debug capability
  41
  42try:
  43    from signal import SIGTERM
  44except ImportError:
  45    SIGTERM = 15
  46
  47# Override warnings module to write to warning_stream.  Initialize to send IDLE
  48# internal warnings to the console.  ScriptBinding.check_syntax() will
  49# temporarily redirect the stream to the shell window to display warnings when
  50# checking user's code.
  51global warning_stream
  52warning_stream = sys.__stderr__
  53try:
  54    import warnings
  55except ImportError:
  56    pass
  57else:
  58    def idle_showwarning(message, category, filename, lineno,
  59                         file=None, line=None):
  60        if file is None:
  61            file = warning_stream
  62        try:
  63            file.write(warnings.formatwarning(message, category, filename,
  64                                              lineno, line=line))
  65        except IOError:
  66            pass  ## file (probably __stderr__) is invalid, warning dropped.
  67    warnings.showwarning = idle_showwarning
  68    def idle_formatwarning(message, category, filename, lineno, line=None):
  69        """Format warnings the IDLE way"""
  70        s = "\nWarning (from warnings module):\n"
  71        s += '  File \"%s\", line %s\n' % (filename, lineno)
  72        if line is None:
  73            line = linecache.getline(filename, lineno)
  74        line = line.strip()
  75        if line:
  76            s += "    %s\n" % line
  77        s += "%s: %s\n>>> " % (category.__name__, message)
  78        return s
  79    warnings.formatwarning = idle_formatwarning
  80
  81def extended_linecache_checkcache(filename=None,
  82                                  orig_checkcache=linecache.checkcache):
  83    """Extend linecache.checkcache to preserve the <pyshell#...> entries
  84
  85    Rather than repeating the linecache code, patch it to save the
  86    <pyshell#...> entries, call the original linecache.checkcache()
  87    (skipping them), and then restore the saved entries.
  88
  89    orig_checkcache is bound at definition time to the original
  90    method, allowing it to be patched.
  91    """
  92    cache = linecache.cache
  93    save = {}
  94    for key in list(cache):
  95        if key[:1] + key[-1:] == '<>':
  96            save[key] = cache.pop(key)
  97    orig_checkcache(filename)
  98    cache.update(save)
  99
 100# Patch linecache.checkcache():
 101linecache.checkcache = extended_linecache_checkcache
 102
 103
 104class PyShellEditorWindow(EditorWindow):
 105    "Regular text edit window in IDLE, supports breakpoints"
 106
 107    def __init__(self, *args):
 108        self.breakpoints = []
 109        EditorWindow.__init__(self, *args)
 110        self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
 111        self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
 112        self.text.bind("<<open-python-shell>>", self.flist.open_shell)
 113
 114        self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
 115                                           'breakpoints.lst')
 116        # whenever a file is changed, restore breakpoints
 117        if self.io.filename: self.restore_file_breaks()
 118        def filename_changed_hook(old_hook=self.io.filename_change_hook,
 119                                  self=self):
 120            self.restore_file_breaks()
 121            old_hook()
 122        self.io.set_filename_change_hook(filename_changed_hook)
 123
 124    rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
 125                   ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
 126
 127    def set_breakpoint(self, lineno):
 128        text = self.text
 129        filename = self.io.filename
 130        text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
 131        try:
 132            i = self.breakpoints.index(lineno)
 133        except ValueError:  # only add if missing, i.e. do once
 134            self.breakpoints.append(lineno)
 135        try:    # update the subprocess debugger
 136            debug = self.flist.pyshell.interp.debugger
 137            debug.set_breakpoint_here(filename, lineno)
 138        except: # but debugger may not be active right now....
 139            pass
 140
 141    def set_breakpoint_here(self, event=None):
 142        text = self.text
 143        filename = self.io.filename
 144        if not filename:
 145            text.bell()
 146            return
 147        lineno = int(float(text.index("insert")))
 148        self.set_breakpoint(lineno)
 149
 150    def clear_breakpoint_here(self, event=None):
 151        text = self.text
 152        filename = self.io.filename
 153        if not filename:
 154            text.bell()
 155            return
 156        lineno = int(float(text.index("insert")))
 157        try:
 158            self.breakpoints.remove(lineno)
 159        except:
 160            pass
 161        text.tag_remove("BREAK", "insert linestart",\
 162                        "insert lineend +1char")
 163        try:
 164            debug = self.flist.pyshell.interp.debugger
 165            debug.clear_breakpoint_here(filename, lineno)
 166        except:
 167            pass
 168
 169    def clear_file_breaks(self):
 170        if self.breakpoints:
 171            text = self.text
 172            filename = self.io.filename
 173            if not filename:
 174                text.bell()
 175                return
 176            self.breakpoints = []
 177            text.tag_remove("BREAK", "1.0", END)
 178            try:
 179                debug = self.flist.pyshell.interp.debugger
 180                debug.clear_file_breaks(filename)
 181            except:
 182                pass
 183
 184    def store_file_breaks(self):
 185        "Save breakpoints when file is saved"
 186        # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
 187        #     be run.  The breaks are saved at that time.  If we introduce
 188        #     a temporary file save feature the save breaks functionality
 189        #     needs to be re-verified, since the breaks at the time the
 190        #     temp file is created may differ from the breaks at the last
 191        #     permanent save of the file.  Currently, a break introduced
 192        #     after a save will be effective, but not persistent.
 193        #     This is necessary to keep the saved breaks synched with the
 194        #     saved file.
 195        #
 196        #     Breakpoints are set as tagged ranges in the text.  Certain
 197        #     kinds of edits cause these ranges to be deleted: Inserting
 198        #     or deleting a line just before a breakpoint, and certain
 199        #     deletions prior to a breakpoint.  These issues need to be
 200        #     investigated and understood.  It's not clear if they are
 201        #     Tk issues or IDLE issues, or whether they can actually
 202        #     be fixed.  Since a modified file has to be saved before it is
 203        #     run, and since self.breakpoints (from which the subprocess
 204        #     debugger is loaded) is updated during the save, the visible
 205        #     breaks stay synched with the subprocess even if one of these
 206        #     unexpected breakpoint deletions occurs.
 207        breaks = self.breakpoints
 208        filename = self.io.filename
 209        try:
 210            with open(self.breakpointPath,"r") as old_file:
 211                lines = old_file.readlines()
 212        except IOError:
 213            lines = []
 214        try:
 215            with open(self.breakpointPath,"w") as new_file:
 216                for line in lines:
 217                    if not line.startswith(filename + '='):
 218                        new_file.write(line)
 219                self.update_breakpoints()
 220                breaks = self.breakpoints
 221                if breaks:
 222                    new_file.write(filename + '=' + str(breaks) + '\n')
 223        except IOError as err:
 224            if not getattr(self.root, "breakpoint_error_displayed", False):
 225                self.root.breakpoint_error_displayed = True
 226                tkMessageBox.showerror(title='IDLE Error',
 227                    message='Unable to update breakpoint list:\n%s'
 228                        % str(err),
 229                    parent=self.text)
 230
 231    def restore_file_breaks(self):
 232        self.text.update()   # this enables setting "BREAK" tags to be visible
 233        filename = self.io.filename
 234        if filename is None:
 235            return
 236        if os.path.isfile(self.breakpointPath):
 237            lines = open(self.breakpointPath,"r").readlines()
 238            for line in lines:
 239                if line.startswith(filename + '='):
 240                    breakpoint_linenumbers = eval(line[len(filename)+1:])
 241                    for breakpoint_linenumber in breakpoint_linenumbers:
 242                        self.set_breakpoint(breakpoint_linenumber)
 243
 244    def update_breakpoints(self):
 245        "Retrieves all the breakpoints in the current window"
 246        text = self.text
 247        ranges = text.tag_ranges("BREAK")
 248        linenumber_list = self.ranges_to_linenumbers(ranges)
 249        self.breakpoints = linenumber_list
 250
 251    def ranges_to_linenumbers(self, ranges):
 252        lines = []
 253        for index in range(0, len(ranges), 2):
 254            lineno = int(float(ranges[index]))
 255            end = int(float(ranges[index+1]))
 256            while lineno < end:
 257                lines.append(lineno)
 258                lineno += 1
 259        return lines
 260
 261# XXX 13 Dec 2002 KBK Not used currently
 262#    def saved_change_hook(self):
 263#        "Extend base method - clear breaks if module is modified"
 264#        if not self.get_saved():
 265#            self.clear_file_breaks()
 266#        EditorWindow.saved_change_hook(self)
 267
 268    def _close(self):
 269        "Extend base method - clear breaks when module is closed"
 270        self.clear_file_breaks()
 271        EditorWindow._close(self)
 272
 273
 274class PyShellFileList(FileList):
 275    "Extend base class: IDLE supports a shell and breakpoints"
 276
 277    # override FileList's class variable, instances return PyShellEditorWindow
 278    # instead of EditorWindow when new edit windows are created.
 279    EditorWindow = PyShellEditorWindow
 280
 281    pyshell = None
 282
 283    def open_shell(self, event=None):
 284        if self.pyshell:
 285            self.pyshell.top.wakeup()
 286        else:
 287            self.pyshell = PyShell(self)
 288            if self.pyshell:
 289                if not self.pyshell.begin():
 290                    return None
 291        return self.pyshell
 292
 293
 294class ModifiedColorDelegator(ColorDelegator):
 295    "Extend base class: colorizer for the shell window itself"
 296
 297    def __init__(self):
 298        ColorDelegator.__init__(self)
 299        self.LoadTagDefs()
 300
 301    def recolorize_main(self):
 302        self.tag_remove("TODO", "1.0", "iomark")
 303        self.tag_add("SYNC", "1.0", "iomark")
 304        ColorDelegator.recolorize_main(self)
 305
 306    def LoadTagDefs(self):
 307        ColorDelegator.LoadTagDefs(self)
 308        theme = idleConf.GetOption('main','Theme','name')
 309        self.tagdefs.update({
 310            "stdin": {'background':None,'foreground':None},
 311            "stdout": idleConf.GetHighlight(theme, "stdout"),
 312            "stderr": idleConf.GetHighlight(theme, "stderr"),
 313            "console": idleConf.GetHighlight(theme, "console"),
 314        })
 315
 316class ModifiedUndoDelegator(UndoDelegator):
 317    "Extend base class: forbid insert/delete before the I/O mark"
 318
 319    def insert(self, index, chars, tags=None):
 320        try:
 321            if self.delegate.compare(index, "<", "iomark"):
 322                self.delegate.bell()
 323                return
 324        except TclError:
 325            pass
 326        UndoDelegator.insert(self, index, chars, tags)
 327
 328    def delete(self, index1, index2=None):
 329        try:
 330            if self.delegate.compare(index1, "<", "iomark"):
 331                self.delegate.bell()
 332                return
 333        except TclError:
 334            pass
 335        UndoDelegator.delete(self, index1, index2)
 336
 337
 338class MyRPCClient(rpc.RPCClient):
 339
 340    def handle_EOF(self):
 341        "Override the base class - just re-raise EOFError"
 342        raise EOFError
 343
 344
 345class ModifiedInterpreter(InteractiveInterpreter):
 346
 347    def __init__(self, tkconsole):
 348        self.tkconsole = tkconsole
 349        locals = sys.modules['__main__'].__dict__
 350        InteractiveInterpreter.__init__(self, locals=locals)
 351        self.save_warnings_filters = None
 352        self.restarting = False
 353        self.subprocess_arglist = None
 354        self.port = PORT
 355        self.original_compiler_flags = self.compile.compiler.flags
 356
 357    rpcclt = None
 358    rpcpid = None
 359
 360    def spawn_subprocess(self):
 361        if self.subprocess_arglist is None:
 362            self.subprocess_arglist = self.build_subprocess_arglist()
 363        args = self.subprocess_arglist
 364        self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
 365
 366    def build_subprocess_arglist(self):
 367        assert (self.port!=0), (
 368            "Socket should have been assigned a port number.")
 369        w = ['-W' + s for s in sys.warnoptions]
 370        if 1/2 > 0: # account for new division
 371            w.append('-Qnew')
 372        # Maybe IDLE is installed and is being accessed via sys.path,
 373        # or maybe it's not installed and the idle.py script is being
 374        # run from the IDLE source directory.
 375        del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
 376                                       default=False, type='bool')
 377        if __name__ == 'idlelib.PyShell':
 378            command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
 379        else:
 380            command = "__import__('run').main(%r)" % (del_exitf,)
 381        if sys.platform[:3] == 'win' and ' ' in sys.executable:
 382            # handle embedded space in path by quoting the argument
 383            decorated_exec = '"%s"' % sys.executable
 384        else:
 385            decorated_exec = sys.executable
 386        return [decorated_exec] + w + ["-c", command, str(self.port)]
 387
 388    def start_subprocess(self):
 389        addr = (HOST, self.port)
 390        # GUI makes several attempts to acquire socket, listens for connection
 391        for i in range(3):
 392            time.sleep(i)
 393            try:
 394                self.rpcclt = MyRPCClient(addr)
 395                break
 396            except socket.error, err:
 397                pass
 398        else:
 399            self.display_port_binding_error()
 400            return None
 401        # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
 402        self.port = self.rpcclt.listening_sock.getsockname()[1]
 403        # if PORT was not 0, probably working with a remote execution server
 404        if PORT != 0:
 405            # To allow reconnection within the 2MSL wait (cf. Stevens TCP
 406            # V1, 18.6),  set SO_REUSEADDR.  Note that this can be problematic
 407            # on Windows since the implementation allows two active sockets on
 408            # the same address!
 409            self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
 410                                           socket.SO_REUSEADDR, 1)
 411        self.spawn_subprocess()
 412        #time.sleep(20) # test to simulate GUI not accepting connection
 413        # Accept the connection from the Python execution server
 414        self.rpcclt.listening_sock.settimeout(10)
 415        try:
 416            self.rpcclt.accept()
 417        except socket.timeout, err:
 418            self.display_no_subprocess_error()
 419            return None
 420        self.rpcclt.register("stdin", self.tkconsole)
 421        self.rpcclt.register("stdout", self.tkconsole.stdout)
 422        self.rpcclt.register("stderr", self.tkconsole.stderr)
 423        self.rpcclt.register("flist", self.tkconsole.flist)
 424        self.rpcclt.register("linecache", linecache)
 425        self.rpcclt.register("interp", self)
 426        self.transfer_path(with_cwd=True)
 427        self.poll_subprocess()
 428        return self.rpcclt
 429
 430    def restart_subprocess(self, with_cwd=False):
 431        if self.restarting:
 432            return self.rpcclt
 433        self.restarting = True
 434        # close only the subprocess debugger
 435        debug = self.getdebugger()
 436        if debug:
 437            try:
 438                # Only close subprocess debugger, don't unregister gui_adap!
 439                RemoteDebugger.close_subprocess_debugger(self.rpcclt)
 440            except:
 441                pass
 442        # Kill subprocess, spawn a new one, accept connection.
 443        self.rpcclt.close()
 444        self.unix_terminate()
 445        console = self.tkconsole
 446        was_executing = console.executing
 447        console.executing = False
 448        self.spawn_subprocess()
 449        try:
 450            self.rpcclt.accept()
 451        except socket.timeout, err:
 452            self.display_no_subprocess_error()
 453            return None
 454        self.transfer_path(with_cwd=with_cwd)
 455        # annotate restart in shell window and mark it
 456        console.text.delete("iomark", "end-1c")
 457        if was_executing:
 458            console.write('\n')
 459            console.showprompt()
 460        halfbar = ((int(console.width) - 16) // 2) * '='
 461        console.write(halfbar + ' RESTART ' + halfbar)
 462        console.text.mark_set("restart", "end-1c")
 463        console.text.mark_gravity("restart", "left")
 464        console.showprompt()
 465        # restart subprocess debugger
 466        if debug:
 467            # Restarted debugger connects to current instance of debug GUI
 468            gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
 469            # reload remote debugger breakpoints for all PyShellEditWindows
 470            debug.load_breakpoints()
 471        self.compile.compiler.flags = self.original_compiler_flags
 472        self.restarting = False
 473        return self.rpcclt
 474
 475    def __request_interrupt(self):
 476        self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
 477
 478    def interrupt_subprocess(self):
 479        threading.Thread(target=self.__request_interrupt).start()
 480
 481    def kill_subprocess(self):
 482        try:
 483            self.rpcclt.close()
 484        except AttributeError:  # no socket
 485            pass
 486        self.unix_terminate()
 487        self.tkconsole.executing = False
 488        self.rpcclt = None
 489
 490    def unix_terminate(self):
 491        "UNIX: make sure subprocess is terminated and collect status"
 492        if hasattr(os, 'kill'):
 493            try:
 494                os.kill(self.rpcpid, SIGTERM)
 495            except OSError:
 496                # process already terminated:
 497                return
 498            else:
 499                try:
 500                    os.waitpid(self.rpcpid, 0)
 501                except OSError:
 502                    return
 503
 504    def transfer_path(self, with_cwd=False):
 505        if with_cwd:        # Issue 13506
 506            path = ['']     # include Current Working Directory
 507            path.extend(sys.path)
 508        else:
 509            path = sys.path
 510
 511        self.runcommand("""if 1:
 512        import sys as _sys
 513        _sys.path = %r
 514        del _sys
 515        \n""" % (path,))
 516
 517    active_seq = None
 518
 519    def poll_subprocess(self):
 520        clt = self.rpcclt
 521        if clt is None:
 522            return
 523        try:
 524            response = clt.pollresponse(self.active_seq, wait=0.05)
 525        except (EOFError, IOError, KeyboardInterrupt):
 526            # lost connection or subprocess terminated itself, restart
 527            # [the KBI is from rpc.SocketIO.handle_EOF()]
 528            if self.tkconsole.closing:
 529                return
 530            response = None
 531            self.restart_subprocess()
 532        if response:
 533            self.tkconsole.resetoutput()
 534            self.active_seq = None
 535            how, what = response
 536            console = self.tkconsole.console
 537            if how == "OK":
 538                if what is not None:
 539                    print >>console, repr(what)
 540            elif how == "EXCEPTION":
 541                if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
 542                    self.remote_stack_viewer()
 543            elif how == "ERROR":
 544                errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
 545                print >>sys.__stderr__, errmsg, what
 546                print >>console, errmsg, what
 547            # we received a response to the currently active seq number:
 548            try:
 549                self.tkconsole.endexecuting()
 550            except AttributeError:  # shell may have closed
 551                pass
 552        # Reschedule myself
 553        if not self.tkconsole.closing:
 554            self.tkconsole.text.after(self.tkconsole.pollinterval,
 555                                      self.poll_subprocess)
 556
 557    debugger = None
 558
 559    def setdebugger(self, debugger):
 560        self.debugger = debugger
 561
 562    def getdebugger(self):
 563        return self.debugger
 564
 565    def open_remote_stack_viewer(self):
 566        """Initiate the remote stack viewer from a separate thread.
 567
 568        This method is called from the subprocess, and by returning from this
 569        method we allow the subprocess to unblock.  After a bit the shell
 570        requests the subprocess to open the remote stack viewer which returns a
 571        static object looking at the last exception.  It is queried through
 572        the RPC mechanism.
 573
 574        """
 575        self.tkconsole.text.after(300, self.remote_stack_viewer)
 576        return
 577
 578    def remote_stack_viewer(self):
 579        from idlelib import RemoteObjectBrowser
 580        oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
 581        if oid is None:
 582            self.tkconsole.root.bell()
 583            return
 584        item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
 585        from idlelib.TreeWidget import ScrolledCanvas, TreeNode
 586        top = Toplevel(self.tkconsole.root)
 587        theme = idleConf.GetOption('main','Theme','name')
 588        background = idleConf.GetHighlight(theme, 'normal')['background']
 589        sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
 590        sc.frame.pack(expand=1, fill="both")
 591        node = TreeNode(sc.canvas, None, item)
 592        node.expand()
 593        # XXX Should GC the remote tree when closing the window
 594
 595    gid = 0
 596
 597    def execsource(self, source):
 598        "Like runsource() but assumes complete exec source"
 599        filename = self.stuffsource(source)
 600        self.execfile(filename, source)
 601
 602    def execfile(self, filename, source=None):
 603        "Execute an existing file"
 604        if source is None:
 605            source = open(filename, "r").read()
 606        try:
 607            code = compile(source, filename, "exec")
 608        except (OverflowError, SyntaxError):
 609            self.tkconsole.resetoutput()
 610            tkerr = self.tkconsole.stderr
 611            print>>tkerr, '*** Error in script or command!\n'
 612            print>>tkerr, 'Traceback (most recent call last):'
 613            InteractiveInterpreter.showsyntaxerror(self, filename)
 614            self.tkconsole.showprompt()
 615        else:
 616            self.runcode(code)
 617
 618    def runsource(self, source):
 619        "Extend base class method: Stuff the source in the line cache first"
 620        filename = self.stuffsource(source)
 621        self.more = 0
 622        self.save_warnings_filters = warnings.filters[:]
 623        warnings.filterwarnings(action="error", category=SyntaxWarning)
 624        if isinstance(source, types.UnicodeType):
 625            from idlelib import IOBinding
 626            try:
 627                source = source.encode(IOBinding.encoding)
 628            except UnicodeError:
 629                self.tkconsole.resetoutput()
 630                self.write("Unsupported characters in input\n")
 631                return
 632        try:
 633            # InteractiveInterpreter.runsource() calls its runcode() method,
 634            # which is overridden (see below)
 635            return InteractiveInterpreter.runsource(self, source, filename)
 636        finally:
 637            if self.save_warnings_filters is not None:
 638                warnings.filters[:] = self.save_warnings_filters
 639                self.save_warnings_filters = None
 640
 641    def stuffsource(self, source):
 642        "Stuff source in the filename cache"
 643        filename = "<pyshell#%d>" % self.gid
 644        self.gid = self.gid + 1
 645        lines = source.split("\n")
 646        linecache.cache[filename] = len(source)+1, 0, lines, filename
 647        return filename
 648
 649    def prepend_syspath(self, filename):
 650        "Prepend sys.path with file's directory if not already included"
 651        self.runcommand("""if 1:
 652            _filename = %r
 653            import sys as _sys
 654            from os.path import dirname as _dirname
 655            _dir = _dirname(_filename)
 656            if not _dir in _sys.path:
 657                _sys.path.insert(0, _dir)
 658            del _filename, _sys, _dirname, _dir
 659            \n""" % (filename,))
 660
 661    def showsyntaxerror(self, filename=None):
 662        """Extend base class method: Add Colorizing
 663
 664        Color the offending position instead of printing it and pointing at it
 665        with a caret.
 666
 667        """
 668        text = self.tkconsole.text
 669        stuff = self.unpackerror()
 670        if stuff:
 671            msg, lineno, offset, line = stuff
 672            if lineno == 1:
 673                pos = "iomark + %d chars" % (offset-1)
 674            else:
 675                pos = "iomark linestart + %d lines + %d chars" % \
 676                      (lineno-1, offset-1)
 677            text.tag_add("ERROR", pos)
 678            text.see(pos)
 679            char = text.get(pos)
 680            if char and char in IDENTCHARS:
 681                text.tag_add("ERROR", pos + " wordstart", pos)
 682            self.tkconsole.resetoutput()
 683            self.write("SyntaxError: %s\n" % str(msg))
 684        else:
 685            self.tkconsole.resetoutput()
 686            InteractiveInterpreter.showsyntaxerror(self, filename)
 687        self.tkconsole.showprompt()
 688
 689    def unpackerror(self):
 690        type, value, tb = sys.exc_info()
 691        ok = type is SyntaxError
 692        if ok:
 693            try:
 694                msg, (dummy_filename, lineno, offset, line) = value
 695                if not offset:
 696                    offset = 0
 697            except:
 698                ok = 0
 699        if ok:
 700            return msg, lineno, offset, line
 701        else:
 702            return None
 703
 704    def showtraceback(self):
 705        "Extend base class method to reset output properly"
 706        self.tkconsole.resetoutput()
 707        self.checklinecache()
 708        InteractiveInterpreter.showtraceback(self)
 709        if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
 710            self.tkconsole.open_stack_viewer()
 711
 712    def checklinecache(self):
 713        c = linecache.cache
 714        for key in c.keys():
 715            if key[:1] + key[-1:] != "<>":
 716                del c[key]
 717
 718    def runcommand(self, code):
 719        "Run the code without invoking the debugger"
 720        # The code better not raise an exception!
 721        if self.tkconsole.executing:
 722            self.display_executing_dialog()
 723            return 0
 724        if self.rpcclt:
 725            self.rpcclt.remotequeue("exec", "runcode", (code,), {})
 726        else:
 727            exec code in self.locals
 728        return 1
 729
 730    def runcode(self, code):
 731        "Override base class method"
 732        if self.tkconsole.executing:
 733            self.interp.restart_subprocess()
 734        self.checklinecache()
 735        if self.save_warnings_filters is not None:
 736            warnings.filters[:] = self.save_warnings_filters
 737            self.save_warnings_filters = None
 738        debugger = self.debugger
 739        try:
 740            self.tkconsole.beginexecuting()
 741            if not debugger and self.rpcclt is not None:
 742                self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
 743                                                        (code,), {})
 744            elif debugger:
 745                debugger.run(code, self.locals)
 746            else:
 747                exec code in self.locals
 748        except SystemExit:
 749            if not self.tkconsole.closing:
 750                if tkMessageBox.askyesno(
 751                    "Exit?",
 752                    "Do you want to exit altogether?",
 753                    default="yes",
 754                    master=self.tkconsole.text):
 755                    raise
 756                else:
 757                    self.showtraceback()
 758            else:
 759                raise
 760        except:
 761            if use_subprocess:
 762                print >>self.tkconsole.stderr, \
 763                         "IDLE internal error in runcode()"
 764                self.showtraceback()
 765                self.tkconsole.endexecuting()
 766            else:
 767                if self.tkconsole.canceled:
 768                    self.tkconsole.canceled = False
 769                    print >>self.tkconsole.stderr, "KeyboardInterrupt"
 770                else:
 771                    self.showtraceback()
 772        finally:
 773            if not use_subprocess:
 774                try:
 775                    self.tkconsole.endexecuting()
 776                except AttributeError:  # shell may have closed
 777                    pass
 778
 779    def write(self, s):
 780        "Override base class method"
 781        self.tkconsole.stderr.write(s)
 782
 783    def display_port_binding_error(self):
 784        tkMessageBox.showerror(
 785            "Port Binding Error",
 786            "IDLE can't bind to a TCP/IP port, which is necessary to "
 787            "communicate with its Python execution server.  This might be "
 788            "because no networking is installed on this computer.  "
 789            "Run IDLE with the -n command line switch to start without a "
 790            "subprocess and refer to Help/IDLE Help 'Running without a "
 791            "subprocess' for further details.",
 792            master=self.tkconsole.text)
 793
 794    def display_no_subprocess_error(self):
 795        tkMessageBox.showerror(
 796            "Subprocess Startup Error",
 797            "IDLE's subprocess didn't make connection.  Either IDLE can't "
 798            "start a subprocess or personal firewall software is blocking "
 799            "the connection.",
 800            master=self.tkconsole.text)
 801
 802    def display_executing_dialog(self):
 803        tkMessageBox.showerror(
 804            "Already executing",
 805            "The Python Shell window is already executing a command; "
 806            "please wait until it is finished.",
 807            master=self.tkconsole.text)
 808
 809
 810class PyShell(OutputWindow):
 811
 812    shell_title = "Python Shell"
 813
 814    # Override classes
 815    ColorDelegator = ModifiedColorDelegator
 816    UndoDelegator = ModifiedUndoDelegator
 817
 818    # Override menus
 819    menu_specs = [
 820        ("file", "_File"),
 821        ("edit", "_Edit"),
 822        ("debug", "_Debug"),
 823        ("options", "_Options"),
 824        ("windows", "_Windows"),
 825        ("help", "_Help"),
 826    ]
 827
 828    if macosxSupport.runningAsOSXApp():
 829        del menu_specs[-3]
 830        menu_specs[-2] = ("windows", "_Window")
 831
 832
 833    # New classes
 834    from idlelib.IdleHistory import History
 835
 836    def __init__(self, flist=None):
 837        if use_subprocess:
 838            ms = self.menu_specs
 839            if ms[2][0] != "shell":
 840                ms.insert(2, ("shell", "She_ll"))
 841        self.interp = ModifiedInterpreter(self)
 842        if flist is None:
 843            root = Tk()
 844            fixwordbreaks(root)
 845            root.withdraw()
 846            flist = PyShellFileList(root)
 847        #
 848        OutputWindow.__init__(self, flist, None, None)
 849        #
 850##        self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
 851        self.usetabs = True
 852        # indentwidth must be 8 when using tabs.  See note in EditorWindow:
 853        self.indentwidth = 8
 854        self.context_use_ps1 = True
 855        #
 856        text = self.text
 857        text.configure(wrap="char")
 858        text.bind("<<newline-and-indent>>", self.enter_callback)
 859        text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
 860        text.bind("<<interrupt-execution>>", self.cancel_callback)
 861        text.bind("<<end-of-file>>", self.eof_callback)
 862        text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
 863        text.bind("<<toggle-debugger>>", self.toggle_debugger)
 864        text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
 865        if use_subprocess:
 866            text.bind("<<view-restart>>", self.view_restart_mark)
 867            text.bind("<<restart-shell>>", self.restart_shell)
 868        #
 869        self.save_stdout = sys.stdout
 870        self.save_stderr = sys.stderr
 871        self.save_stdin = sys.stdin
 872        from idlelib import IOBinding
 873        self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
 874        self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
 875        self.console = PseudoFile(self, "console", IOBinding.encoding)
 876        if not use_subprocess:
 877            sys.stdout = self.stdout
 878            sys.stderr = self.stderr
 879            sys.stdin = self
 880        #
 881        self.history = self.History(self.text)
 882        #
 883        self.pollinterval = 50  # millisec
 884
 885    def get_standard_extension_names(self):
 886        return idleConf.GetExtensions(shell_only=True)
 887
 888    reading = False
 889    executing = False
 890    canceled = False
 891    endoffile = False
 892    closing = False
 893
 894    def set_warning_stream(self, stream):
 895        global warning_stream
 896        warning_stream = stream
 897
 898    def get_warning_stream(self):
 899        return warning_stream
 900
 901    def toggle_debugger(self, event=None):
 902        if self.executing:
 903            tkMessageBox.showerror("Don't debug now",
 904                "You can only toggle the debugger when idle",
 905                master=self.text)
 906            self.set_debugger_indicator()
 907            return "break"
 908        else:
 909            db = self.interp.getdebugger()
 910            if db:
 911                self.close_debugger()
 912            else:
 913                self.open_debugger()
 914
 915    def set_debugger_indicator(self):
 916        db = self.interp.getdebugger()
 917        self.setvar("<<toggle-debugger>>", not not db)
 918
 919    def toggle_jit_stack_viewer(self, event=None):
 920        pass # All we need is the variable
 921
 922    def close_debugger(self):
 923        db = self.interp.getdebugger()
 924        if db:
 925            self.interp.setdebugger(None)
 926            db.close()
 927            if self.interp.rpcclt:
 928                RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
 929            self.resetoutput()
 930            self.console.write("[DEBUG OFF]\n")
 931            sys.ps1 = ">>> "
 932            self.showprompt()
 933        self.set_debugger_indicator()
 934
 935    def open_debugger(self):
 936        if self.interp.rpcclt:
 937            dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
 938                                                           self)
 939        else:
 940            dbg_gui = Debugger.Debugger(self)
 941        self.interp.setdebugger(dbg_gui)
 942        dbg_gui.load_breakpoints()
 943        sys.ps1 = "[DEBUG ON]\n>>> "
 944        self.showprompt()
 945        self.set_debugger_indicator()
 946
 947    def beginexecuting(self):
 948        "Helper for ModifiedInterpreter"
 949        self.resetoutput()
 950        self.executing = 1
 951
 952    def endexecuting(self):
 953        "Helper for ModifiedInterpreter"
 954        self.executing = 0
 955        self.canceled = 0
 956        self.showprompt()
 957
 958    def close(self):
 959        "Extend EditorWindow.close()"
 960        if self.executing:
 961            response = tkMessageBox.askokcancel(
 962                "Kill?",
 963                "The program is still running!\n Do you want to kill it?",
 964                default="ok",
 965                parent=self.text)
 966            if response is False:
 967                return "cancel"
 968        if self.reading:
 969            self.top.quit()
 970        self.canceled = True
 971        self.closing = True
 972        # Wait for poll_subprocess() rescheduling to stop
 973        self.text.after(2 * self.pollinterval, self.close2)
 974
 975    def close2(self):
 976        return EditorWindow.close(self)
 977
 978    def _close(self):
 979        "Extend EditorWindow._close(), shut down debugger and execution server"
 980        self.close_debugger()
 981        if use_subprocess:
 982            self.interp.kill_subprocess()
 983        # Restore std streams
 984        sys.stdout = self.save_stdout
 985        sys.stderr = self.save_stderr
 986        sys.stdin = self.save_stdin
 987        # Break cycles
 988        self.interp = None
 989        self.console = None
 990        self.flist.pyshell = None
 991        self.history = None
 992        EditorWindow._close(self)
 993
 994    def ispythonsource(self, filename):
 995        "Override EditorWindow method: never remove the colorizer"
 996        return True
 997
 998    def short_title(self):
 999        return self.shell_title
1000
1001    COPYRIGHT = \
1002          'Type "copyright", "credits" or "license()" for more information.'
1003
1004    def begin(self):
1005        self.resetoutput()
1006        if use_subprocess:
1007            nosub = ''
1008            client = self.interp.start_subprocess()
1009            if not client:
1010                self.close()
1011                return False
1012        else:
1013            nosub = "==== No Subprocess ===="
1014        self.write("Python %s on %s\n%s\n%s" %
1015                   (sys.version, sys.platform, self.COPYRIGHT, nosub))
1016        self.showprompt()
1017        import Tkinter
1018        Tkinter._default_root = None # 03Jan04 KBK What's this?
1019        return True
1020
1021    def readline(self):
1022        save = self.reading
1023        try:
1024            self.reading = 1
1025            self.top.mainloop()  # nested mainloop()
1026        finally:
1027            self.reading = save
1028        line = self.text.get("iomark", "end-1c")
1029        if len(line) == 0:  # may be EOF if we quit our mainloop with Ctrl-C
1030            line = "\n"
1031        if isinstance(line, unicode):
1032            from idlelib import IOBinding
1033            try:
1034                line = line.encode(IOBinding.encoding)
1035            except UnicodeError:
1036                pass
1037        self.resetoutput()
1038        if self.canceled:
1039            self.canceled = 0
1040            if not use_subprocess:
1041                raise KeyboardInterrupt
1042        if self.endoffile:
1043            self.endoffile = 0
1044            line = ""
1045        return line
1046
1047    def isatty(self):
1048        return True
1049
1050    def cancel_callback(self, event=None):
1051        try:
1052            if self.text.compare("sel.first", "!=", "sel.last"):
1053                return # Active selection -- always use default binding
1054        except:
1055            pass
1056        if not (self.executing or self.reading):
1057            self.resetoutput()
1058            self.interp.write("KeyboardInterrupt\n")
1059            self.showprompt()
1060            return "break"
1061        self.endoffile = 0
1062        self.canceled = 1
1063        if (self.executing and self.interp.rpcclt):
1064            if self.interp.getdebugger():
1065                self.interp.restart_subprocess()
1066            else:
1067                self.interp.interrupt_subprocess()
1068        if self.reading:
1069            self.top.quit()  # exit the nested mainloop() in readline()
1070        return "break"
1071
1072    def eof_callback(self, event):
1073        if self.executing and not self.reading:
1074            return # Let the default binding (delete next char) take over
1075        if not (self.text.compare("iomark", "==", "insert") and
1076                self.text.compare("insert", "==", "end-1c")):
1077            return # Let the default binding (delete next char) take over
1078        if not self.executing:
1079            self.resetoutput()
1080            self.close()
1081        else:
1082            self.canceled = 0
1083            self.endoffile = 1
1084            self.top.quit()
1085        return "break"
1086
1087    def linefeed_callback(self, event):
1088        # Insert a linefeed without entering anything (still autoindented)
1089        if self.reading:
1090            self.text.insert("insert", "\n")
1091            self.text.see("insert")
1092        else:
1093            self.newline_and_indent_event(event)
1094        return "break"
1095
1096    def enter_callback(self, event):
1097        if self.executing and not self.reading:
1098            return # Let the default binding (insert '\n') take over
1099        # If some text is selected, recall the selection
1100        # (but only if this before the I/O mark)
1101        try:
1102            sel = self.text.get("sel.first", "sel.last")
1103            if sel:
1104                if self.text.compare("sel.last", "<=", "iomark"):
1105                    self.recall(sel, event)
1106                    return "break"
1107        except:
1108            pass
1109        # If we're strictly before the line containing iomark, recall
1110        # the current line, less a leading prompt, less leading or
1111        # trailing whitespace
1112        if self.text.compare("insert", "<", "iomark linestart"):
1113            # Check if there's a relevant stdin range -- if so, use it
1114            prev = self.text.tag_prevrange("stdin", "insert")
1115            if prev and self.text.compare("insert", "<", prev[1]):
1116                self.recall(self.text.get(prev[0], prev[1]), event)
1117                return "break"
1118            next = self.text.tag_nextrange("stdin", "insert")
1119            if next and self.text.compare("insert lineend", ">=", next[0]):
1120                self.recall(self.text.get(next[0], next[1]), event)
1121                return "break"
1122            # No stdin mark -- just get the current line, less any prompt
1123            indices = self.text.tag_nextrange("console", "insert linestart")
1124            if indices and \
1125               self.text.compare(indices[0], "<=", "insert linestart"):
1126                self.recall(self.text.get(indices[1], "insert lineend"), event)
1127            else:
1128                self.recall(self.text.get("insert linestart", "insert lineend"), event)
1129            return "break"
1130        # If we're between the beginning of the line and the iomark, i.e.
1131        # in the prompt area, move to the end of the prompt
1132        if self.text.compare("insert", "<", "iomark"):
1133            self.text.mark_set("insert", "iomark")
1134        # If we're in the current input and there's only whitespace
1135        # beyond the cursor, erase that whitespace first
1136        s = self.text.get("insert", "end-1c")
1137        if s and not s.strip():
1138            self.text.delete("insert", "end-1c")
1139        # If we're in the current input before its last line,
1140        # insert a newline right at the insert point
1141        if self.text.compare("insert", "<", "end-1c linestart"):
1142            self.newline_and_indent_event(event)
1143            return "break"
1144        # We're in the last line; append a newline and submit it
1145        self.text.mark_set("insert", "end-1c")
1146        if self.reading:
1147            self.text.insert("insert", "\n")
1148            self.text.see("insert")
1149        else:
1150            self.newline_and_indent_event(event)
1151        self.text.tag_add("stdin", "iomark", "end-1c")
1152        self.text.update_idletasks()
1153        if self.reading:
1154            self.top.quit() # Break out of recursive mainloop() in raw_input()
1155        else:
1156            self.runit()
1157        return "break"
1158
1159    def recall(self, s, event):
1160        # remove leading and trailing empty or whitespace lines
1161        s = re.sub(r'^\s*\n', '' , s)
1162        s = re.sub(r'\n\s*$', '', s)
1163        lines = s.split('\n')
1164        self.text.undo_block_start()
1165        try:
1166            self.text.tag_remove("sel", "1.0", "end")
1167            self.text.mark_set("insert", "end-1c")
1168            prefix = self.text.get("insert linestart", "insert")
1169            if prefix.rstrip().endswith(':'):
1170                self.newline_and_indent_event(event)
1171                prefix = self.text.get("insert linestart", "insert")
1172            self.text.insert("insert", lines[0].strip())
1173            if len(lines) > 1:
1174                orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1175                new_base_indent  = re.search(r'^([ \t]*)', prefix).group(0)
1176                for line in lines[1:]:
1177                    if line.startswith(orig_base_indent):
1178                        # replace orig base indentation with new indentation
1179                        line = new_base_indent + line[len(orig_base_indent):]
1180                    self.text.insert('insert', '\n'+line.rstrip())
1181        finally:
1182            self.text.see("insert")
1183            self.text.undo_block_stop()
1184
1185    def runit(self):
1186        line = self.text.get("iomark", "end-1c")
1187        # Strip off last newline and surrounding whitespace.
1188        # (To allow you to hit return twice to end a statement.)
1189        i = len(line)
1190        while i > 0 and line[i-1] in " \t":
1191            i = i-1
1192        if i > 0 and line[i-1] == "\n":
1193            i = i-1
1194        while i > 0 and line[i-1] in " \t":
1195            i = i-1
1196        line = line[:i]
1197        more = self.interp.runsource(line)
1198
1199    def open_stack_viewer(self, event=None):
1200        if self.interp.rpcclt:
1201            return self.interp.remote_stack_viewer()
1202        try:
1203            sys.last_traceback
1204        except:
1205            tkMessageBox.showerror("No stack trace",
1206                "There is no stack trace yet.\n"
1207                "(sys.last_traceback is not defined)",
1208                master=self.text)
1209            return
1210        from idlelib.StackViewer import StackBrowser
1211        sv = StackBrowser(self.root, self.flist)
1212
1213    def view_restart_mark(self, event=None):
1214        self.text.see("iomark")
1215        self.text.see("restart")
1216
1217    def restart_shell(self, event=None):
1218        "Callback for Run/Restart Shell Cntl-F6"
1219        self.interp.restart_subprocess(with_cwd=True)
1220
1221    def showprompt(self):
1222        self.resetoutput()
1223        try:
1224            s = str(sys.ps1)
1225        except:
1226            s = ""
1227        self.console.write(s)
1228        self.text.mark_set("insert", "end-1c")
1229        self.set_line_and_column()
1230        self.io.reset_undo()
1231
1232    def resetoutput(self):
1233        source = self.text.get("iomark", "end-1c")
1234        if self.history:
1235            self.history.history_store(source)
1236        if self.text.get("end-2c") != "\n":
1237            self.text.insert("end-1c", "\n")
1238        self.text.mark_set("iomark", "end-1c")
1239        self.set_line_and_column()
1240        sys.stdout.softspace = 0
1241
1242    def write(self, s, tags=()):
1243        try:
1244            self.text.mark_gravity("iomark", "right")
1245            OutputWindow.write(self, s, tags, "iomark")
1246            self.text.mark_gravity("iomark", "left")
1247        except:
1248            pass
1249        if self.canceled:
1250            self.canceled = 0
1251            if not use_subprocess:
1252                raise KeyboardInterrupt
1253
1254class PseudoFile(object):
1255
1256    def __init__(self, shell, tags, encoding=None):
1257        self.shell = shell
1258        self.tags = tags
1259        self.softspace = 0
1260        self.encoding = encoding
1261
1262    def write(self, s):
1263        self.shell.write(s, self.tags)
1264
1265    def writelines(self, lines):
1266        for line in lines:
1267            self.write(line)
1268
1269    def flush(self):
1270        pass
1271
1272    def isatty(self):
1273        return True
1274
1275
1276usage_msg = """\
1277
1278USAGE: idle  [-deins] [-t title] [file]*
1279       idle  [-dns] [-t title] (-c cmd | -r file) [arg]*
1280       idle  [-dns] [-t title] - [arg]*
1281
1282  -h         print this help message and exit
1283  -n         run IDLE without a subprocess (see Help/IDLE Help for details)
1284
1285The following options will override the IDLE 'settings' configuration:
1286
1287  -e         open an edit window
1288  -i         open a shell window
1289
1290The following options imply -i and will open a shell:
1291
1292  -c cmd     run the command in a shell, or
1293  -r file    run script from file
1294
1295  -d         enable the debugger
1296  -s         run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1297  -t title   set title of shell window
1298
1299A default edit window will be bypassed when -c, -r, or - are used.
1300
1301[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1302
1303Examples:
1304
1305idle
1306        Open an edit window or shell depending on IDLE's configuration.
1307
1308idle foo.py foobar.py
1309        Edit the files, also open a shell if configured to start with shell.
1310
1311idle -est "Baz" foo.py
1312        Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1313        window with the title "Baz".
1314
1315idle -c "import sys; print sys.argv" "foo"
1316        Open a shell window and run the command, passing "-c" in sys.argv[0]
1317        and "foo" in sys.argv[1].
1318
1319idle -d -s -r foo.py "Hello World"
1320        Open a shell window, run a startup script, enable the debugger, and
1321        run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1322        sys.argv[1].
1323
1324echo "import sys; print sys.argv" | idle - "foobar"
1325        Open a shell window, run the script piped in, passing '' in sys.argv[0]
1326        and "foobar" in sys.argv[1].
1327"""
1328
1329def main():
1330    global flist, root, use_subprocess
1331
1332    use_subprocess = True
1333    enable_shell = True
1334    enable_edit = False
1335    debug = False
1336    cmd = None
1337    script = None
1338    startup = False
1339    try:
1340        opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
1341    except getopt.error, msg:
1342        sys.stderr.write("Error: %s\n" % str(msg))
1343        sys.stderr.write(usage_msg)
1344        sys.exit(2)
1345    for o, a in opts:
1346        if o == '-c':
1347            cmd = a
1348            enable_shell = True
1349        if o == '-d':
1350            debug = True
1351            enable_shell = True
1352        if o == '-e':
1353            enable_edit = True
1354            enable_shell = False
1355        if o == '-h':
1356            sys.stdout.write(usage_msg)
1357            sys.exit()
1358        if o == '-i':
1359            enable_shell = True
1360        if o == '-n':
1361            use_subprocess = False
1362        if o == '-r':
1363            script = a
1364            if os.path.isfile(script):
1365                pass
1366            else:
1367                print "No script file: ", script
1368                sys.exit()
1369            enable_shell = True
1370        if o == '-s':
1371            startup = True
1372            enable_shell = True
1373        if o == '-t':
1374            PyShell.shell_title = a
1375            enable_shell = True
1376    if args and args[0] == '-':
1377        cmd = sys.stdin.read()
1378        enable_shell = True
1379    # process sys.argv and sys.path:
1380    for i in range(len(sys.path)):
1381        sys.path[i] = os.path.abspath(sys.path[i])
1382    if args and args[0] == '-':
1383        sys.argv = [''] + args[1:]
1384    elif cmd:
1385        sys.argv = ['-c'] + args
1386    elif script:
1387        sys.argv = [script] + ar

Large files files are truncated, but you can click here to view the full file