home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / python2.5 / idlelib / run.py < prev    next >
Encoding:
Python Source  |  2007-05-02  |  10.6 KB  |  328 lines

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