mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Array viewer for console variables (PY-14182).
This commit is contained in:
@@ -385,16 +385,21 @@ class BaseInterpreterInterface:
|
||||
|
||||
return xml
|
||||
|
||||
def getArray(self, attr):
|
||||
def getArray(self, attr, roffset, coffset, rows, cols, format):
|
||||
xml = "<xml>"
|
||||
valDict = pydevd_vars.resolveVar(self.getNamespace(), attributes)
|
||||
if valDict is None:
|
||||
valDict = {}
|
||||
array = pydevd_vars.evalInContext(attr, self.getNamespace(), self.getNamespace())
|
||||
|
||||
keys = valDict.keys()
|
||||
xml += pydevd_vars.array_to_xml(array, roffset, coffset, rows, cols, format)
|
||||
|
||||
for k in keys:
|
||||
xml += pydevd_vars.varToXML(valDict[k], to_string(k))
|
||||
xml += "</xml>"
|
||||
|
||||
return xml
|
||||
|
||||
def evaluate(self, expression):
|
||||
xml = "<xml>"
|
||||
result = pydevd_vars.evalInContext(expression, self.getNamespace(), self.getNamespace())
|
||||
|
||||
xml += pydevd_vars.varToXML(result, expression)
|
||||
|
||||
xml += "</xml>"
|
||||
|
||||
|
||||
@@ -293,6 +293,8 @@ def start_server(host, port, interpreter):
|
||||
server.register_function(handshake)
|
||||
server.register_function(interpreter.connectToDebugger)
|
||||
server.register_function(interpreter.hello)
|
||||
server.register_function(interpreter.getArray)
|
||||
server.register_function(interpreter.evaluate)
|
||||
|
||||
# Functions for GUI main loop integration
|
||||
server.register_function(interpreter.enableGui)
|
||||
|
||||
@@ -277,6 +277,43 @@ def customOperation(thread_id, frame_id, scope, attrs, style, code_or_file, oper
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def evalInContext(expression, globals, locals):
|
||||
result = None
|
||||
try:
|
||||
result = eval(expression, globals, locals)
|
||||
except Exception:
|
||||
s = StringIO()
|
||||
traceback.print_exc(file=s)
|
||||
result = s.getvalue()
|
||||
|
||||
try:
|
||||
try:
|
||||
etype, value, tb = sys.exc_info()
|
||||
result = value
|
||||
finally:
|
||||
etype = value = tb = None
|
||||
except:
|
||||
pass
|
||||
|
||||
result = ExceptionOnEvaluate(result)
|
||||
|
||||
# Ok, we have the initial error message, but let's see if we're dealing with a name mangling error...
|
||||
try:
|
||||
if '__' in expression:
|
||||
# Try to handle '__' name mangling...
|
||||
split = expression.split('.')
|
||||
curr = locals.get(split[0])
|
||||
for entry in split[1:]:
|
||||
if entry.startswith('__') and not hasattr(curr, entry):
|
||||
entry = '_%s%s' % (curr.__class__.__name__, entry)
|
||||
curr = getattr(curr, entry)
|
||||
|
||||
result = curr
|
||||
except:
|
||||
pass
|
||||
return result
|
||||
|
||||
|
||||
def evaluateExpression(thread_id, frame_id, expression, doExec):
|
||||
'''returns the result of the evaluated expression
|
||||
@param doExec: determines if we should do an exec or an eval
|
||||
@@ -285,9 +322,6 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
|
||||
if frame is None:
|
||||
return
|
||||
|
||||
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
|
||||
@@ -296,6 +330,7 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
|
||||
updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
|
||||
|
||||
try:
|
||||
expression = str(expression.replace('@LINE@', '\n'))
|
||||
|
||||
if doExec:
|
||||
try:
|
||||
@@ -312,42 +347,7 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
|
||||
return
|
||||
|
||||
else:
|
||||
result = None
|
||||
try:
|
||||
result = eval(expression, updated_globals, frame.f_locals)
|
||||
except Exception:
|
||||
s = StringIO()
|
||||
traceback.print_exc(file=s)
|
||||
result = s.getvalue()
|
||||
|
||||
try:
|
||||
try:
|
||||
etype, value, tb = sys.exc_info()
|
||||
result = value
|
||||
finally:
|
||||
etype = value = tb = None
|
||||
except:
|
||||
pass
|
||||
|
||||
result = ExceptionOnEvaluate(result)
|
||||
|
||||
# Ok, we have the initial error message, but let's see if we're dealing with a name mangling error...
|
||||
try:
|
||||
if '__' in expression:
|
||||
# Try to handle '__' name mangling...
|
||||
split = expression.split('.')
|
||||
curr = frame.f_locals.get(split[0])
|
||||
for entry in split[1:]:
|
||||
if entry.startswith('__') and not hasattr(curr, entry):
|
||||
entry = '_%s%s' % (curr.__class__.__name__, entry)
|
||||
curr = getattr(curr, entry)
|
||||
|
||||
result = curr
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
return result
|
||||
return evalInContext(expression, updated_globals, frame.f_locals)
|
||||
finally:
|
||||
#Should not be kept alive if an exception happens and this frame is kept in the stack.
|
||||
del updated_globals
|
||||
|
||||
@@ -21,5 +21,5 @@ public interface PyFrameAccessor {
|
||||
@Nullable
|
||||
PyReferrersLoader getReferrersLoader();
|
||||
|
||||
Object[][] getArrayItems(PyDebugValue var, int colOffset, int rowOffset, int rows, int cols, String format) throws PyDebuggerException;
|
||||
Object[][] getArrayItems(PyDebugValue var, int rowOffset, int colOffset, int rows, int cols, String format) throws PyDebuggerException;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
|
||||
private static final String CONNECT_TO_DEBUGGER = "connectToDebugger";
|
||||
private static final String HANDSHAKE = "handshake";
|
||||
private static final String CLOSE = "close";
|
||||
private static final String EVALUATE = "evaluate";
|
||||
private static final String GET_ARRAY = "getArray";
|
||||
|
||||
/**
|
||||
* XML-RPC client for sending messages to the server.
|
||||
@@ -461,7 +463,21 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
|
||||
|
||||
@Override
|
||||
public PyDebugValue evaluate(String expression, boolean execute, boolean doTrunc) throws PyDebuggerException {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
if (myClient != null) {
|
||||
try {
|
||||
Object ret = myClient.execute(EVALUATE, new Object[]{expression});
|
||||
if (ret instanceof String) {
|
||||
return ProtocolParser.parseValue((String)ret, this);
|
||||
}
|
||||
else {
|
||||
checkError(ret);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new PyDebuggerException("Evaluate in console failed", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -532,8 +548,23 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[][] getArrayItems(PyDebugValue var, int colOffset, int rowOffset, int rows, int cols, String format) {
|
||||
return new Object[][]{new Object[]{1, 2}, new Object[]{3, 4}};
|
||||
public Object[][] getArrayItems(PyDebugValue var, int rowOffset, int colOffset, int rows, int cols, String format)
|
||||
throws PyDebuggerException {
|
||||
if (myClient != null) {
|
||||
try {
|
||||
Object ret = myClient.execute(GET_ARRAY, new Object[]{var.getName(), rowOffset, colOffset, rows, cols, format});
|
||||
if (ret instanceof String) {
|
||||
return ProtocolParser.parseArrayValues((String)ret, this);
|
||||
}
|
||||
else {
|
||||
checkError(ret);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new PyDebuggerException("Evaluate in console failed", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,8 +56,8 @@ public class AsyncArrayTableModel extends AbstractTableModel {
|
||||
@Override
|
||||
public Object[][] call() throws Exception {
|
||||
return value.getFrameAccessor()
|
||||
.getArrayItems(slicedValue, key.first, key.second, Math.min(CHUNK_COL_SIZE, getRowCount() - key.first),
|
||||
Math.min(CHUNK_ROW_SIZE, getColumnCount() - key.second),
|
||||
.getArrayItems(slicedValue, key.first, key.second, Math.min(CHUNK_ROW_SIZE, getRowCount() - key.first),
|
||||
Math.min(CHUNK_COL_SIZE, getColumnCount() - key.second),
|
||||
myProvider.getFormat());
|
||||
}
|
||||
});
|
||||
@@ -99,10 +99,11 @@ public class AsyncArrayTableModel extends AbstractTableModel {
|
||||
|
||||
if (r < chunk.get().length) {
|
||||
if (c < chunk.get()[r].length) {
|
||||
return myProvider.correctStringValue((String)chunk.get()[r][c]);
|
||||
return myProvider.correctStringValue(chunk.get()[r][c]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
chunk.addListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -22,11 +22,14 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.jetbrains.python.debugger.PyDebugValue;
|
||||
import com.jetbrains.python.debugger.PyDebuggerEvaluator;
|
||||
import com.jetbrains.python.debugger.PyDebuggerException;
|
||||
import com.jetbrains.python.debugger.PyFrameAccessor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.management.InvalidAttributeValueException;
|
||||
@@ -197,8 +200,8 @@ public class NumpyArrayTable {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
public PyDebuggerEvaluator getEvaluator() {
|
||||
return myEvaluator;
|
||||
public PyFrameAccessor getEvaluator() {
|
||||
return myValue.getFrameAccessor();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
@@ -244,10 +247,10 @@ public class NumpyArrayTable {
|
||||
}
|
||||
|
||||
private void fillColorRange(@NotNull final Runnable returnToMain) {
|
||||
XDebuggerEvaluator.XEvaluationCallback callback = new XDebuggerEvaluator.XEvaluationCallback() {
|
||||
Consumer<PyDebugValue> callback = new Consumer<PyDebugValue>() {
|
||||
@Override
|
||||
public void evaluated(@NotNull XValue result) {
|
||||
String rawValue = ((PyDebugValue)result).getValue();
|
||||
public void consume(@NotNull PyDebugValue result) {
|
||||
String rawValue = result.getValue();
|
||||
double min;
|
||||
double max;
|
||||
String minValue = rawValue.substring(1, rawValue.indexOf(","));
|
||||
@@ -271,11 +274,6 @@ public class NumpyArrayTable {
|
||||
myTableCellRenderer.setMax(max);
|
||||
returnToMain.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorOccurred(@NotNull String errorMessage) {
|
||||
showError(errorMessage);
|
||||
}
|
||||
};
|
||||
|
||||
if (getMaxRow(myShape) * getMaxColumn(myShape) > HUGE_ARRAY_SIZE) {
|
||||
@@ -284,7 +282,13 @@ public class NumpyArrayTable {
|
||||
}
|
||||
|
||||
String evalTypeCommand = "[" + getNodeName() + ".min(), " + getNodeName() + ".max()]";
|
||||
getEvaluator().evaluate(evalTypeCommand, callback, null);
|
||||
try {
|
||||
PyDebugValue value = getEvaluator().evaluate(evalTypeCommand, true, false);
|
||||
callback.consume(value);
|
||||
}
|
||||
catch (PyDebuggerException e) {
|
||||
showError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String getDefaultPresentation() {
|
||||
@@ -341,42 +345,27 @@ public class NumpyArrayTable {
|
||||
}
|
||||
|
||||
private void fillType(@NotNull final Runnable returnToMain) {
|
||||
XDebuggerEvaluator.XEvaluationCallback callback = new XDebuggerEvaluator.XEvaluationCallback() {
|
||||
@Override
|
||||
public void evaluated(@NotNull XValue result) {
|
||||
setDtypeKind(((PyDebugValue)result).getValue());
|
||||
returnToMain.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorOccurred(@NotNull String errorMessage) {
|
||||
showError(errorMessage);
|
||||
}
|
||||
};
|
||||
String evalTypeCommand = getNodeName() + ".dtype.kind";
|
||||
getEvaluator().evaluate(evalTypeCommand, callback, null);
|
||||
try {
|
||||
PyDebugValue value = getEvaluator().evaluate(evalTypeCommand, true, false);
|
||||
setDtypeKind(value.getValue());
|
||||
returnToMain.run();
|
||||
}
|
||||
catch (PyDebuggerException e) {
|
||||
showError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void fillShape(@NotNull final Runnable returnToMain) {
|
||||
XDebuggerEvaluator.XEvaluationCallback callback = new XDebuggerEvaluator.XEvaluationCallback() {
|
||||
@Override
|
||||
public void evaluated(@NotNull XValue result) {
|
||||
try {
|
||||
setShape(parseShape(((PyDebugValue)result).getValue()));
|
||||
returnToMain.run();
|
||||
}
|
||||
catch (InvalidAttributeValueException e) {
|
||||
errorOccurred(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorOccurred(@NotNull String errorMessage) {
|
||||
showError(errorMessage);
|
||||
}
|
||||
};
|
||||
String evalShapeCommand = getEvalShapeCommand(getNodeName());
|
||||
getEvaluator().evaluate(evalShapeCommand, callback, null);
|
||||
try {
|
||||
PyDebugValue value = getEvaluator().evaluate(evalShapeCommand, true, false);
|
||||
setShape(parseShape(value.getValue()));
|
||||
returnToMain.run();
|
||||
}
|
||||
catch (Exception e) {
|
||||
showError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private int[] parseShape(String value) throws InvalidAttributeValueException {
|
||||
@@ -542,14 +531,20 @@ public class NumpyArrayTable {
|
||||
};
|
||||
}
|
||||
|
||||
public String correctStringValue(@NotNull String value) {
|
||||
String corrected = value;
|
||||
if (isNumeric()) {
|
||||
if (value.startsWith("\'") || value.startsWith("\"")) {
|
||||
corrected = value.substring(1, value.length() - 1);
|
||||
public String correctStringValue(@NotNull Object value) {
|
||||
if (value instanceof String) {
|
||||
String corrected = (String)value;
|
||||
if (isNumeric()) {
|
||||
if (corrected.startsWith("\'") || corrected.startsWith("\"")) {
|
||||
corrected = corrected.substring(1, corrected.length() - 1);
|
||||
}
|
||||
}
|
||||
return corrected;
|
||||
}
|
||||
return corrected;
|
||||
else if (value instanceof Integer) {
|
||||
return Integer.toString((Integer)value);
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
public void setDtypeKind(String dtype) {
|
||||
@@ -611,28 +606,18 @@ public class NumpyArrayTable {
|
||||
|
||||
private void doReslice(final String newSlice, int[] shape) {
|
||||
if (shape == null) {
|
||||
XDebuggerEvaluator.XEvaluationCallback callback = new XDebuggerEvaluator.XEvaluationCallback() {
|
||||
@Override
|
||||
public void evaluated(@NotNull XValue result) {
|
||||
try {
|
||||
int[] shape = parseShape(((PyDebugValue)result).getValue());
|
||||
if (!is2DShape(shape)) {
|
||||
errorOccurred("Incorrect slice shape " + ((PyDebugValue)result).getValue() + ".");
|
||||
}
|
||||
doReslice(newSlice, shape);
|
||||
}
|
||||
catch (InvalidAttributeValueException e) {
|
||||
errorOccurred(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorOccurred(@NotNull String errorMessage) {
|
||||
showError(errorMessage);
|
||||
}
|
||||
};
|
||||
String evalShapeCommand = getEvalShapeCommand(newSlice);
|
||||
getEvaluator().evaluate(evalShapeCommand, callback, null);
|
||||
try {
|
||||
PyDebugValue result = getEvaluator().evaluate(evalShapeCommand, true, false);
|
||||
shape = parseShape(((PyDebugValue)result).getValue());
|
||||
if (!is2DShape(shape)) {
|
||||
showError("Incorrect slice shape " + ((PyDebugValue)result).getValue() + ".");
|
||||
}
|
||||
doReslice(newSlice, shape);
|
||||
}
|
||||
catch (Exception e) {
|
||||
showError(e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user