diff --git a/python/helpers/pydev/pydev_console_utils.py b/python/helpers/pydev/pydev_console_utils.py index f519db6d191f..2980873cd323 100644 --- a/python/helpers/pydev/pydev_console_utils.py +++ b/python/helpers/pydev/pydev_console_utils.py @@ -385,16 +385,21 @@ class BaseInterpreterInterface: return xml - def getArray(self, attr): + def getArray(self, attr, roffset, coffset, rows, cols, format): 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 += "" + + return xml + + def evaluate(self, expression): + xml = "" + result = pydevd_vars.evalInContext(expression, self.getNamespace(), self.getNamespace()) + + xml += pydevd_vars.varToXML(result, expression) xml += "" diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py index f48f975f703f..19c6c944bea2 100644 --- a/python/helpers/pydev/pydevconsole.py +++ b/python/helpers/pydev/pydevconsole.py @@ -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) diff --git a/python/helpers/pydev/pydevd_vars.py b/python/helpers/pydev/pydevd_vars.py index 56c350034969..d9e1d28c37c5 100644 --- a/python/helpers/pydev/pydevd_vars.py +++ b/python/helpers/pydev/pydevd_vars.py @@ -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 diff --git a/python/pydevSrc/com/jetbrains/python/debugger/PyFrameAccessor.java b/python/pydevSrc/com/jetbrains/python/debugger/PyFrameAccessor.java index 7ce55d3f2031..e4f68b797571 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/PyFrameAccessor.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/PyFrameAccessor.java @@ -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; } diff --git a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java index d756e198765e..c27cfbe0ca0a 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java @@ -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; } /** diff --git a/python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java b/python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java index 97316d821925..278bde5f3eb7 100644 --- a/python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java +++ b/python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java @@ -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() { diff --git a/python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java b/python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java index a169fc3d6521..d8e5a9ad0821 100644 --- a/python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java +++ b/python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java @@ -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 callback = new Consumer() { @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; }