Make PyDev debugger independent from Thriftpy library

- Extract `get_ipython_hidden_vars()` and `console_exec()` methods from pydevconsole.py to pydev_console_integration.py.
- Make `DebugConsole` derive from `BaseCodeExecutor`.
This commit is contained in:
Alexander Koshevoy
2018-09-02 20:46:32 +03:00
parent 09a1da7eea
commit afe529a1f8
7 changed files with 517 additions and 351 deletions

View File

@@ -0,0 +1,224 @@
import sys
import traceback
from _pydev_bundle._pydev_calltip_util import get_description
from _pydev_bundle.pydev_imports import _queue
from _pydev_bundle.pydev_stdin import DebugConsoleStdIn
from _pydevd_bundle import pydevd_vars
# =======================================================================================================================
# BaseCodeExecutor
# =======================================================================================================================
class BaseCodeExecutor(object):
def __init__(self):
self.interruptable = False
self.exec_queue = _queue.Queue(0)
self.buffer = None
self.mpl_modules_for_patching = {}
self.init_mpl_modules_for_patching()
def get_greeting_msg(self):
return 'PyDev console: starting.\n'
def init_mpl_modules_for_patching(self):
from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot
self.mpl_modules_for_patching = {
"matplotlib": lambda: activate_matplotlib(self.enableGui),
"matplotlib.pyplot": activate_pyplot,
"pylab": activate_pylab
}
def need_more_for_code(self, source):
# PyDev-502: PyDev 3.9 F2 doesn't support backslash continuations
# Strangely even the IPython console is_complete said it was complete
# even with a continuation char at the end.
if source.endswith('\\'):
return True
if hasattr(self.interpreter, 'is_complete'):
return not self.interpreter.is_complete(source)
try:
code = self.interpreter.compile(source, '<input>', 'exec')
except (OverflowError, SyntaxError, ValueError):
# Case 1
return False
if code is None:
# Case 2
return True
# Case 3
return False
def need_more(self, code_fragment):
if self.buffer is None:
self.buffer = code_fragment
else:
self.buffer.append(code_fragment)
return self.need_more_for_code(self.buffer.text)
def create_std_in(self, debugger=None, original_std_in=None):
return DebugConsoleStdIn(dbg=debugger, original_stdin=original_std_in)
def add_exec(self, code_fragment, debugger=None):
original_in = sys.stdin
try:
help = None
if 'pydoc' in sys.modules:
pydoc = sys.modules['pydoc'] # Don't import it if it still is not there.
if hasattr(pydoc, 'help'):
# You never know how will the API be changed, so, let's code defensively here
help = pydoc.help
if not hasattr(help, 'input'):
help = None
except:
# Just ignore any error here
pass
more = False
try:
sys.stdin = self.create_std_in(debugger, original_in)
try:
if help is not None:
# This will enable the help() function to work.
try:
try:
help.input = sys.stdin
except AttributeError:
help._input = sys.stdin
except:
help = None
if not self._input_error_printed:
self._input_error_printed = True
sys.stderr.write('\nError when trying to update pydoc.help.input\n')
sys.stderr.write('(help() may not work -- please report this as a bug in the pydev bugtracker).\n\n')
traceback.print_exc()
try:
self.start_exec()
if hasattr(self, 'debugger'):
from _pydevd_bundle import pydevd_tracing
pydevd_tracing.SetTrace(self.debugger.trace_dispatch)
more = self.do_add_exec(code_fragment)
if hasattr(self, 'debugger'):
from _pydevd_bundle import pydevd_tracing
pydevd_tracing.SetTrace(None)
self.finish_exec(more)
finally:
if help is not None:
try:
try:
help.input = original_in
except AttributeError:
help._input = original_in
except:
pass
finally:
sys.stdin = original_in
except SystemExit:
raise
except:
traceback.print_exc()
return more
def do_add_exec(self, codeFragment):
'''
Subclasses should override.
@return: more (True if more input is needed to complete the statement and False if the statement is complete).
'''
raise NotImplementedError()
def get_namespace(self):
'''
Subclasses should override.
@return: dict with namespace.
'''
raise NotImplementedError()
def __resolve_reference__(self, text):
"""
:type text: str
"""
obj = None
if '.' not in text:
try:
obj = self.get_namespace()[text]
except KeyError:
pass
if obj is None:
try:
obj = self.get_namespace()['__builtins__'][text]
except:
pass
if obj is None:
try:
obj = getattr(self.get_namespace()['__builtins__'], text, None)
except:
pass
else:
try:
last_dot = text.rindex('.')
parent_context = text[0:last_dot]
res = pydevd_vars.eval_in_context(parent_context, self.get_namespace(), self.get_namespace())
obj = getattr(res, text[last_dot + 1:])
except:
pass
return obj
def getDescription(self, text):
try:
obj = self.__resolve_reference__(text)
if obj is None:
return ''
return get_description(obj)
except:
return ''
def start_exec(self):
self.interruptable = True
def finish_exec(self, more):
self.interruptable = False
return True
def enableGui(self, guiname):
''' Enable the GUI specified in guiname (see inputhook for list).
As with IPython, enabling multiple GUIs isn't an error, but
only the last one's main loop runs and it may not work
'''
def do_enable_gui():
from _pydev_bundle.pydev_versioncheck import versionok_for_gui
if versionok_for_gui():
try:
from pydev_ipython.inputhook import enable_gui
enable_gui(guiname)
except:
sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname)
traceback.print_exc()
elif guiname not in ['none', '', None]:
# Only print a warning if the guiname was going to do something
sys.stderr.write("PyDev console: Python version does not support GUI event loop integration for '%s'\n" % guiname)
# Return value does not matter, so return back what was sent
return guiname
# Important: it has to be really enabled in the main thread, so, schedule
# it to run in the main thread.
self.exec_queue.put(do_enable_gui)
def get_ipython_hidden_vars_dict(self):
return None

