pydevconsole.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. """
  2. Entry point module to start the interactive console.
  3. """
  4. from _pydev_bundle._pydev_saved_modules import thread, _code
  5. from _pydevd_bundle.pydevd_constants import IS_JYTHON
  6. start_new_thread = thread.start_new_thread
  7. from _pydevd_bundle.pydevconsole_code import InteractiveConsole
  8. compile_command = _code.compile_command
  9. InteractiveInterpreter = _code.InteractiveInterpreter
  10. import os
  11. import sys
  12. from _pydev_bundle._pydev_saved_modules import threading
  13. from _pydevd_bundle.pydevd_constants import INTERACTIVE_MODE_AVAILABLE
  14. import traceback
  15. from _pydev_bundle import pydev_log
  16. from _pydevd_bundle import pydevd_save_locals
  17. from _pydev_bundle.pydev_imports import Exec, _queue
  18. import builtins as __builtin__
  19. from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface, BaseStdIn # @UnusedImport
  20. from _pydev_bundle.pydev_console_utils import CodeFragment
  21. class Command:
  22. def __init__(self, interpreter, code_fragment):
  23. """
  24. :type code_fragment: CodeFragment
  25. :type interpreter: InteractiveConsole
  26. """
  27. self.interpreter = interpreter
  28. self.code_fragment = code_fragment
  29. self.more = None
  30. def symbol_for_fragment(code_fragment):
  31. if code_fragment.is_single_line:
  32. symbol = "single"
  33. else:
  34. if IS_JYTHON:
  35. symbol = "single" # Jython doesn't support exec
  36. else:
  37. symbol = "exec"
  38. return symbol
  39. symbol_for_fragment = staticmethod(symbol_for_fragment)
  40. def run(self):
  41. text = self.code_fragment.text
  42. symbol = self.symbol_for_fragment(self.code_fragment)
  43. self.more = self.interpreter.runsource(text, "<input>", symbol)
  44. try:
  45. from _pydev_bundle.pydev_imports import execfile
  46. __builtin__.execfile = execfile
  47. except:
  48. pass
  49. # Pull in runfile, the interface to UMD that wraps execfile
  50. from _pydev_bundle.pydev_umd import runfile, _set_globals_function
  51. if sys.version_info[0] >= 3:
  52. __builtin__.runfile = runfile
  53. else:
  54. __builtin__.runfile = runfile
  55. # =======================================================================================================================
  56. # InterpreterInterface
  57. # =======================================================================================================================
  58. class InterpreterInterface(BaseInterpreterInterface):
  59. """
  60. The methods in this class should be registered in the xml-rpc server.
  61. """
  62. def __init__(self, host, client_port, mainThread, connect_status_queue=None):
  63. BaseInterpreterInterface.__init__(self, mainThread, connect_status_queue)
  64. self.client_port = client_port
  65. self.host = host
  66. self.namespace = {}
  67. self.interpreter = InteractiveConsole(self.namespace)
  68. self._input_error_printed = False
  69. def do_add_exec(self, codeFragment):
  70. command = Command(self.interpreter, codeFragment)
  71. command.run()
  72. return command.more
  73. def get_namespace(self):
  74. return self.namespace
  75. def getCompletions(self, text, act_tok):
  76. try:
  77. from _pydev_bundle._pydev_completer import Completer
  78. completer = Completer(self.namespace, None)
  79. return completer.complete(act_tok)
  80. except:
  81. pydev_log.exception()
  82. return []
  83. def close(self):
  84. sys.exit(0)
  85. def get_greeting_msg(self):
  86. return "PyDev console: starting.\n"
  87. class _ProcessExecQueueHelper:
  88. _debug_hook = None
  89. _return_control_osc = False
  90. def set_debug_hook(debug_hook):
  91. _ProcessExecQueueHelper._debug_hook = debug_hook
  92. def activate_mpl_if_already_imported(interpreter):
  93. if interpreter.mpl_modules_for_patching:
  94. for module in list(interpreter.mpl_modules_for_patching):
  95. if module in sys.modules:
  96. activate_function = interpreter.mpl_modules_for_patching.pop(module)
  97. activate_function()
  98. def init_set_return_control_back(interpreter):
  99. from pydev_ipython.inputhook import set_return_control_callback
  100. def return_control():
  101. """A function that the inputhooks can call (via inputhook.stdin_ready()) to find
  102. out if they should cede control and return"""
  103. if _ProcessExecQueueHelper._debug_hook:
  104. # Some of the input hooks check return control without doing
  105. # a single operation, so we don't return True on every
  106. # call when the debug hook is in place to allow the GUI to run
  107. # XXX: Eventually the inputhook code will have diverged enough
  108. # from the IPython source that it will be worthwhile rewriting
  109. # it rather than pretending to maintain the old API
  110. _ProcessExecQueueHelper._return_control_osc = not _ProcessExecQueueHelper._return_control_osc
  111. if _ProcessExecQueueHelper._return_control_osc:
  112. return True
  113. if not interpreter.exec_queue.empty():
  114. return True
  115. return False
  116. set_return_control_callback(return_control)
  117. def init_mpl_in_console(interpreter):
  118. init_set_return_control_back(interpreter)
  119. if not INTERACTIVE_MODE_AVAILABLE:
  120. return
  121. activate_mpl_if_already_imported(interpreter)
  122. from _pydev_bundle.pydev_import_hook import import_hook_manager
  123. for mod in list(interpreter.mpl_modules_for_patching):
  124. import_hook_manager.add_module_name(mod, interpreter.mpl_modules_for_patching.pop(mod))
  125. if sys.platform != "win32":
  126. if not hasattr(os, "kill"): # Jython may not have it.
  127. def pid_exists(pid):
  128. return True
  129. else:
  130. def pid_exists(pid):
  131. # Note that this function in the face of errors will conservatively consider that
  132. # the pid is still running (because we'll exit the current process when it's
  133. # no longer running, so, we need to be 100% sure it actually exited).
  134. import errno
  135. if pid == 0:
  136. # According to "man 2 kill" PID 0 has a special meaning:
  137. # it refers to <<every process in the process group of the
  138. # calling process>> so we don't want to go any further.
  139. # If we get here it means this UNIX platform *does* have
  140. # a process with id 0.
  141. return True
  142. try:
  143. os.kill(pid, 0)
  144. except OSError as err:
  145. if err.errno == errno.ESRCH:
  146. # ESRCH == No such process
  147. return False
  148. elif err.errno == errno.EPERM:
  149. # EPERM clearly means there's a process to deny access to
  150. return True
  151. else:
  152. # According to "man 2 kill" possible error values are
  153. # (EINVAL, EPERM, ESRCH) therefore we should never get
  154. # here. If we do, although it's an error, consider it
  155. # exists (see first comment in this function).
  156. return True
  157. else:
  158. return True
  159. else:
  160. def pid_exists(pid):
  161. # Note that this function in the face of errors will conservatively consider that
  162. # the pid is still running (because we'll exit the current process when it's
  163. # no longer running, so, we need to be 100% sure it actually exited).
  164. import ctypes
  165. kernel32 = ctypes.windll.kernel32
  166. PROCESS_QUERY_INFORMATION = 0x0400
  167. PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
  168. ERROR_INVALID_PARAMETER = 0x57
  169. STILL_ACTIVE = 259
  170. process = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, 0, pid)
  171. if not process:
  172. err = kernel32.GetLastError()
  173. if err == ERROR_INVALID_PARAMETER:
  174. # Means it doesn't exist (pid parameter is wrong).
  175. return False
  176. # There was some unexpected error (such as access denied), so
  177. # consider it exists (although it could be something else, but we don't want
  178. # to raise any errors -- so, just consider it exists).
  179. return True
  180. try:
  181. zero = ctypes.c_int(0)
  182. exit_code = ctypes.pointer(zero)
  183. exit_code_suceeded = kernel32.GetExitCodeProcess(process, exit_code)
  184. if not exit_code_suceeded:
  185. # There was some unexpected error (such as access denied), so
  186. # consider it exists (although it could be something else, but we don't want
  187. # to raise any errors -- so, just consider it exists).
  188. return True
  189. elif bool(exit_code.contents.value) and int(exit_code.contents.value) != STILL_ACTIVE:
  190. return False
  191. finally:
  192. kernel32.CloseHandle(process)
  193. return True
  194. def process_exec_queue(interpreter):
  195. init_mpl_in_console(interpreter)
  196. from pydev_ipython.inputhook import get_inputhook
  197. try:
  198. kill_if_pid_not_alive = int(os.environ.get("PYDEV_ECLIPSE_PID", "-1"))
  199. except:
  200. kill_if_pid_not_alive = -1
  201. while 1:
  202. if kill_if_pid_not_alive != -1:
  203. if not pid_exists(kill_if_pid_not_alive):
  204. exit()
  205. # Running the request may have changed the inputhook in use
  206. inputhook = get_inputhook()
  207. if _ProcessExecQueueHelper._debug_hook:
  208. _ProcessExecQueueHelper._debug_hook()
  209. if inputhook:
  210. try:
  211. # Note: it'll block here until return_control returns True.
  212. inputhook()
  213. except:
  214. pydev_log.exception()
  215. try:
  216. try:
  217. code_fragment = interpreter.exec_queue.get(block=True, timeout=1 / 20.0) # 20 calls/second
  218. except _queue.Empty:
  219. continue
  220. if callable(code_fragment):
  221. # It can be a callable (i.e.: something that must run in the main
  222. # thread can be put in the queue for later execution).
  223. code_fragment()
  224. else:
  225. more = interpreter.add_exec(code_fragment)
  226. except KeyboardInterrupt:
  227. interpreter.buffer = None
  228. continue
  229. except SystemExit:
  230. raise
  231. except:
  232. pydev_log.exception("Error processing queue on pydevconsole.")
  233. exit()
  234. if "IPYTHONENABLE" in os.environ:
  235. IPYTHON = os.environ["IPYTHONENABLE"] == "True"
  236. else:
  237. # By default, don't use IPython because occasionally changes
  238. # in IPython break pydevd.
  239. IPYTHON = False
  240. try:
  241. try:
  242. exitfunc = sys.exitfunc
  243. except AttributeError:
  244. exitfunc = None
  245. if IPYTHON:
  246. from _pydev_bundle.pydev_ipython_console import InterpreterInterface
  247. if exitfunc is not None:
  248. sys.exitfunc = exitfunc
  249. else:
  250. try:
  251. delattr(sys, "exitfunc")
  252. except:
  253. pass
  254. except:
  255. IPYTHON = False
  256. pass
  257. # =======================================================================================================================
  258. # _DoExit
  259. # =======================================================================================================================
  260. def do_exit(*args):
  261. """
  262. We have to override the exit because calling sys.exit will only actually exit the main thread,
  263. and as we're in a Xml-rpc server, that won't work.
  264. """
  265. try:
  266. import java.lang.System
  267. java.lang.System.exit(1)
  268. except ImportError:
  269. if len(args) == 1:
  270. os._exit(args[0])
  271. else:
  272. os._exit(0)
  273. # =======================================================================================================================
  274. # start_console_server
  275. # =======================================================================================================================
  276. def start_console_server(host, port, interpreter):
  277. try:
  278. if port == 0:
  279. host = ""
  280. # I.e.: supporting the internal Jython version in PyDev to create a Jython interactive console inside Eclipse.
  281. from _pydev_bundle.pydev_imports import SimpleXMLRPCServer as XMLRPCServer # @Reimport
  282. try:
  283. server = XMLRPCServer((host, port), logRequests=False, allow_none=True)
  284. except:
  285. sys.stderr.write(
  286. 'Error starting server with host: "%s", port: "%s", client_port: "%s"\n' % (host, port, interpreter.client_port)
  287. )
  288. sys.stderr.flush()
  289. raise
  290. # Tell UMD the proper default namespace
  291. _set_globals_function(interpreter.get_namespace)
  292. server.register_function(interpreter.execLine)
  293. server.register_function(interpreter.execMultipleLines)
  294. server.register_function(interpreter.getCompletions)
  295. server.register_function(interpreter.getFrame)
  296. server.register_function(interpreter.getVariable)
  297. server.register_function(interpreter.changeVariable)
  298. server.register_function(interpreter.getDescription)
  299. server.register_function(interpreter.close)
  300. server.register_function(interpreter.interrupt)
  301. server.register_function(interpreter.handshake)
  302. server.register_function(interpreter.connectToDebugger)
  303. server.register_function(interpreter.hello)
  304. server.register_function(interpreter.getArray)
  305. server.register_function(interpreter.evaluate)
  306. server.register_function(interpreter.ShowConsole)
  307. server.register_function(interpreter.loadFullValue)
  308. # Functions for GUI main loop integration
  309. server.register_function(interpreter.enableGui)
  310. if port == 0:
  311. (h, port) = server.socket.getsockname()
  312. print(port)
  313. print(interpreter.client_port)
  314. while True:
  315. try:
  316. server.serve_forever()
  317. except:
  318. # Ugly code to be py2/3 compatible
  319. # https://sw-brainwy.rhcloud.com/tracker/PyDev/534:
  320. # Unhandled "interrupted system call" error in the pydevconsol.py
  321. e = sys.exc_info()[1]
  322. retry = False
  323. try:
  324. retry = e.args[0] == 4 # errno.EINTR
  325. except:
  326. pass
  327. if not retry:
  328. raise
  329. # Otherwise, keep on going
  330. return server
  331. except:
  332. pydev_log.exception()
  333. # Notify about error to avoid long waiting
  334. connection_queue = interpreter.get_connect_status_queue()
  335. if connection_queue is not None:
  336. connection_queue.put(False)
  337. def start_server(host, port, client_port):
  338. # replace exit (see comments on method)
  339. # note that this does not work in jython!!! (sys method can't be replaced).
  340. sys.exit = do_exit
  341. interpreter = InterpreterInterface(host, client_port, threading.current_thread())
  342. start_new_thread(start_console_server, (host, port, interpreter))
  343. process_exec_queue(interpreter)
  344. def get_ipython_hidden_vars():
  345. if IPYTHON and hasattr(__builtin__, "interpreter"):
  346. interpreter = get_interpreter()
  347. return interpreter.get_ipython_hidden_vars_dict()
  348. def get_interpreter():
  349. try:
  350. interpreterInterface = getattr(__builtin__, "interpreter")
  351. except AttributeError:
  352. interpreterInterface = InterpreterInterface(None, None, threading.current_thread())
  353. __builtin__.interpreter = interpreterInterface
  354. sys.stderr.write(interpreterInterface.get_greeting_msg())
  355. sys.stderr.flush()
  356. return interpreterInterface
  357. def get_completions(text, token, globals, locals):
  358. interpreterInterface = get_interpreter()
  359. interpreterInterface.interpreter.update(globals, locals)
  360. return interpreterInterface.getCompletions(text, token)
  361. # ===============================================================================
  362. # Debugger integration
  363. # ===============================================================================
  364. def exec_code(code, globals, locals, debugger):
  365. interpreterInterface = get_interpreter()
  366. interpreterInterface.interpreter.update(globals, locals)
  367. res = interpreterInterface.need_more(code)
  368. if res:
  369. return True
  370. interpreterInterface.add_exec(code, debugger)
  371. return False
  372. class ConsoleWriter(InteractiveInterpreter):
  373. skip = 0
  374. def __init__(self, locals=None):
  375. InteractiveInterpreter.__init__(self, locals)
  376. def write(self, data):
  377. # if (data.find("global_vars") == -1 and data.find("pydevd") == -1):
  378. if self.skip > 0:
  379. self.skip -= 1
  380. else:
  381. if data == "Traceback (most recent call last):\n":
  382. self.skip = 1
  383. sys.stderr.write(data)
  384. def showsyntaxerror(self, filename=None):
  385. """Display the syntax error that just occurred."""
  386. # Override for avoid using sys.excepthook PY-12600
  387. type, value, tb = sys.exc_info()
  388. sys.last_type = type
  389. sys.last_value = value
  390. sys.last_traceback = tb
  391. if filename and type is SyntaxError:
  392. # Work hard to stuff the correct filename in the exception
  393. try:
  394. msg, (dummy_filename, lineno, offset, line) = value.args
  395. except ValueError:
  396. # Not the format we expect; leave it alone
  397. pass
  398. else:
  399. # Stuff in the right filename
  400. value = SyntaxError(msg, (filename, lineno, offset, line))
  401. sys.last_value = value
  402. list = traceback.format_exception_only(type, value)
  403. sys.stderr.write("".join(list))
  404. def showtraceback(self, *args, **kwargs):
  405. """Display the exception that just occurred."""
  406. # Override for avoid using sys.excepthook PY-12600
  407. try:
  408. type, value, tb = sys.exc_info()
  409. sys.last_type = type
  410. sys.last_value = value
  411. sys.last_traceback = tb
  412. tblist = traceback.extract_tb(tb)
  413. del tblist[:1]
  414. lines = traceback.format_list(tblist)
  415. if lines:
  416. lines.insert(0, "Traceback (most recent call last):\n")
  417. lines.extend(traceback.format_exception_only(type, value))
  418. finally:
  419. tblist = tb = None
  420. sys.stderr.write("".join(lines))
  421. def console_exec(thread_id, frame_id, expression, dbg):
  422. """returns 'False' in case expression is partially correct"""
  423. frame = dbg.find_frame(thread_id, frame_id)
  424. is_multiline = expression.count("@LINE@") > 1
  425. expression = str(expression.replace("@LINE@", "\n"))
  426. # Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
  427. # (Names not resolved in generator expression in method)
  428. # See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
  429. updated_globals = {}
  430. updated_globals.update(frame.f_globals)
  431. updated_globals.update(frame.f_locals) # locals later because it has precedence over the actual globals
  432. if IPYTHON:
  433. need_more = exec_code(CodeFragment(expression), updated_globals, frame.f_locals, dbg)
  434. if not need_more:
  435. pydevd_save_locals.save_locals(frame)
  436. return need_more
  437. interpreter = ConsoleWriter()
  438. if not is_multiline:
  439. try:
  440. code = compile_command(expression)
  441. except (OverflowError, SyntaxError, ValueError):
  442. # Case 1
  443. interpreter.showsyntaxerror()
  444. return False
  445. if code is None:
  446. # Case 2
  447. return True
  448. else:
  449. code = expression
  450. # Case 3
  451. try:
  452. Exec(code, updated_globals, frame.f_locals)
  453. except SystemExit:
  454. raise
  455. except:
  456. interpreter.showtraceback()
  457. else:
  458. pydevd_save_locals.save_locals(frame)
  459. return False
  460. # =======================================================================================================================
  461. # main
  462. # =======================================================================================================================
  463. if __name__ == "__main__":
  464. # Important: don't use this module directly as the __main__ module, rather, import itself as pydevconsole
  465. # so that we don't get multiple pydevconsole modules if it's executed directly (otherwise we'd have multiple
  466. # representations of its classes).
  467. # See: https://sw-brainwy.rhcloud.com/tracker/PyDev/446:
  468. # 'Variables' and 'Expressions' views stopped working when debugging interactive console
  469. import pydevconsole
  470. sys.stdin = pydevconsole.BaseStdIn(sys.stdin)
  471. port, client_port = sys.argv[1:3]
  472. from _pydev_bundle import pydev_localhost
  473. if int(port) == 0 and int(client_port) == 0:
  474. (h, p) = pydev_localhost.get_socket_name()
  475. client_port = p
  476. pydevconsole.start_server(pydev_localhost.get_localhost(), int(port), int(client_port))