diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
index 70566d248c16..1c3f2a3ee69a 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
@@ -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 = '' % 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
#=======================================================================================================================
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_console.py b/python/helpers/pydev/_pydevd_bundle/pydevd_console.py
index d35cdc9df39d..b48daae2703a 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_console.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_console.py
@@ -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
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py b/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py
index 2b7783cbe8ca..dec84ed73369 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py
@@ -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)
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java
index 941e39343ba4..9090238a6a45 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java
@@ -30,7 +30,9 @@ public abstract class AbstractCommand {
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 {
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;
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetDescriptionCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetDescriptionCommand.java
new file mode 100644
index 000000000000..ca216c7eb02e
--- /dev/null
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetDescriptionCommand.java
@@ -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;
+ }
+}
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java
index 042b455f3f1b..9b3231974b93 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java
@@ -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()) {
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java
index 99c8908ab5c9..186dd53a569d 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java
@@ -87,6 +87,9 @@ public interface ProcessDebugger {
List getCompletions(String threadId, String frameId, String prefix);
+ String getDescription(String threadId, String frameId, String cmd);
+
+
void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory);
void removeExceptionBreakpoint(ExceptionBreakpointCommandFactory factory);
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java
index 457947dc9431..3149e42efa5e 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java
@@ -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));
diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
index 78ecbf99578b..f0a16fcb3b69 100644
--- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
+++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
@@ -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
diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
index b252994c0e15..75023a3f24b6 100644
--- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
+++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
@@ -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) {
}