View File

@@ -3,9 +3,9 @@ import sys
import traceback import traceback
from _pydev_bundle import _pydev_imports_tipper from _pydev_bundle import _pydev_imports_tipper
from _pydev_bundle._pydev_calltip_util import get_description from _pydev_bundle.pydev_code_executor import BaseCodeExecutor
from _pydev_bundle.pydev_console_types import CodeFragment from _pydev_bundle.pydev_console_types import CodeFragment
from _pydev_bundle.pydev_imports import _queue, Exec from _pydev_bundle.pydev_imports import Exec
from _pydev_bundle.pydev_stdin import StdIn, DebugConsoleStdIn from _pydev_bundle.pydev_stdin import StdIn, DebugConsoleStdIn
from _pydev_imps._pydev_saved_modules import thread from _pydev_imps._pydev_saved_modules import thread
from _pydevd_bundle import pydevd_thrift from _pydevd_bundle import pydevd_thrift
@@ -88,195 +88,25 @@ class Null:
# ======================================================================================================================= # =======================================================================================================================
# BaseInterpreterInterface # BaseInterpreterInterface
# ======================================================================================================================= # =======================================================================================================================
class BaseInterpreterInterface: class BaseInterpreterInterface(BaseCodeExecutor):
def __init__(self, mainThread, connect_status_queue=None, rpc_client=None): def __init__(self, mainThread, connect_status_queue=None, rpc_client=None):
super(BaseInterpreterInterface, self).__init__()
self.mainThread = mainThread self.mainThread = mainThread
self.interruptable = False
self.exec_queue = _queue.Queue(0)
self.buffer = None
self.banner_shown = False self.banner_shown = False
self.connect_status_queue = connect_status_queue self.connect_status_queue = connect_status_queue
self.mpl_modules_for_patching = {}
self.init_mpl_modules_for_patching()
self.rpc_client = rpc_client self.rpc_client = rpc_client
def build_banner(self): def build_banner(self):
return 'print({0})\n'.format(repr(self.get_greeting_msg())) return 'print({0})\n'.format(repr(self.get_greeting_msg()))
def get_greeting_msg(self):
return 'PyDev console: starting.\n'
def init_mpl_modules_for_patching(self):
from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot
self.mpl_modules_for_patching = {
"matplotlib": lambda: activate_matplotlib(self.enableGui),
"matplotlib.pyplot": activate_pyplot,
"pylab": activate_pylab
}
def need_more_for_code(self, source):
# PyDev-502: PyDev 3.9 F2 doesn't support backslash continuations
# Strangely even the IPython console is_complete said it was complete
# even with a continuation char at the end.
if source.endswith('\\'):
return True
if hasattr(self.interpreter, 'is_complete'):
return not self.interpreter.is_complete(source)
try:
code = self.interpreter.compile(source, '<input>', 'exec')
except (OverflowError, SyntaxError, ValueError):
# Case 1
return False
if code is None:
# Case 2
return True
# Case 3
return False
def need_more(self, code_fragment):
if self.buffer is None:
self.buffer = code_fragment
else:
self.buffer.append(code_fragment)
return self.need_more_for_code(self.buffer.text)
def create_std_in(self, debugger=None, original_std_in=None): def create_std_in(self, debugger=None, original_std_in=None):
if debugger is None: if debugger is None:
return StdIn(self, self.rpc_client, original_stdin=original_std_in) return StdIn(self, self.rpc_client, original_stdin=original_std_in)
else: else:
return DebugConsoleStdIn(dbg=debugger, original_stdin=original_std_in) return DebugConsoleStdIn(dbg=debugger, original_stdin=original_std_in)
def add_exec(self, code_fragment, debugger=None):
original_in = sys.stdin
try:
help = None
if 'pydoc' in sys.modules:
pydoc = sys.modules['pydoc'] # Don't import it if it still is not there.
if hasattr(pydoc, 'help'):
# You never know how will the API be changed, so, let's code defensively here
help = pydoc.help
if not hasattr(help, 'input'):
help = None
except:
# Just ignore any error here
pass
more = False
try:
sys.stdin = self.create_std_in(debugger, original_in)
try:
if help is not None:
# This will enable the help() function to work.
try:
try:
help.input = sys.stdin
except AttributeError:
help._input = sys.stdin
except:
help = None
if not self._input_error_printed:
self._input_error_printed = True
sys.stderr.write('\nError when trying to update pydoc.help.input\n')
sys.stderr.write('(help() may not work -- please report this as a bug in the pydev bugtracker).\n\n')
traceback.print_exc()
try:
self.start_exec()
if hasattr(self, 'debugger'):
from _pydevd_bundle import pydevd_tracing
pydevd_tracing.SetTrace(self.debugger.trace_dispatch)
more = self.do_add_exec(code_fragment)
if hasattr(self, 'debugger'):
from _pydevd_bundle import pydevd_tracing
pydevd_tracing.SetTrace(None)
self.finish_exec(more)
finally:
if help is not None:
try:
try:
help.input = original_in
except AttributeError:
help._input = original_in
except:
pass
finally:
sys.stdin = original_in
except SystemExit:
raise
except:
traceback.print_exc()
return more
def do_add_exec(self, codeFragment):
'''
Subclasses should override.
@return: more (True if more input is needed to complete the statement and False if the statement is complete).
'''
raise NotImplementedError()
def get_namespace(self):
'''
Subclasses should override.
@return: dict with namespace.
'''
raise NotImplementedError()
def __resolve_reference__(self, text):
"""
:type text: str
"""
obj = None
if '.' not in text:
try:
obj = self.get_namespace()[text]
except KeyError:
pass
if obj is None:
try:
obj = self.get_namespace()['__builtins__'][text]
except:
pass
if obj is None:
try:
obj = getattr(self.get_namespace()['__builtins__'], text, None)
except:
pass
else:
try:
last_dot = text.rindex('.')
parent_context = text[0:last_dot]
res = pydevd_vars.eval_in_context(parent_context, self.get_namespace(), self.get_namespace())
obj = getattr(res, text[last_dot + 1:])
except:
pass
return obj
def getDescription(self, text):
try:
obj = self.__resolve_reference__(text)
if obj is None:
return ''
return get_description(obj)
except:
return ''
def do_exec_code(self, code, is_single_line): def do_exec_code(self, code, is_single_line):
try: try:
code_fragment = CodeFragment(code, is_single_line) code_fragment = CodeFragment(code, is_single_line)
@@ -359,9 +189,6 @@ class BaseInterpreterInterface:
def close(self): def close(self):
sys.exit(0) sys.exit(0)
def start_exec(self):
self.interruptable = True
def get_server(self): def get_server(self):
if getattr(self, 'rpc_client', None) is not None: if getattr(self, 'rpc_client', None) is not None:
return self.rpc_client return self.rpc_client
@@ -574,33 +401,6 @@ class BaseInterpreterInterface:
# Don't care what the input string is # Don't care what the input string is
return ("Hello eclipse",) return ("Hello eclipse",)
def enableGui(self, guiname):
''' Enable the GUI specified in guiname (see inputhook for list).
As with IPython, enabling multiple GUIs isn't an error, but
only the last one's main loop runs and it may not work
'''
def do_enable_gui():
from _pydev_bundle.pydev_versioncheck import versionok_for_gui
if versionok_for_gui():
try:
from pydev_ipython.inputhook import enable_gui
enable_gui(guiname)
except:
sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname)
traceback.print_exc()
elif guiname not in ['none', '', None]:
# Only print a warning if the guiname was going to do something
sys.stderr.write("PyDev console: Python version does not support GUI event loop integration for '%s'\n" % guiname)
# Return value does not matter, so return back what was sent
return guiname
# Important: it has to be really enabled in the main thread, so, schedule
# it to run in the main thread.
self.exec_queue.put(do_enable_gui)
def get_ipython_hidden_vars_dict(self):
return None
# ======================================================================================================================= # =======================================================================================================================
# FakeFrame # FakeFrame

