Implement get variable for console variables view.

This commit is contained in:
Dmitry Trofimov
2013-09-08 18:44:40 +02:00
parent 9a15c3cb49
commit 0924cafc8c
8 changed files with 158 additions and 96 deletions
@@ -31,7 +31,7 @@ class InterpreterInterface(BaseInterpreterInterface):
self.interpreter = PyDevFrontEnd()
self._input_error_printed = False
self.notification_succeeded = False
self.notification_tries = 0;
self.notification_tries = 0
self.notification_max_tries = 3
self.notify_about_magic()
@@ -101,11 +101,9 @@ class InterpreterInterface(BaseInterpreterInterface):
traceback.print_exc()
return []
def close(self):
sys.exit(0)
def ipython_editor(self, file, line):
server = self.get_server()
+86 -1
View File
@@ -3,10 +3,14 @@ try:
except ImportError:
from pydevconsole_code_for_ironpython import InteractiveConsole
from code import compile_command
from code import InteractiveInterpreter
import os
import sys
from pydevd_constants import USE_LIB_COPY
from pydevd_utils import *
if USE_LIB_COPY:
import _pydev_threading as threading
@@ -18,6 +22,12 @@ import fix_getpass
fix_getpass.fixGetpass()
import pydevd_xml
import pydevd_vars
try:
from pydevd_exec import Exec
except:
from pydevd_exec2 import Exec
try:
if USE_LIB_COPY:
@@ -171,6 +181,21 @@ class InterpreterInterface(BaseInterpreterInterface):
xml += "</xml>"
return xml
def getVariable(self, attributes):
xml = "<xml>"
valDict = pydevd_vars.resolveVar(self.namespace, attributes)
if valDict is None:
valDict = {}
keys = valDict.keys()
for k in keys:
xml += pydevd_vars.varToXML(valDict[k], to_string(k))
xml += "</xml>"
return xml
def close(self):
sys.exit(0)
@@ -274,6 +299,7 @@ def start_server(host, port, interpreter):
server.register_function(interpreter.execLine)
server.register_function(interpreter.getCompletions)
server.register_function(interpreter.getFrame)
server.register_function(interpreter.getVariable)
server.register_function(interpreter.getDescription)
server.register_function(interpreter.close)
server.register_function(interpreter.interrupt)
@@ -332,7 +358,7 @@ def get_completions(text, token, globals, locals):
return interpreterInterface.getCompletions(text, token)
def get_frame(globals, locals):
def get_frame():
return interpreterInterface.getFrame()
def exec_expression(expression, globals, locals):
@@ -363,6 +389,65 @@ def read_line(s):
return ret
# Debugger integration
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 consoleExec(thread_id, frame_id, expression):
"""returns 'False' in case expression is partialy correct
"""
frame = pydevd_vars.findFrame(thread_id, frame_id)
expression = str(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:
return exec_expression(expression, updated_globals, frame.f_locals)
interpreter = ConsoleWriter()
try:
code = compile_command(expression)
except (OverflowError, SyntaxError, ValueError):
# Case 1
interpreter.showsyntaxerror()
return False
if code is None:
# Case 2
return True
#Case 3
try:
Exec(code, updated_globals, frame.f_locals)
except SystemExit:
raise
except:
interpreter.showtraceback()
return False
#=======================================================================================================================
# main
#=======================================================================================================================
+1 -1
View File
@@ -905,7 +905,7 @@ class InternalConsoleExec(InternalThreadCommand):
thread.start_new_thread = thread._original_start_new_thread #don't trace new threads created by console command
thread.start_new = thread._original_start_new_thread
result = pydevd_vars.consoleExec(self.thread_id, self.frame_id, self.expression)
result = pydevconsole.consoleExec(self.thread_id, self.frame_id, self.expression)
xml = "<xml>"
xml += pydevd_vars.varToXML(result, "")
xml += "</xml>"
+18 -64
View File
@@ -5,9 +5,7 @@ import pickle
from django_frame import DjangoTemplateFrame
from pydevd_constants import * #@UnusedWildImport
from types import * #@UnusedWildImport
from code import compile_command
from code import InteractiveInterpreter
import pydevconsole
from pydevd_xml import *
try:
@@ -54,9 +52,6 @@ if USE_PSYCO_OPTIMIZATION:
if hasattr(sys, 'exc_clear'): #jython does not have it
sys.exc_clear() #don't keep the traceback -- clients don't want to see it
def iterFrames(initialFrame):
"""NO-YIELD VERSION: Iterates through all the frames starting at the specified frame (which will be the first returned item)"""
#cannot use yield
@@ -161,6 +156,7 @@ def resolveCompoundVariable(thread_id, frame_id, scope, attrs):
return {}
attrList = attrs.split('\t')
if scope == "GLOBAL":
var = frame.f_globals
del attrList[0] # globals are special, and they get a single dummy unused attribute
@@ -181,6 +177,22 @@ def resolveCompoundVariable(thread_id, frame_id, scope, attrs):
return resolver.getDictionary(var)
except:
traceback.print_exc()
def resolveVar(var, attrs):
attrList = attrs.split('\t')
for k in attrList:
type, _typeName, resolver = getType(var)
var = resolver.resolve(var, k)
try:
type, _typeName, resolver = getType(var)
return resolver.getDictionary(var)
except:
traceback.print_exc()
def evaluateExpression(thread_id, frame_id, expression, doExec):
"""returns the result of the evaluated expression
@@ -241,64 +253,6 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
del updated_globals
del frame
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 consoleExec(thread_id, frame_id, expression):
"""returns 'False' in case expression is partialy correct
"""
frame = findFrame(thread_id, frame_id)
expression = str(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 pydevconsole.IPYTHON:
return pydevconsole.exec_expression(expression, updated_globals, frame.f_locals)
interpreter = ConsoleWriter()
try:
code = compile_command(expression)
except (OverflowError, SyntaxError, ValueError):
# Case 1
interpreter.showsyntaxerror()
return False
if code is None:
# Case 2
return True
#Case 3
try:
Exec(code, updated_globals, frame.f_locals)
except SystemExit:
raise
except:
interpreter.showtraceback()
return False
def changeAttrExpression(thread_id, frame_id, attr, expression):
"""Changes some attribute in a given frame.
@note: it will not (currently) work if we're not in the topmost frame (that's a python
@@ -8,11 +8,19 @@ public class GetVariableCommand extends GetFrameCommand {
private final String myVariableName;
private final PyDebugValue myParent;
public GetVariableCommand(final RemoteDebugger debugger, final String threadId, final String frameId, final String variableName,
PyDebugValue parent) {
public GetVariableCommand(final RemoteDebugger debugger, final String threadId, final String frameId, PyDebugValue var) {
super(debugger, GET_VARIABLE, threadId, frameId);
myVariableName = variableName;
myParent = parent;
myVariableName = composeName(var);
myParent = var;
}
public static String composeName(final PyDebugValue var) {
final StringBuilder sb = new StringBuilder(var.getTempName());
PyDebugValue p = var;
while ((p = p.getParent()) != null) {
sb.insert(0, '\t').insert(0, p.getTempName());
}
return sb.toString();
}
@Override
@@ -143,7 +143,7 @@ public class RemoteDebugger implements ProcessDebugger {
@Override
public XValueChildrenList loadVariable(final String threadId, final String frameId, final PyDebugValue var) throws PyDebuggerException {
setTempVariable(threadId, frameId, var);
final GetVariableCommand command = new GetVariableCommand(this, threadId, frameId, composeName(var), var);
final GetVariableCommand command = new GetVariableCommand(this, threadId, frameId, var);
command.execute();
return command.getVariables();
}
@@ -182,15 +182,6 @@ public class RemoteDebugger implements ProcessDebugger {
myTempVars.clear();
}
private static String composeName(final PyDebugValue var) {
final StringBuilder sb = new StringBuilder(var.getTempName());
PyDebugValue p = var;
while ((p = p.getParent()) != null) {
sb.insert(0, '\t').insert(0, p.getTempName());
}
return sb.toString();
}
// todo: change variable in lists doesn't work - either fix in pydevd or format var name appropriately
private void setTempVariable(final String threadId, final String frameId, final PyDebugValue var) {
final PyDebugValue topVar = var.getTopParent();
@@ -18,8 +18,9 @@ import com.jetbrains.python.console.parsing.PythonConsoleData;
import com.jetbrains.python.console.pydev.*;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyDebuggerException;
import com.jetbrains.python.debugger.PyEvaluator;
import com.jetbrains.python.debugger.PyFrameAccessor;
import com.jetbrains.python.debugger.PydevXmlUtils;
import com.jetbrains.python.debugger.pydev.GetVariableCommand;
import com.jetbrains.python.debugger.pydev.ProtocolParser;
import org.apache.xmlrpc.WebServer;
import org.apache.xmlrpc.XmlRpcException;
@@ -38,12 +39,13 @@ import java.util.Vector;
* @author Fabio
*/
public class PydevConsoleCommunication extends AbstractConsoleCommunication implements IScriptConsoleCommunication, XmlRpcHandler,
PyEvaluator {
PyFrameAccessor {
private static final String EXEC_LINE = "execLine";
private static final String GET_COMPLETIONS = "getCompletions";
private static final String GET_DESCRIPTION = "getDescription";
private static final String GET_FRAME = "getFrame";
private static final String GET_VARIABLE = "getVariable";
private static final String HANDSHAKE = "handshake";
private static final String CLOSE = "close";
/**
@@ -431,19 +433,43 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
try {
Object ret = myClient.execute(GET_FRAME, new Object[]{});
if (ret instanceof String) {
final List<PyDebugValue> values = ProtocolParser.parseValues((String)ret);
XValueChildrenList list = new XValueChildrenList(values.size());
for (PyDebugValue v: values) {
list.add(v.getName(), v);
}
return list;
return parseVars((String)ret, null);
}
}
catch (XmlRpcException e) {
throw new PyDebuggerException("Get frame from console failed", e);
}
}
//list.add("X", new PyDebugValue("X", "int", "1000000", false, false));
return new XValueChildrenList();
}
private XValueChildrenList parseVars(String ret, PyDebugValue parent) throws PyDebuggerException {
final List<PyDebugValue> values = ProtocolParser.parseValues(ret, this);
XValueChildrenList list = new XValueChildrenList(values.size());
for (PyDebugValue v : values) {
list.add(v.getName(), parent != null ? v.setParent(parent) : v);
}
return list;
}
@Override
public XValueChildrenList loadVariable(PyDebugValue var) throws PyDebuggerException {
if (myClient != null) {
try {
Object ret = myClient.execute(GET_VARIABLE, new Object[]{GetVariableCommand.composeName(var)});
if (ret instanceof String) {
return parseVars((String)ret, var);
}
}
catch (XmlRpcException e) {
throw new PyDebuggerException("Get variable from console failed", e);
}
}
return new XValueChildrenList();
}
@Override
public void changeVariable(PyDebugValue variable, String expression) throws PyDebuggerException {
//To change body of implemented methods use File | Settings | File Templates.
}
}
@@ -2,8 +2,8 @@ package com.jetbrains.python.console;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.util.Function;
import com.jetbrains.python.console.pydev.AbstractConsoleCommunication;
import com.jetbrains.python.console.pydev.ICallback;
import com.jetbrains.python.console.pydev.InterpreterResponse;
import com.jetbrains.python.console.pydev.PydevCompletionVariant;
import com.jetbrains.python.debugger.PyDebugProcess;
@@ -62,7 +62,7 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio
});
}
public void execInterpreter(String s, final ICallback<Object, InterpreterResponse> callback) {
public void execInterpreter(String s, final Function<InterpreterResponse, Object> callback) {
myExpression.append(s);
exec(myExpression.toString(), new ProcessDebugger.DebugCallback<Pair<String, Boolean>>() {
@Override
@@ -72,13 +72,13 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio
if (!more) {
myExpression.setLength(0);
}
callback.call(new InterpreterResponse(more, isWaitingForInput()));
callback.fun(new InterpreterResponse(more, isWaitingForInput()));
}
@Override
public void error(PyDebuggerException exception) {
myExpression.setLength(0);
callback.call(new InterpreterResponse(false, isWaitingForInput()));
callback.fun(new InterpreterResponse(false, isWaitingForInput()));
}
});
}