symbian-qemu-0.9.1-12/python-2.6.1/Lib/idlelib/run.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 import sys
       
     2 import linecache
       
     3 import time
       
     4 import socket
       
     5 import traceback
       
     6 import thread
       
     7 import threading
       
     8 import Queue
       
     9 
       
    10 import CallTips
       
    11 import AutoComplete
       
    12 
       
    13 import RemoteDebugger
       
    14 import RemoteObjectBrowser
       
    15 import StackViewer
       
    16 import rpc
       
    17 
       
    18 import __main__
       
    19 
       
    20 LOCALHOST = '127.0.0.1'
       
    21 
       
    22 try:
       
    23     import warnings
       
    24 except ImportError:
       
    25     pass
       
    26 else:
       
    27     def idle_formatwarning_subproc(message, category, filename, lineno,
       
    28                                    file=None, line=None):
       
    29         """Format warnings the IDLE way"""
       
    30         s = "\nWarning (from warnings module):\n"
       
    31         s += '  File \"%s\", line %s\n' % (filename, lineno)
       
    32         line = linecache.getline(filename, lineno).strip() \
       
    33             if line is None else line
       
    34         if line:
       
    35             s += "    %s\n" % line
       
    36         s += "%s: %s\n" % (category.__name__, message)
       
    37         return s
       
    38     warnings.formatwarning = idle_formatwarning_subproc
       
    39 
       
    40 # Thread shared globals: Establish a queue between a subthread (which handles
       
    41 # the socket) and the main thread (which runs user code), plus global
       
    42 # completion, exit and interruptable (the main thread) flags:
       
    43 
       
    44 exit_now = False
       
    45 quitting = False
       
    46 interruptable = False
       
    47 
       
    48 def main(del_exitfunc=False):
       
    49     """Start the Python execution server in a subprocess
       
    50 
       
    51     In the Python subprocess, RPCServer is instantiated with handlerclass
       
    52     MyHandler, which inherits register/unregister methods from RPCHandler via
       
    53     the mix-in class SocketIO.
       
    54 
       
    55     When the RPCServer 'server' is instantiated, the TCPServer initialization
       
    56     creates an instance of run.MyHandler and calls its handle() method.
       
    57     handle() instantiates a run.Executive object, passing it a reference to the
       
    58     MyHandler object.  That reference is saved as attribute rpchandler of the
       
    59     Executive instance.  The Executive methods have access to the reference and
       
    60     can pass it on to entities that they command
       
    61     (e.g. RemoteDebugger.Debugger.start_debugger()).  The latter, in turn, can
       
    62     call MyHandler(SocketIO) register/unregister methods via the reference to
       
    63     register and unregister themselves.
       
    64 
       
    65     """
       
    66     global exit_now
       
    67     global quitting
       
    68     global no_exitfunc
       
    69     no_exitfunc = del_exitfunc
       
    70     port = 8833
       
    71     #time.sleep(15) # test subprocess not responding
       
    72     if sys.argv[1:]:
       
    73         port = int(sys.argv[1])
       
    74     sys.argv[:] = [""]
       
    75     sockthread = threading.Thread(target=manage_socket,
       
    76                                   name='SockThread',
       
    77                                   args=((LOCALHOST, port),))
       
    78     sockthread.setDaemon(True)
       
    79     sockthread.start()
       
    80     while 1:
       
    81         try:
       
    82             if exit_now:
       
    83                 try:
       
    84                     exit()
       
    85                 except KeyboardInterrupt:
       
    86                     # exiting but got an extra KBI? Try again!
       
    87                     continue
       
    88             try:
       
    89                 seq, request = rpc.request_queue.get(block=True, timeout=0.05)
       
    90             except Queue.Empty:
       
    91                 continue
       
    92             method, args, kwargs = request
       
    93             ret = method(*args, **kwargs)
       
    94             rpc.response_queue.put((seq, ret))
       
    95         except KeyboardInterrupt:
       
    96             if quitting:
       
    97                 exit_now = True
       
    98             continue
       
    99         except SystemExit:
       
   100             raise
       
   101         except:
       
   102             type, value, tb = sys.exc_info()
       
   103             try:
       
   104                 print_exception()
       
   105                 rpc.response_queue.put((seq, None))
       
   106             except:
       
   107                 # Link didn't work, print same exception to __stderr__
       
   108                 traceback.print_exception(type, value, tb, file=sys.__stderr__)
       
   109                 exit()
       
   110             else:
       
   111                 continue
       
   112 
       
   113 def manage_socket(address):
       
   114     for i in range(3):
       
   115         time.sleep(i)
       
   116         try:
       
   117             server = MyRPCServer(address, MyHandler)
       
   118             break
       
   119         except socket.error, err:
       
   120             print>>sys.__stderr__,"IDLE Subprocess: socket error: "\
       
   121                                         + err[1] + ", retrying...."
       
   122     else:
       
   123         print>>sys.__stderr__, "IDLE Subprocess: Connection to "\
       
   124                                "IDLE GUI failed, exiting."
       
   125         show_socket_error(err, address)
       
   126         global exit_now
       
   127         exit_now = True
       
   128         return
       
   129     server.handle_request() # A single request only
       
   130 
       
   131 def show_socket_error(err, address):
       
   132     import Tkinter
       
   133     import tkMessageBox
       
   134     root = Tkinter.Tk()
       
   135     root.withdraw()
       
   136     if err[0] == 61: # connection refused
       
   137         msg = "IDLE's subprocess can't connect to %s:%d.  This may be due "\
       
   138               "to your personal firewall configuration.  It is safe to "\
       
   139               "allow this internal connection because no data is visible on "\
       
   140               "external ports." % address
       
   141         tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root)
       
   142     else:
       
   143         tkMessageBox.showerror("IDLE Subprocess Error", "Socket Error: %s" % err[1])
       
   144     root.destroy()
       
   145 
       
   146 def print_exception():
       
   147     import linecache
       
   148     linecache.checkcache()
       
   149     flush_stdout()
       
   150     efile = sys.stderr
       
   151     typ, val, tb = excinfo = sys.exc_info()
       
   152     sys.last_type, sys.last_value, sys.last_traceback = excinfo
       
   153     tbe = traceback.extract_tb(tb)
       
   154     print>>efile, '\nTraceback (most recent call last):'
       
   155     exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
       
   156                "RemoteDebugger.py", "bdb.py")
       
   157     cleanup_traceback(tbe, exclude)
       
   158     traceback.print_list(tbe, file=efile)
       
   159     lines = traceback.format_exception_only(typ, val)
       
   160     for line in lines:
       
   161         print>>efile, line,
       
   162 
       
   163 def cleanup_traceback(tb, exclude):
       
   164     "Remove excluded traces from beginning/end of tb; get cached lines"
       
   165     orig_tb = tb[:]
       
   166     while tb:
       
   167         for rpcfile in exclude:
       
   168             if tb[0][0].count(rpcfile):
       
   169                 break    # found an exclude, break for: and delete tb[0]
       
   170         else:
       
   171             break        # no excludes, have left RPC code, break while:
       
   172         del tb[0]
       
   173     while tb:
       
   174         for rpcfile in exclude:
       
   175             if tb[-1][0].count(rpcfile):
       
   176                 break
       
   177         else:
       
   178             break
       
   179         del tb[-1]
       
   180     if len(tb) == 0:
       
   181         # exception was in IDLE internals, don't prune!
       
   182         tb[:] = orig_tb[:]
       
   183         print>>sys.stderr, "** IDLE Internal Exception: "
       
   184     rpchandler = rpc.objecttable['exec'].rpchandler
       
   185     for i in range(len(tb)):
       
   186         fn, ln, nm, line = tb[i]
       
   187         if nm == '?':
       
   188             nm = "-toplevel-"
       
   189         if not line and fn.startswith("<pyshell#"):
       
   190             line = rpchandler.remotecall('linecache', 'getline',
       
   191                                               (fn, ln), {})
       
   192         tb[i] = fn, ln, nm, line
       
   193 
       
   194 def flush_stdout():
       
   195     try:
       
   196         if sys.stdout.softspace:
       
   197             sys.stdout.softspace = 0
       
   198             sys.stdout.write("\n")
       
   199     except (AttributeError, EOFError):
       
   200         pass
       
   201 
       
   202 def exit():
       
   203     """Exit subprocess, possibly after first deleting sys.exitfunc
       
   204 
       
   205     If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
       
   206     sys.exitfunc will be removed before exiting.  (VPython support)
       
   207 
       
   208     """
       
   209     if no_exitfunc:
       
   210         try:
       
   211             del sys.exitfunc
       
   212         except AttributeError:
       
   213             pass
       
   214     sys.exit(0)
       
   215 
       
   216 class MyRPCServer(rpc.RPCServer):
       
   217 
       
   218     def handle_error(self, request, client_address):
       
   219         """Override RPCServer method for IDLE
       
   220 
       
   221         Interrupt the MainThread and exit server if link is dropped.
       
   222 
       
   223         """
       
   224         global quitting
       
   225         try:
       
   226             raise
       
   227         except SystemExit:
       
   228             raise
       
   229         except EOFError:
       
   230             global exit_now
       
   231             exit_now = True
       
   232             thread.interrupt_main()
       
   233         except:
       
   234             erf = sys.__stderr__
       
   235             print>>erf, '\n' + '-'*40
       
   236             print>>erf, 'Unhandled server exception!'
       
   237             print>>erf, 'Thread: %s' % threading.currentThread().getName()
       
   238             print>>erf, 'Client Address: ', client_address
       
   239             print>>erf, 'Request: ', repr(request)
       
   240             traceback.print_exc(file=erf)
       
   241             print>>erf, '\n*** Unrecoverable, server exiting!'
       
   242             print>>erf, '-'*40
       
   243             quitting = True
       
   244             thread.interrupt_main()
       
   245 
       
   246 
       
   247 class MyHandler(rpc.RPCHandler):
       
   248 
       
   249     def handle(self):
       
   250         """Override base method"""
       
   251         executive = Executive(self)
       
   252         self.register("exec", executive)
       
   253         sys.stdin = self.console = self.get_remote_proxy("stdin")
       
   254         sys.stdout = self.get_remote_proxy("stdout")
       
   255         sys.stderr = self.get_remote_proxy("stderr")
       
   256         import IOBinding
       
   257         sys.stdin.encoding = sys.stdout.encoding = \
       
   258                              sys.stderr.encoding = IOBinding.encoding
       
   259         self.interp = self.get_remote_proxy("interp")
       
   260         rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
       
   261 
       
   262     def exithook(self):
       
   263         "override SocketIO method - wait for MainThread to shut us down"
       
   264         time.sleep(10)
       
   265 
       
   266     def EOFhook(self):
       
   267         "Override SocketIO method - terminate wait on callback and exit thread"
       
   268         global quitting
       
   269         quitting = True
       
   270         thread.interrupt_main()
       
   271 
       
   272     def decode_interrupthook(self):
       
   273         "interrupt awakened thread"
       
   274         global quitting
       
   275         quitting = True
       
   276         thread.interrupt_main()
       
   277 
       
   278 
       
   279 class Executive(object):
       
   280 
       
   281     def __init__(self, rpchandler):
       
   282         self.rpchandler = rpchandler
       
   283         self.locals = __main__.__dict__
       
   284         self.calltip = CallTips.CallTips()
       
   285         self.autocomplete = AutoComplete.AutoComplete()
       
   286 
       
   287     def runcode(self, code):
       
   288         global interruptable
       
   289         try:
       
   290             self.usr_exc_info = None
       
   291             interruptable = True
       
   292             try:
       
   293                 exec code in self.locals
       
   294             finally:
       
   295                 interruptable = False
       
   296         except:
       
   297             self.usr_exc_info = sys.exc_info()
       
   298             if quitting:
       
   299                 exit()
       
   300             # even print a user code SystemExit exception, continue
       
   301             print_exception()
       
   302             jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
       
   303             if jit:
       
   304                 self.rpchandler.interp.open_remote_stack_viewer()
       
   305         else:
       
   306             flush_stdout()
       
   307 
       
   308     def interrupt_the_server(self):
       
   309         if interruptable:
       
   310             thread.interrupt_main()
       
   311 
       
   312     def start_the_debugger(self, gui_adap_oid):
       
   313         return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
       
   314 
       
   315     def stop_the_debugger(self, idb_adap_oid):
       
   316         "Unregister the Idb Adapter.  Link objects and Idb then subject to GC"
       
   317         self.rpchandler.unregister(idb_adap_oid)
       
   318 
       
   319     def get_the_calltip(self, name):
       
   320         return self.calltip.fetch_tip(name)
       
   321 
       
   322     def get_the_completion_list(self, what, mode):
       
   323         return self.autocomplete.fetch_completions(what, mode)
       
   324 
       
   325     def stackviewer(self, flist_oid=None):
       
   326         if self.usr_exc_info:
       
   327             typ, val, tb = self.usr_exc_info
       
   328         else:
       
   329             return None
       
   330         flist = None
       
   331         if flist_oid is not None:
       
   332             flist = self.rpchandler.get_remote_proxy(flist_oid)
       
   333         while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
       
   334             tb = tb.tb_next
       
   335         sys.last_type = typ
       
   336         sys.last_value = val
       
   337         item = StackViewer.StackTreeItem(flist, tb)
       
   338         return RemoteObjectBrowser.remote_object_tree_item(item)