View File

@@ -0,0 +1,76 @@
import sys
import traceback
from _pydev_bundle.pydev_code_executor import BaseCodeExecutor
from _pydev_bundle.pydev_ipython_console_011 import get_pydev_frontend
from _pydevd_bundle.pydevd_constants import dict_iter_items
# Uncomment to force PyDev standard shell.
# raise ImportError()
# TODO reuse `CodeExecutor` in `InterpreterInterface` in pydev_ipython_console.py
#=======================================================================================================================
# CodeExecutor
#=======================================================================================================================
class CodeExecutor(BaseCodeExecutor):
'''
The methods in this class should be registered in the xml-rpc server.
'''
def __init__(self, show_banner=True, rpc_client=None):
super(CodeExecutor, self).__init__()
self.interpreter = get_pydev_frontend(rpc_client)
self._input_error_printed = False
self.notification_succeeded = False
self.notification_tries = 0
self.notification_max_tries = 3
self.show_banner = show_banner
def get_greeting_msg(self):
if self.show_banner:
self.interpreter.show_banner()
return self.interpreter.get_greeting_msg()
def do_add_exec(self, code_fragment):
self.notify_about_magic()
if code_fragment.text.rstrip().endswith('??'):
print('IPython-->')
try:
res = bool(self.interpreter.add_exec(code_fragment.text))
finally:
if code_fragment.text.rstrip().endswith('??'):
print('<--IPython')
return res
def get_namespace(self):
return self.interpreter.get_namespace()
def close(self):
sys.exit(0)
def notify_about_magic(self):
pass
def get_ipython_hidden_vars_dict(self):
try:
if hasattr(self.interpreter, 'ipython') and hasattr(self.interpreter.ipython, 'user_ns_hidden'):
user_ns_hidden = self.interpreter.ipython.user_ns_hidden
if isinstance(user_ns_hidden, dict):
# Since IPython 2 dict `user_ns_hidden` contains hidden variables and values
user_hidden_dict = user_ns_hidden.copy()
else:
# In IPython 1.x `user_ns_hidden` used to be a set with names of hidden variables
user_hidden_dict = dict([(key, val) for key, val in dict_iter_items(self.interpreter.ipython.user_ns)
if key in user_ns_hidden])
# while `_`, `__` and `___` were not initialized, they are not presented in `user_ns_hidden`
user_hidden_dict.setdefault('_', '')
user_hidden_dict.setdefault('__', '')
user_hidden_dict.setdefault('___', '')
return user_hidden_dict
except:
# Getting IPython variables shouldn't break loading frame variables
traceback.print_exc()

