--handle getDescription in debugger

This commit is contained in:
fitermay
2016-08-28 20:59:20 -04:00
parent e1aa4eac1f
commit 70db0e9bbf
10 changed files with 149 additions and 11 deletions
@@ -139,6 +139,7 @@ CMD_STEP_INTO_MY_CODE = 144
CMD_GET_CONCURRENCY_EVENT = 145
CMD_SHOW_RETURN_VALUES = 146
CMD_INPUT_REQUESTED = 147
CMD_GET_DESCRIPTION = 148
CMD_VERSION = 501
CMD_RETURN = 502
@@ -193,6 +194,7 @@ ID_TO_MEANING = {
'145': 'CMD_GET_CONCURRENCY_EVENT',
'146': 'CMD_SHOW_RETURN_VALUES',
'147': 'CMD_INPUT_REQUESTED',
'148': 'CMD_GET_DESCRIPTION',
'501': 'CMD_VERSION',
'502': 'CMD_RETURN',
@@ -700,6 +702,12 @@ class NetCommandFactory:
except Exception:
return self.make_error_message(seq, get_exception_traceback_str())
def make_get_description_message(self, seq, payload):
try:
return NetCommand(CMD_GET_DESCRIPTION, seq, payload)
except Exception:
return self.make_error_message(seq, get_exception_traceback_str())
def make_get_frame_message(self, seq, payload):
try:
return NetCommand(CMD_GET_FRAME, seq, payload)
@@ -1135,6 +1143,36 @@ class InternalGetCompletions(InternalThreadCommand):
cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating expression " + exc)
dbg.writer.add_command(cmd)
# =======================================================================================================================
# InternalGetDescription
# =======================================================================================================================
class InternalGetDescription(InternalThreadCommand):
""" Fetch the variable description stub from the debug console
"""
def __init__(self, seq, thread_id, frame_id, expression):
self.sequence = seq
self.thread_id = thread_id
self.frame_id = frame_id
self.expression = expression
def do_it(self, dbg):
""" Get completions and write back to the client
"""
try:
frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
description = pydevd_console.get_description(frame, self.thread_id, self.frame_id, self.expression)
description = pydevd_vars.make_valid_xml_value(quote(description, '/>_= \t'))
description_xml = '<xml><var name="" type="" value="%s"/></xml>' % description
cmd = dbg.cmd_factory.make_get_description_message(self.sequence, description_xml)
dbg.writer.add_command(cmd)
except:
exc = get_exception_traceback_str()
cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in fetching description" + exc)
dbg.writer.add_command(cmd)
#=======================================================================================================================
# InternalGetBreakpointException
#=======================================================================================================================
@@ -1,17 +1,17 @@
'''An helper file for the pydev debugger (REPL) console
'''
from code import InteractiveConsole
import sys
import traceback
from code import InteractiveConsole
from _pydev_bundle import _pydev_completer
from _pydevd_bundle.pydevd_tracing import get_exception_traceback_str
from _pydevd_bundle.pydevd_vars import make_valid_xml_value
from _pydev_bundle.pydev_imports import Exec
from _pydevd_bundle.pydevd_io import IOBuf
from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface, BaseStdIn
from _pydev_bundle.pydev_imports import Exec
from _pydev_bundle.pydev_override import overrides
from _pydevd_bundle import pydevd_save_locals
from _pydevd_bundle.pydevd_io import IOBuf
from _pydevd_bundle.pydevd_tracing import get_exception_traceback_str
from _pydevd_bundle.pydevd_vars import make_valid_xml_value
CONSOLE_OUTPUT = "output"
CONSOLE_ERROR = "error"
@@ -160,6 +160,12 @@ class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
except:
self.showtraceback()
def get_namespace(self):
dbg_namespace = {}
dbg_namespace.update(self.frame.f_globals)
dbg_namespace.update(self.frame.f_locals) # locals later because it has precedence over the actual globals
return dbg_namespace
#=======================================================================================================================
# InteractiveConsoleCache
@@ -175,6 +181,7 @@ class InteractiveConsoleCache:
def get_interactive_console(thread_id, frame_id, frame, console_message):
"""returns the global interactive console.
interactive console should have been initialized by this time
:rtype: DebugConsole
"""
if InteractiveConsoleCache.thread_id == thread_id and InteractiveConsoleCache.frame_id == frame_id:
return InteractiveConsoleCache.interactive_console_instance
@@ -218,6 +225,16 @@ def execute_console_command(frame, thread_id, frame_id, line, buffer_output=True
return console_message
def get_description(frame, thread_id, frame_id, expression):
console_message = ConsoleMessage()
interpreter = get_interactive_console(thread_id, frame_id, frame, console_message)
try:
interpreter.frame = frame
return interpreter.getDescription(expression)
finally:
interpreter.frame = None
def get_completions(frame, act_tok):
""" fetch all completions, create xml for the same
return the completions xml
@@ -16,11 +16,10 @@ from _pydevd_bundle.pydevd_comm import CMD_RUN, CMD_VERSION, CMD_LIST_THREADS, C
CMD_SET_PY_EXCEPTION, CMD_GET_FILE_CONTENTS, CMD_SET_PROPERTY_TRACE, CMD_ADD_EXCEPTION_BREAK, \
CMD_REMOVE_EXCEPTION_BREAK, CMD_LOAD_SOURCE, CMD_ADD_DJANGO_EXCEPTION_BREAK, CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \
CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression, InternalConsoleGetCompletions, \
CMD_RUN_CUSTOM_OPERATION, InternalRunCustomOperation, CMD_IGNORE_THROWN_EXCEPTION_AT, CMD_ENABLE_DONT_TRACE,\
CMD_SHOW_RETURN_VALUES, ID_TO_MEANING
CMD_RUN_CUSTOM_OPERATION, InternalRunCustomOperation, CMD_IGNORE_THROWN_EXCEPTION_AT, CMD_ENABLE_DONT_TRACE, \
CMD_SHOW_RETURN_VALUES, ID_TO_MEANING, CMD_GET_DESCRIPTION, InternalGetDescription
from _pydevd_bundle.pydevd_constants import get_thread_id, IS_PY3K, DebugInfoHolder, dict_contains, dict_keys, dict_pop, \
STATE_RUN
import pydevd_file_utils
def process_net_command(py_db, cmd_id, seq, text):
@@ -229,6 +228,14 @@ def process_net_command(py_db, cmd_id, seq, text):
except:
traceback.print_exc()
elif cmd_id == CMD_GET_DESCRIPTION:
try:
thread_id, frame_id, expression = text.split('\t', 2)
int_cmd = InternalGetDescription(seq, thread_id, frame_id, expression)
py_db.post_internal_command(int_cmd, thread_id)
except:
traceback.print_exc()
elif cmd_id == CMD_GET_FRAME:
thread_id, frame_id, scope = text.split('\t', 2)
@@ -30,7 +30,9 @@ public abstract class AbstractCommand<T> {
public static final int LOAD_SOURCE = 124;
public static final int SMART_STEP_INTO = 128;
public static final int EXIT = 129;
public static final int GET_DESCRIPTION = 148;
public static final int CALL_SIGNATURE_TRACE = 130;
public static final int CMD_SET_PY_EXCEPTION = 131;
@@ -52,6 +54,7 @@ public abstract class AbstractCommand<T> {
public static final int SHOW_RETURN_VALUES = 146;
public static final int INPUT_REQUESTED = 147;
public static final int ERROR = 901;
public static final int VERSION = 501;
@@ -0,0 +1,47 @@
package com.jetbrains.python.debugger.pydev;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyDebuggerException;
/**
* @author traff
*/
public class GetDescriptionCommand extends AbstractFrameCommand {
private String myActionToken;
private String result = null;
public GetDescriptionCommand(final RemoteDebugger debugger, String threadId, String frameId, final String myActionToken) {
super(debugger, GET_DESCRIPTION, threadId, frameId);
this.myActionToken = myActionToken;
}
@Override
public boolean isResponseExpected() {
return true;
}
@Override
protected void processResponse(ProtocolFrame response) throws PyDebuggerException {
super.processResponse(response);
try {
PyDebugValue pyDebugValue = ProtocolParser.parseValue(response.getPayload(), getDebugger().getDebugProcess());
result = pyDebugValue.getValue();
}
catch (Exception e) {
throw new PyDebuggerException("cant obtain completions", e);
}
}
@Override
protected void buildPayload(Payload payload) {
super.buildPayload(payload);
payload.add(myActionToken);
}
public String getResult() {
return result;
}
}
@@ -518,6 +518,11 @@ public class MultiProcessDebugger implements ProcessDebugger {
return debugger(threadId).getCompletions(threadId, frameId, prefix);
}
@Override
public String getDescription(String threadId, String frameId, String cmd) {
return debugger(threadId).getDescription(threadId, frameId, cmd);
}
@Override
public void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory) {
for (RemoteDebugger d : allDebuggers()) {
@@ -87,6 +87,9 @@ public interface ProcessDebugger {
List<PydevCompletionVariant> getCompletions(String threadId, String frameId, String prefix);
String getDescription(String threadId, String frameId, String cmd);
void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory);
void removeExceptionBreakpoint(ExceptionBreakpointCommandFactory factory);
@@ -761,6 +761,13 @@ public class RemoteDebugger implements ProcessDebugger {
return command.getCompletions();
}
@Override
public String getDescription(String threadId, String frameId, String cmd) {
final GetDescriptionCommand command = new GetDescriptionCommand(this, threadId, frameId, cmd);
execute(command);
return command.getResult();
}
@Override
public void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory) {
execute(factory.createAddCommand(this));
@@ -55,8 +55,8 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio
}
@Override
public String getDescription(String text) {
return null;
public String getDescription(String refExpression) throws Exception {
return myDebugProcess.getDescription(refExpression);
}
@Override
@@ -902,6 +902,17 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
return Lists.newArrayList();
}
@NotNull
public String getDescription(String prefix) throws Exception {
if (isConnected()) {
dropFrameCaches();
final PyStackFrame frame = currentFrame();
return myDebugger.getDescription(frame.getThreadId(), frame.getFrameId(), prefix);
}
return "";
}
@Override
public void startNotified(ProcessEvent event) {
}