183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys
283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport io
383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport linecache
483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport time
583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport socket
683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport traceback
783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport thread
883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport threading
983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport Queue
1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import CallTips
1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import AutoComplete
1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import RemoteDebugger
1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import RemoteObjectBrowser
1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import StackViewer
1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import rpc
1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import PyShell
1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import IOBinding
2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport __main__
2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehLOCALHOST = '127.0.0.1'
2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehtry:
2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    import warnings
2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehexcept ImportError:
2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    pass
2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehelse:
3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def idle_formatwarning_subproc(message, category, filename, lineno,
3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                   line=None):
3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Format warnings the IDLE way"""
3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        s = "\nWarning (from warnings module):\n"
3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        s += '  File \"%s\", line %s\n' % (filename, lineno)
3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if line is None:
3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            line = linecache.getline(filename, lineno)
3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        line = line.strip()
3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if line:
3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            s += "    %s\n" % line
4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        s += "%s: %s\n" % (category.__name__, message)
4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return s
4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    warnings.formatwarning = idle_formatwarning_subproc
4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Thread shared globals: Establish a queue between a subthread (which handles
4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# the socket) and the main thread (which runs user code), plus global
4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# completion, exit and interruptable (the main thread) flags:
4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehexit_now = False
4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehquitting = False
5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehinterruptable = False
5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef main(del_exitfunc=False):
5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Start the Python execution server in a subprocess
5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    In the Python subprocess, RPCServer is instantiated with handlerclass
5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    MyHandler, which inherits register/unregister methods from RPCHandler via
5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    the mix-in class SocketIO.
5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    When the RPCServer 'server' is instantiated, the TCPServer initialization
6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    creates an instance of run.MyHandler and calls its handle() method.
6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    handle() instantiates a run.Executive object, passing it a reference to the
6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    MyHandler object.  That reference is saved as attribute rpchandler of the
6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Executive instance.  The Executive methods have access to the reference and
6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    can pass it on to entities that they command
6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    (e.g. RemoteDebugger.Debugger.start_debugger()).  The latter, in turn, can
6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    call MyHandler(SocketIO) register/unregister methods via the reference to
6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    register and unregister themselves.
6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    global exit_now
7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    global quitting
7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    global no_exitfunc
7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    no_exitfunc = del_exitfunc
7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #time.sleep(15) # test subprocess not responding
7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    try:
7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert(len(sys.argv) > 1)
7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        port = int(sys.argv[-1])
7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    except:
7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        print>>sys.stderr, "IDLE Subprocess: no IP port passed in sys.argv."
8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return
8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sys.argv[:] = [""]
8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sockthread = threading.Thread(target=manage_socket,
8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                  name='SockThread',
8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                  args=((LOCALHOST, port),))
8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sockthread.setDaemon(True)
8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sockthread.start()
8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    while 1:
8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if exit_now:
9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                try:
9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    exit()
9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                except KeyboardInterrupt:
9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    # exiting but got an extra KBI? Try again!
9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    continue
9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                seq, request = rpc.request_queue.get(block=True, timeout=0.05)
9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except Queue.Empty:
9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                continue
9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            method, args, kwargs = request
10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ret = method(*args, **kwargs)
10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            rpc.response_queue.put((seq, ret))
10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except KeyboardInterrupt:
10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if quitting:
10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                exit_now = True
10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            continue
10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except SystemExit:
10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            raise
10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except:
10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            type, value, tb = sys.exc_info()
11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                print_exception()
11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                rpc.response_queue.put((seq, None))
11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except:
11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # Link didn't work, print same exception to __stderr__
11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                traceback.print_exception(type, value, tb, file=sys.__stderr__)
11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                exit()
11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                continue
11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef manage_socket(address):
12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    for i in range(3):
12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        time.sleep(i)
12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            server = MyRPCServer(address, MyHandler)
12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            break
12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except socket.error, err:
12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print>>sys.__stderr__,"IDLE Subprocess: socket error: "\
12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                        + err.args[1] + ", retrying...."
12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    else:
13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        print>>sys.__stderr__, "IDLE Subprocess: Connection to "\
13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                               "IDLE GUI failed, exiting."
13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        show_socket_error(err, address)
13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        global exit_now
13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        exit_now = True
13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return
13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    server.handle_request() # A single request only
13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef show_socket_error(err, address):
13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    import Tkinter
14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    import tkMessageBox
14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    root = Tkinter.Tk()
14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    root.withdraw()
14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if err.args[0] == 61: # connection refused
14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        msg = "IDLE's subprocess can't connect to %s:%d.  This may be due "\
14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh              "to your personal firewall configuration.  It is safe to "\
14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh              "allow this internal connection because no data is visible on "\
14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh              "external ports." % address
14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root)
14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    else:
15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        tkMessageBox.showerror("IDLE Subprocess Error",
15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                               "Socket Error: %s" % err.args[1])
15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    root.destroy()
15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef print_exception():
15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    import linecache
15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    linecache.checkcache()
15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    flush_stdout()
15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    efile = sys.stderr
15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    typ, val, tb = excinfo = sys.exc_info()
16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sys.last_type, sys.last_value, sys.last_traceback = excinfo
16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    tbe = traceback.extract_tb(tb)
16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    print>>efile, '\nTraceback (most recent call last):'
16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh               "RemoteDebugger.py", "bdb.py")
16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    cleanup_traceback(tbe, exclude)
16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    traceback.print_list(tbe, file=efile)
16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    lines = traceback.format_exception_only(typ, val)
16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    for line in lines:
16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        print>>efile, line,
17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef cleanup_traceback(tb, exclude):
17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    "Remove excluded traces from beginning/end of tb; get cached lines"
17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    orig_tb = tb[:]
17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    while tb:
17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for rpcfile in exclude:
17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if tb[0][0].count(rpcfile):
17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                break    # found an exclude, break for: and delete tb[0]
17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            break        # no excludes, have left RPC code, break while:
18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        del tb[0]
18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    while tb:
18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for rpcfile in exclude:
18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if tb[-1][0].count(rpcfile):
18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                break
18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            break
18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        del tb[-1]
18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if len(tb) == 0:
18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # exception was in IDLE internals, don't prune!
19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        tb[:] = orig_tb[:]
19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        print>>sys.stderr, "** IDLE Internal Exception: "
19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    rpchandler = rpc.objecttable['exec'].rpchandler
19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    for i in range(len(tb)):
19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        fn, ln, nm, line = tb[i]
19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if nm == '?':
19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            nm = "-toplevel-"
19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not line and fn.startswith("<pyshell#"):
19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            line = rpchandler.remotecall('linecache', 'getline',
19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                              (fn, ln), {})
20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        tb[i] = fn, ln, nm, line
20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef flush_stdout():
20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    try:
20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if sys.stdout.softspace:
20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            sys.stdout.softspace = 0
20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            sys.stdout.write("\n")
20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    except (AttributeError, EOFError):
20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef exit():
21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Exit subprocess, possibly after first deleting sys.exitfunc
21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sys.exitfunc will be removed before exiting.  (VPython support)
21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if no_exitfunc:
21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            del sys.exitfunc
22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except AttributeError:
22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            pass
22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sys.exit(0)
22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass MyRPCServer(rpc.RPCServer):
22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def handle_error(self, request, client_address):
22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Override RPCServer method for IDLE
22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Interrupt the MainThread and exit server if link is dropped.
23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        global quitting
23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            raise
23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except SystemExit:
23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            raise
23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except EOFError:
23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            global exit_now
23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            exit_now = True
24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            thread.interrupt_main()
24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except:
24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            erf = sys.__stderr__
24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print>>erf, '\n' + '-'*40
24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print>>erf, 'Unhandled server exception!'
24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print>>erf, 'Thread: %s' % threading.currentThread().getName()
24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print>>erf, 'Client Address: ', client_address
24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print>>erf, 'Request: ', repr(request)
24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            traceback.print_exc(file=erf)
24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print>>erf, '\n*** Unrecoverable, server exiting!'
25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print>>erf, '-'*40
25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            quitting = True
25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            thread.interrupt_main()
25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass MyHandler(rpc.RPCHandler):
25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def handle(self):
25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Override base method"""
25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        executive = Executive(self)
25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.register("exec", executive)
26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.console = self.get_remote_proxy("console")
26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sys.stdin = PyShell.PseudoInputFile(self.console, "stdin",
26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                IOBinding.encoding)
26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sys.stdout = PyShell.PseudoOutputFile(self.console, "stdout",
26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                IOBinding.encoding)
26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sys.stderr = PyShell.PseudoOutputFile(self.console, "stderr",
26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                IOBinding.encoding)
26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Keep a reference to stdin so that it won't try to exit IDLE if
26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # sys.stdin gets changed from within IDLE's shell. See issue17838.
27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._keep_stdin = sys.stdin
27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.interp = self.get_remote_proxy("interp")
27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def exithook(self):
27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "override SocketIO method - wait for MainThread to shut us down"
27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        time.sleep(10)
27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def EOFhook(self):
28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "Override SocketIO method - terminate wait on callback and exit thread"
28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        global quitting
28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        quitting = True
28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        thread.interrupt_main()
28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def decode_interrupthook(self):
28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "interrupt awakened thread"
28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        global quitting
28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        quitting = True
28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        thread.interrupt_main()
29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Executive(object):
29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, rpchandler):
29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.rpchandler = rpchandler
29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.locals = __main__.__dict__
29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.calltip = CallTips.CallTips()
29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.autocomplete = AutoComplete.AutoComplete()
29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def runcode(self, code):
30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        global interruptable
30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.usr_exc_info = None
30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            interruptable = True
30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                exec code in self.locals
30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            finally:
30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                interruptable = False
30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except SystemExit:
31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # Scripts that raise SystemExit should just
31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # return to the interactive prompt
31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            pass
31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except:
31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.usr_exc_info = sys.exc_info()
31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if quitting:
31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                exit()
31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            print_exception()
31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if jit:
32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.rpchandler.interp.open_remote_stack_viewer()
32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            flush_stdout()
32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def interrupt_the_server(self):
32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if interruptable:
32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            thread.interrupt_main()
32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def start_the_debugger(self, gui_adap_oid):
32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def stop_the_debugger(self, idb_adap_oid):
33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        "Unregister the Idb Adapter.  Link objects and Idb then subject to GC"
33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.rpchandler.unregister(idb_adap_oid)
33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_the_calltip(self, name):
33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.calltip.fetch_tip(name)
33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_the_completion_list(self, what, mode):
33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.autocomplete.fetch_completions(what, mode)
34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def stackviewer(self, flist_oid=None):
34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.usr_exc_info:
34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            typ, val, tb = self.usr_exc_info
34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
34583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return None
34683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        flist = None
34783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if flist_oid is not None:
34883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            flist = self.rpchandler.get_remote_proxy(flist_oid)
34983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
35083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            tb = tb.tb_next
35183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sys.last_type = typ
35283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sys.last_value = val
35383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        item = StackViewer.StackTreeItem(flist, tb)
35483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return RemoteObjectBrowser.remote_object_tree_item(item)
355