View File

@@ -77,7 +77,7 @@ if IS_IRONPYTHON:
def unquote(s): def unquote(s):
return s return s
import pydevconsole from _pydevd_bundle import pydevd_console_integration
from _pydevd_bundle import pydevd_vars from _pydevd_bundle import pydevd_vars
from _pydevd_bundle import pydevd_xml from _pydevd_bundle import pydevd_xml
from _pydevd_bundle import pydevd_tracing from _pydevd_bundle import pydevd_tracing
@@ -1125,7 +1125,7 @@ class InternalGetFrame(InternalThreadCommand):
try: try:
frame = pydevd_vars.find_frame(self.thread_id, self.frame_id) frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
if frame is not None: if frame is not None:
hidden_ns = pydevconsole.get_ipython_hidden_vars() hidden_ns = pydevd_console_integration.get_ipython_hidden_vars()
xml = "<xml>" xml = "<xml>"
xml += pydevd_xml.frame_vars_to_xml(frame.f_locals, hidden_ns) xml += pydevd_xml.frame_vars_to_xml(frame.f_locals, hidden_ns)
del frame del frame
@@ -1443,7 +1443,7 @@ class InternalConsoleExec(InternalThreadCommand):
#don't trace new threads created by console command #don't trace new threads created by console command
disable_trace_thread_modules() disable_trace_thread_modules()
result = pydevconsole.console_exec(self.thread_id, self.frame_id, self.expression, dbg) result = pydevd_console_integration.console_exec(self.thread_id, self.frame_id, self.expression, dbg)
xml = "<xml>" xml = "<xml>"
xml += pydevd_xml.var_to_xml(result, "") xml += pydevd_xml.var_to_xml(result, "")
xml += "</xml>" xml += "</xml>"

