home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 14 / hacker14.iso / programacao / pythonwin / python.exe / RUN.PY < prev    next >
Encoding:
Text File  |  2003-06-22  |  9.3 KB  |  286 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 = sys.exc_info()
  115.     tbe = traceback.extract_tb(tb)
  116.     print >>efile, '\nTraceback (most recent call last):'
  117.     exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
  118.                "RemoteDebugger.py", "bdb.py")
  119.     cleanup_traceback(tbe, exclude)
  120.     traceback.print_list(tbe, file=efile)
  121.     lines = traceback.format_exception_only(typ, val)
  122.     for line in lines:
  123.         print>>efile, line,
  124.  
  125. def cleanup_traceback(tb, exclude):
  126.     "Remove excluded traces from beginning/end of tb; get cached lines"
  127.     orig_tb = tb[:]
  128.     while tb:
  129.         for rpcfile in exclude:
  130.             if tb[0][0].count(rpcfile):
  131.                 break    # found an exclude, break for: and delete tb[0]
  132.         else:
  133.             break        # no excludes, have left RPC code, break while:
  134.         del tb[0]
  135.     while tb:
  136.         for rpcfile in exclude:
  137.             if tb[-1][0].count(rpcfile):
  138.                 break
  139.         else:
  140.             break
  141.         del tb[-1]
  142.     if len(tb) == 0:
  143.         # exception was in IDLE internals, don't prune!
  144.         tb[:] = orig_tb[:]
  145.         print>>sys.stderr, "** IDLE Internal Exception: "
  146.     rpchandler = rpc.objecttable['exec'].rpchandler
  147.     for i in range(len(tb)):
  148.         fn, ln, nm, line = tb[i]
  149.         if nm == '?':
  150.             nm = "-toplevel-"
  151.         if not line and fn.startswith("<pyshell#"):
  152.             line = rpchandler.remotecall('linecache', 'getline',
  153.                                               (fn, ln), {})
  154.         tb[i] = fn, ln, nm, line
  155.  
  156. def flush_stdout():
  157.     try:
  158.         if sys.stdout.softspace:
  159.             sys.stdout.softspace = 0
  160.             sys.stdout.write("\n")
  161.     except (AttributeError, EOFError):
  162.         pass
  163.  
  164. def exit():
  165.     """Exit subprocess, possibly after first deleting sys.exitfunc
  166.  
  167.     If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
  168.     sys.exitfunc will be removed before exiting.  (VPython support)
  169.  
  170.     """
  171.     if no_exitfunc:
  172.         del sys.exitfunc
  173.     sys.exit(0)
  174.  
  175. class MyRPCServer(rpc.RPCServer):
  176.  
  177.     def handle_error(self, request, client_address):
  178.         """Override RPCServer method for IDLE
  179.  
  180.         Interrupt the MainThread and exit server if link is dropped.
  181.  
  182.         """
  183.         try:
  184.             raise
  185.         except SystemExit:
  186.             raise
  187.         except EOFError:
  188.             global exit_now
  189.             exit_now = True
  190.             thread.interrupt_main()
  191.         except:
  192.             erf = sys.__stderr__
  193.             print>>erf, '\n' + '-'*40
  194.             print>>erf, 'Unhandled server exception!'
  195.             print>>erf, 'Thread: %s' % threading.currentThread().getName()
  196.             print>>erf, 'Client Address: ', client_address
  197.             print>>erf, 'Request: ', repr(request)
  198.             traceback.print_exc(file=erf)
  199.             print>>erf, '\n*** Unrecoverable, server exiting!'
  200.             print>>erf, '-'*40
  201.             exit()
  202.  
  203.  
  204. class MyHandler(rpc.RPCHandler):
  205.  
  206.     def handle(self):
  207.         """Override base method"""
  208.         executive = Executive(self)
  209.         self.register("exec", executive)
  210.         sys.stdin = self.console = self.get_remote_proxy("stdin")
  211.         sys.stdout = self.get_remote_proxy("stdout")
  212.         sys.stderr = self.get_remote_proxy("stderr")
  213.         import IOBinding
  214.         sys.stdin.encoding = sys.stdout.encoding = \
  215.                              sys.stderr.encoding = IOBinding.encoding
  216.         self.interp = self.get_remote_proxy("interp")
  217.         rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
  218.  
  219.     def exithook(self):
  220.         "override SocketIO method - wait for MainThread to shut us down"
  221.         time.sleep(10)
  222.  
  223.     def EOFhook(self):
  224.         "Override SocketIO method - terminate wait on callback and exit thread"
  225.         global quitting
  226.         quitting = True
  227.         thread.interrupt_main()
  228.  
  229.     def decode_interrupthook(self):
  230.         "interrupt awakened thread"
  231.         global quitting
  232.         quitting = True
  233.         thread.interrupt_main()
  234.  
  235.  
  236. class Executive:
  237.  
  238.     def __init__(self, rpchandler):
  239.         self.rpchandler = rpchandler
  240.         self.locals = __main__.__dict__
  241.         self.calltip = CallTips.CallTips()
  242.  
  243.     def runcode(self, code):
  244.         try:
  245.             self.usr_exc_info = None
  246.             exec code in self.locals
  247.         except:
  248.             self.usr_exc_info = sys.exc_info()
  249.             if quitting:
  250.                 exit()
  251.             # even print a user code SystemExit exception, continue
  252.             print_exception()
  253.             jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
  254.             if jit:
  255.                 self.rpchandler.interp.open_remote_stack_viewer()
  256.         else:
  257.             flush_stdout()
  258.  
  259.     def interrupt_the_server(self):
  260.         thread.interrupt_main()
  261.  
  262.     def start_the_debugger(self, gui_adap_oid):
  263.         return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
  264.  
  265.     def stop_the_debugger(self, idb_adap_oid):
  266.         "Unregister the Idb Adapter.  Link objects and Idb then subject to GC"
  267.         self.rpchandler.unregister(idb_adap_oid)
  268.  
  269.     def get_the_calltip(self, name):
  270.         return self.calltip.fetch_tip(name)
  271.  
  272.     def stackviewer(self, flist_oid=None):
  273.         if self.usr_exc_info:
  274.             typ, val, tb = self.usr_exc_info
  275.         else:
  276.             return None
  277.         flist = None
  278.         if flist_oid is not None:
  279.             flist = self.rpchandler.get_remote_proxy(flist_oid)
  280.         while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
  281.             tb = tb.tb_next
  282.         sys.last_type = typ
  283.         sys.last_value = val
  284.         item = StackViewer.StackTreeItem(flist, tb)
  285.         return RemoteObjectBrowser.remote_object_tree_item(item)
  286.