PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Lib/idlelib/run.py

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