View File

@@ -5,7 +5,7 @@ import traceback
from code import InteractiveConsole from code import InteractiveConsole
from _pydev_bundle import _pydev_completer from _pydev_bundle import _pydev_completer
from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface from _pydev_bundle.pydev_code_executor import BaseCodeExecutor
from _pydev_bundle.pydev_imports import Exec from _pydev_bundle.pydev_imports import Exec
from _pydev_bundle.pydev_override import overrides from _pydev_bundle.pydev_override import overrides
from _pydev_bundle.pydev_stdin import BaseStdIn from _pydev_bundle.pydev_stdin import BaseStdIn
@@ -75,12 +75,12 @@ class DebugConsoleStdIn(BaseStdIn):
#======================================================================================================================= #=======================================================================================================================
# DebugConsole # DebugConsole
#======================================================================================================================= #=======================================================================================================================
class DebugConsole(InteractiveConsole, BaseInterpreterInterface): class DebugConsole(InteractiveConsole, BaseCodeExecutor):
"""Wrapper around code.InteractiveConsole, in order to send """Wrapper around code.InteractiveConsole, in order to send
errors and outputs to the debug console errors and outputs to the debug console
""" """
overrides(BaseInterpreterInterface.create_std_in) overrides(BaseCodeExecutor.create_std_in)
def create_std_in(self, *args, **kwargs): def create_std_in(self, *args, **kwargs):
try: try:
if not self.__buffer_output: if not self.__buffer_output:
@@ -135,7 +135,7 @@ class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
return more, [], [] return more, [], []
overrides(BaseInterpreterInterface.do_add_exec) overrides(BaseCodeExecutor.do_add_exec)
def do_add_exec(self, line): def do_add_exec(self, line):
return InteractiveConsole.push(self, line) return InteractiveConsole.push(self, line)

