home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / run.py < prev    next >
Text File  |  2003-12-30  |  9KB  |  287 lines

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