View File

@@ -0,0 +1,203 @@
try:
from code import InteractiveConsole
except ImportError:
from _pydevd_bundle.pydevconsole_code_for_ironpython import InteractiveConsole
import os
import sys
import traceback
from code import InteractiveInterpreter, InteractiveConsole
from code import compile_command
from _pydev_bundle.pydev_code_executor import BaseCodeExecutor
from _pydev_bundle.pydev_console_types import CodeFragment, Command
from _pydev_bundle.pydev_imports import Exec
from _pydevd_bundle import pydevd_vars, pydevd_save_locals
try:
import __builtin__
except:
import builtins as __builtin__ # @UnresolvedImport
class CodeExecutor(BaseCodeExecutor):
def __init__(self):
super(CodeExecutor, self).__init__()
self.namespace = {}
self.interpreter = InteractiveConsole(self.namespace)
def do_add_exec(self, codeFragment):
command = Command(self.interpreter, codeFragment)
command.run()
return command.more
def get_namespace(self):
return self.namespace
if 'IPYTHONENABLE' in os.environ:
IPYTHON = os.environ['IPYTHONENABLE'] == 'True'
else:
IPYTHON = True
try:
try:
exitfunc = sys.exitfunc
except AttributeError:
exitfunc = None
if IPYTHON:
from _pydev_bundle.pydev_ipython_code_executor import CodeExecutor
if exitfunc is not None:
sys.exitfunc = exitfunc
else:
try:
delattr(sys, 'exitfunc')
except:
pass
except:
IPYTHON = False
pass
def get_ipython_hidden_vars():
if IPYTHON and hasattr(__builtin__, 'interpreter'):
code_executor = get_code_executor()
return code_executor.get_ipython_hidden_vars_dict()
def get_code_executor():
try:
code_executor = getattr(__builtin__, 'interpreter')
except AttributeError:
code_executor = CodeExecutor()
__builtin__.interpreter = code_executor
print(code_executor.get_greeting_msg())
return code_executor
# ===============================================================================
# Debugger integration
# ===============================================================================
def exec_code(code, globals, locals, debugger):
code_executor = get_code_executor()
code_executor.interpreter.update(globals, locals)
res = code_executor.need_more(code)
if res:
return True
code_executor.add_exec(code, debugger)
return False
class ConsoleWriter(InteractiveInterpreter):
skip = 0
def __init__(self, locals=None):
InteractiveInterpreter.__init__(self, locals)
def write(self, data):
# if (data.find("global_vars") == -1 and data.find("pydevd") == -1):
if self.skip > 0:
self.skip -= 1
else:
if data == "Traceback (most recent call last):\n":
self.skip = 1
sys.stderr.write(data)
def showsyntaxerror(self, filename=None):
"""Display the syntax error that just occurred."""
# Override for avoid using sys.excepthook PY-12600
type, value, tb = sys.exc_info()
sys.last_type = type
sys.last_value = value
sys.last_traceback = tb
if filename and type is SyntaxError:
# Work hard to stuff the correct filename in the exception
try:
msg, (dummy_filename, lineno, offset, line) = value.args
except ValueError:
# Not the format we expect; leave it alone
pass
else:
# Stuff in the right filename
value = SyntaxError(msg, (filename, lineno, offset, line))
sys.last_value = value
list = traceback.format_exception_only(type, value)
sys.stderr.write(''.join(list))
def showtraceback(self):
"""Display the exception that just occurred."""
# Override for avoid using sys.excepthook PY-12600
try:
type, value, tb = sys.exc_info()
sys.last_type = type
sys.last_value = value
sys.last_traceback = tb
tblist = traceback.extract_tb(tb)
del tblist[:1]
lines = traceback.format_list(tblist)
if lines:
lines.insert(0, "Traceback (most recent call last):\n")
lines.extend(traceback.format_exception_only(type, value))
finally:
tblist = tb = None
sys.stderr.write(''.join(lines))
def console_exec(thread_id, frame_id, expression, dbg):
"""returns 'False' in case expression is partially correct
"""
frame = pydevd_vars.find_frame(thread_id, frame_id)
is_multiline = expression.count('@LINE@') > 1
try:
expression = str(expression.replace('@LINE@', '\n'))
except UnicodeEncodeError as e:
expression = expression.replace('@LINE@', '\n')
# Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
# (Names not resolved in generator expression in method)
# See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
updated_globals = {}
updated_globals.update(frame.f_globals)
updated_globals.update(frame.f_locals) # locals later because it has precedence over the actual globals
if IPYTHON:
need_more = exec_code(CodeFragment(expression), updated_globals, frame.f_locals, dbg)
if not need_more:
pydevd_save_locals.save_locals(frame)
return need_more
interpreter = ConsoleWriter()
if not is_multiline:
try:
code = compile_command(expression)
except (OverflowError, SyntaxError, ValueError):
# Case 1
interpreter.showsyntaxerror()
return False
if code is None:
# Case 2
return True
else:
code = expression
# Case 3
try:
Exec(code, updated_globals, frame.f_locals)
except SystemExit:
raise
except:
interpreter.showtraceback()
else:
pydevd_save_locals.save_locals(frame)
return False

View File

@@ -12,9 +12,6 @@ try:
except ImportError: except ImportError:
from _pydevd_bundle.pydevconsole_code_for_ironpython import InteractiveConsole from _pydevd_bundle.pydevconsole_code_for_ironpython import InteractiveConsole
from code import compile_command
from code import InteractiveInterpreter
import os import os
import sys import sys
@@ -22,13 +19,10 @@ from _pydev_imps._pydev_saved_modules import threading
from _pydevd_bundle.pydevd_constants import INTERACTIVE_MODE_AVAILABLE, dict_keys from _pydevd_bundle.pydevd_constants import INTERACTIVE_MODE_AVAILABLE, dict_keys
from _pydevd_bundle.pydevd_utils import save_main_module from _pydevd_bundle.pydevd_utils import save_main_module
import traceback
from _pydev_bundle import fix_getpass from _pydev_bundle import fix_getpass
fix_getpass.fix_getpass() fix_getpass.fix_getpass()
from _pydevd_bundle import pydevd_vars, pydevd_save_locals from _pydev_bundle.pydev_imports import _queue
from _pydev_bundle.pydev_imports import Exec, _queue
try: try:
import __builtin__ import __builtin__
@@ -37,7 +31,7 @@ except:
from _pydev_bundle.pydev_stdin import BaseStdIn from _pydev_bundle.pydev_stdin import BaseStdIn
from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface
from _pydev_bundle.pydev_console_types import CodeFragment, Command from _pydev_bundle.pydev_console_types import Command
IS_PYTHON_3_ONWARDS = sys.version_info[0] >= 3 IS_PYTHON_3_ONWARDS = sys.version_info[0] >= 3
IS_PY24 = sys.version_info[0] == 2 and sys.version_info[1] == 4 IS_PY24 = sys.version_info[0] == 2 and sys.version_info[1] == 4
@@ -330,12 +324,6 @@ def start_client(host, port):
process_exec_queue(interpreter) process_exec_queue(interpreter)
def get_ipython_hidden_vars():
if IPYTHON and hasattr(__builtin__, 'interpreter'):
interpreter = get_interpreter()
return interpreter.get_ipython_hidden_vars_dict()
def get_interpreter(): def get_interpreter():
try: try:
interpreterInterface = getattr(__builtin__, 'interpreter') interpreterInterface = getattr(__builtin__, 'interpreter')
@@ -354,131 +342,6 @@ def get_completions(text, token, globals, locals):
return interpreterInterface.getCompletions(text, token) return interpreterInterface.getCompletions(text, token)
#===============================================================================
# Debugger integration
#===============================================================================
def exec_code(code, globals, locals, debugger):
interpreterInterface = get_interpreter()
interpreterInterface.interpreter.update(globals, locals)
res = interpreterInterface.need_more(code)
if res:
return True
interpreterInterface.add_exec(code, debugger)
return False
class ConsoleWriter(InteractiveInterpreter):
skip = 0
def __init__(self, locals=None):
InteractiveInterpreter.__init__(self, locals)
def write(self, data):
#if (data.find("global_vars") == -1 and data.find("pydevd") == -1):
if self.skip > 0:
self.skip -= 1
else:
if data == "Traceback (most recent call last):\n":
self.skip = 1
sys.stderr.write(data)
def showsyntaxerror(self, filename=None):
"""Display the syntax error that just occurred."""
#Override for avoid using sys.excepthook PY-12600
type, value, tb = sys.exc_info()
sys.last_type = type
sys.last_value = value
sys.last_traceback = tb
if filename and type is SyntaxError:
# Work hard to stuff the correct filename in the exception
try:
msg, (dummy_filename, lineno, offset, line) = value.args
except ValueError:
# Not the format we expect; leave it alone
pass
else:
# Stuff in the right filename
value = SyntaxError(msg, (filename, lineno, offset, line))
sys.last_value = value
list = traceback.format_exception_only(type, value)
sys.stderr.write(''.join(list))
def showtraceback(self):
"""Display the exception that just occurred."""
#Override for avoid using sys.excepthook PY-12600
try:
type, value, tb = sys.exc_info()
sys.last_type = type
sys.last_value = value
sys.last_traceback = tb
tblist = traceback.extract_tb(tb)
del tblist[:1]
lines = traceback.format_list(tblist)
if lines:
lines.insert(0, "Traceback (most recent call last):\n")
lines.extend(traceback.format_exception_only(type, value))
finally:
tblist = tb = None
sys.stderr.write(''.join(lines))
def console_exec(thread_id, frame_id, expression, dbg):
"""returns 'False' in case expression is partially correct
"""
frame = pydevd_vars.find_frame(thread_id, frame_id)
is_multiline = expression.count('@LINE@') > 1
try:
expression = str(expression.replace('@LINE@', '\n'))
except UnicodeEncodeError as e:
expression = expression.replace('@LINE@', '\n')
#Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
#(Names not resolved in generator expression in method)
#See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
updated_globals = {}
updated_globals.update(frame.f_globals)
updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
if IPYTHON:
need_more = exec_code(CodeFragment(expression), updated_globals, frame.f_locals, dbg)
if not need_more:
pydevd_save_locals.save_locals(frame)
return need_more
interpreter = ConsoleWriter()
if not is_multiline:
try:
code = compile_command(expression)
except (OverflowError, SyntaxError, ValueError):
# Case 1
interpreter.showsyntaxerror()
return False
if code is None:
# Case 2
return True
else:
code = expression
#Case 3
try:
Exec(code, updated_globals, frame.f_locals)
except SystemExit:
raise
except:
interpreter.showtraceback()
else:
pydevd_save_locals.save_locals(frame)
return False
#======================================================================================================================= #=======================================================================================================================
# main # main