Variable view in Python Console.

This commit is contained in:
Dmitry Trofimov
2013-09-03 14:48:54 +02:00
parent f67487028d
commit fd689cb7dc
19 changed files with 833 additions and 246 deletions
+12 -1
View File
@@ -17,6 +17,8 @@ import traceback
import fix_getpass
fix_getpass.fixGetpass()
import pydevd_xml
try:
if USE_LIB_COPY:
import _pydev_Queue as _queue
@@ -162,7 +164,13 @@ class InterpreterInterface(BaseInterpreterInterface):
traceback.print_exc()
return []
def getFrame(self):
xml = "<xml>"
xml += pydevd_xml.frameVarsToXML(self.namespace)
xml += "</xml>"
return xml
def close(self):
sys.exit(0)
@@ -265,6 +273,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.getDescription)
server.register_function(interpreter.close)
server.register_function(interpreter.interrupt)
@@ -323,6 +332,8 @@ def get_completions(text, token, globals, locals):
return interpreterInterface.getCompletions(text, token)
def get_frame(globals, locals):
return interpreterInterface.getFrame()
def exec_expression(expression, globals, locals):
interpreterInterface = get_interpreter()
+2 -2
View File
@@ -604,7 +604,7 @@ class NetCommandFactory:
#print "line is ", myLine
#the variables are all gotten 'on-demand'
#variables = pydevd_vars.frameVarsToXML(curFrame)
#variables = pydevd_vars.frameVarsToXML(curFrame.f_locals)
variables = ''
cmdTextList.append('<frame id="%s" name="%s" ' % (myId , pydevd_vars.makeValidXmlValue(myName)))
@@ -839,7 +839,7 @@ class InternalGetFrame(InternalThreadCommand):
frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
if frame is not None:
xml = "<xml>"
xml += pydevd_vars.frameVarsToXML(frame)
xml += pydevd_vars.frameVarsToXML(frame.f_locals)
del frame
xml += "</xml>"
cmd = dbg.cmdFactory.makeGetFrameMessage(self.sequence, xml)
+4
View File
@@ -6,6 +6,7 @@ except:
from urllib.parse import quote
import pydevd_constants
import pydev_log
def to_number(x):
if is_string(x):
@@ -92,4 +93,7 @@ def quote_smart(s, safe='/'):
s = s.encode('utf-8')
return quote(s, safe)
+1 -201
View File
@@ -8,7 +8,7 @@ from types import * #@UnusedWildImport
from code import compile_command
from code import InteractiveInterpreter
import pydevconsole
import pydev_log
from pydevd_xml import *
try:
from StringIO import StringIO
@@ -16,11 +16,6 @@ except ImportError:
from io import StringIO
import sys #@Reimport
try:
from urllib import quote
except:
from urllib.parse import quote #@UnresolvedImport
if USE_LIB_COPY:
import _pydev_threading as threading
else:
@@ -50,177 +45,6 @@ class VariableError(RuntimeError): pass
class FrameNotFoundError(RuntimeError): pass
#------------------------------------------------------------------------------------------------------ resolvers in map
if not sys.platform.startswith("java"):
typeMap = [
#None means that it should not be treated as a compound variable
#isintance does not accept a tuple on some versions of python, so, we must declare it expanded
(type(None), None,),
(int, None),
(float, None),
(complex, None),
(str, None),
(tuple, pydevd_resolver.tupleResolver),
(list, pydevd_resolver.tupleResolver),
(dict, pydevd_resolver.dictResolver),
]
try:
typeMap.append((long, None))
except:
pass #not available on all python versions
try:
typeMap.append((unicode, None))
except:
pass #not available on all python versions
try:
typeMap.append((set, pydevd_resolver.setResolver))
except:
pass #not available on all python versions
try:
typeMap.append((frozenset, pydevd_resolver.setResolver))
except:
pass #not available on all python versions
else: #platform is java
from org.python import core #@UnresolvedImport
typeMap = [
(core.PyNone, None),
(core.PyInteger, None),
(core.PyLong, None),
(core.PyFloat, None),
(core.PyComplex, None),
(core.PyString, None),
(core.PyTuple, pydevd_resolver.tupleResolver),
(core.PyList, pydevd_resolver.tupleResolver),
(core.PyDictionary, pydevd_resolver.dictResolver),
(core.PyStringMap, pydevd_resolver.dictResolver),
]
if hasattr(core, 'PyJavaInstance'):
#Jython 2.5b3 removed it.
typeMap.append((core.PyJavaInstance, pydevd_resolver.instanceResolver))
def getType(o):
""" returns a triple (typeObject, typeString, resolver
resolver != None means that variable is a container,
and should be displayed as a hierarchy.
Use the resolver to get its attributes.
All container objects should have a resolver.
"""
try:
type_object = type(o)
type_name = type_object.__name__
except:
#This happens for org.python.core.InitModule
return 'Unable to get Type', 'Unable to get Type', None
try:
if type_name == 'org.python.core.PyJavaInstance':
return type_object, type_name, pydevd_resolver.instanceResolver
if type_name == 'org.python.core.PyArray':
return type_object, type_name, pydevd_resolver.jyArrayResolver
for t in typeMap:
if isinstance(o, t[0]):
return type_object, type_name, t[1]
except:
traceback.print_exc()
#no match return default
return type_object, type_name, pydevd_resolver.defaultResolver
try:
from xml.sax.saxutils import escape
def makeValidXmlValue(s):
return escape(s, {'"': '&quot;'})
except:
#Simple replacement if it's not there.
def makeValidXmlValue(s):
return s.replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;')
def varToXML(val, name, doTrim=True):
""" single variable or dictionary to xml representation """
is_exception_on_eval = isinstance(val, ExceptionOnEvaluate)
if is_exception_on_eval:
v = val.result
else:
v = val
type, typeName, resolver = getType(v)
try:
if hasattr(v, '__class__'):
try:
cName = str(v.__class__)
if cName.find('.') != -1:
cName = cName.split('.')[-1]
elif cName.find("'") != -1: #does not have '.' (could be something like <type 'int'>)
cName = cName[cName.index("'") + 1:]
if cName.endswith("'>"):
cName = cName[:-2]
except:
cName = str(v.__class__)
value = '%s: %s' % (cName, v)
else:
value = str(v)
except:
try:
value = repr(v)
except:
value = 'Unable to get repr for %s' % v.__class__
xml = '<var name="%s" type="%s"' % (makeValidXmlValue(quote(name, '/>_= ')), makeValidXmlValue(typeName))
if value:
#cannot be too big... communication may not handle it.
if len(value) > MAXIMUM_VARIABLE_REPRESENTATION_SIZE and doTrim:
value = value[0:MAXIMUM_VARIABLE_REPRESENTATION_SIZE]
value += '...'
#fix to work with unicode values
try:
if not IS_PY3K:
if isinstance(value, unicode):
value = value.encode('utf-8')
else:
if isinstance(value, bytes):
value = value.encode('utf-8')
except TypeError: #in java, unicode is a function
pass
xmlValue = ' value="%s"' % (makeValidXmlValue(quote(value, '/>_= ')))
else:
xmlValue = ''
if is_exception_on_eval:
xmlCont = ' isErrorOnEval="True"'
else:
if resolver is not None:
xmlCont = ' isContainer="True"'
else:
xmlCont = ''
return ''.join((xml, xmlValue, xmlCont, ' />\n'))
if USE_PSYCO_OPTIMIZATION:
try:
import psyco
@@ -231,27 +55,7 @@ if USE_PSYCO_OPTIMIZATION:
sys.exc_clear() #don't keep the traceback -- clients don't want to see it
def frameVarsToXML(frame):
""" dumps frame variables to XML
<var name="var_name" scope="local" type="type" value="value"/>
"""
xml = ""
keys = frame.f_locals.keys()
if hasattr(keys, 'sort'):
keys.sort() #Python 3.0 does not have it
else:
keys = sorted(keys) #Jython 2.1 does not have it
for k in keys:
try:
v = frame.f_locals[k]
xml += varToXML(v, str(k))
except Exception:
traceback.print_exc()
pydev_log.error("Unexpected error, recovered safely.\n")
return xml
def iterFrames(initialFrame):
"""NO-YIELD VERSION: Iterates through all the frames starting at the specified frame (which will be the first returned item)"""
@@ -378,10 +182,6 @@ def resolveCompoundVariable(thread_id, frame_id, scope, attrs):
except:
traceback.print_exc()
class ExceptionOnEvaluate:
def __init__(self, result):
self.result = 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
+205
View File
@@ -0,0 +1,205 @@
import pydev_log
import traceback
import pydevd_resolver
from pydevd_constants import * #@UnusedWildImport
from types import * #@UnusedWildImport
try:
from urllib import quote
except:
from urllib.parse import quote #@UnresolvedImport
try:
from xml.sax.saxutils import escape
def makeValidXmlValue(s):
return escape(s, {'"': '&quot;'})
except:
#Simple replacement if it's not there.
def makeValidXmlValue(s):
return s.replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;')
class ExceptionOnEvaluate:
def __init__(self, result):
self.result = result
#------------------------------------------------------------------------------------------------------ resolvers in map
if not sys.platform.startswith("java"):
typeMap = [
#None means that it should not be treated as a compound variable
#isintance does not accept a tuple on some versions of python, so, we must declare it expanded
(type(None), None,),
(int, None),
(float, None),
(complex, None),
(str, None),
(tuple, pydevd_resolver.tupleResolver),
(list, pydevd_resolver.tupleResolver),
(dict, pydevd_resolver.dictResolver),
]
try:
typeMap.append((long, None))
except:
pass #not available on all python versions
try:
typeMap.append((unicode, None))
except:
pass #not available on all python versions
try:
typeMap.append((set, pydevd_resolver.setResolver))
except:
pass #not available on all python versions
try:
typeMap.append((frozenset, pydevd_resolver.setResolver))
except:
pass #not available on all python versions
else: #platform is java
from org.python import core #@UnresolvedImport
typeMap = [
(core.PyNone, None),
(core.PyInteger, None),
(core.PyLong, None),
(core.PyFloat, None),
(core.PyComplex, None),
(core.PyString, None),
(core.PyTuple, pydevd_resolver.tupleResolver),
(core.PyList, pydevd_resolver.tupleResolver),
(core.PyDictionary, pydevd_resolver.dictResolver),
(core.PyStringMap, pydevd_resolver.dictResolver),
]
if hasattr(core, 'PyJavaInstance'):
#Jython 2.5b3 removed it.
typeMap.append((core.PyJavaInstance, pydevd_resolver.instanceResolver))
def getType(o):
""" returns a triple (typeObject, typeString, resolver
resolver != None means that variable is a container,
and should be displayed as a hierarchy.
Use the resolver to get its attributes.
All container objects should have a resolver.
"""
try:
type_object = type(o)
type_name = type_object.__name__
except:
#This happens for org.python.core.InitModule
return 'Unable to get Type', 'Unable to get Type', None
try:
if type_name == 'org.python.core.PyJavaInstance':
return type_object, type_name, pydevd_resolver.instanceResolver
if type_name == 'org.python.core.PyArray':
return type_object, type_name, pydevd_resolver.jyArrayResolver
for t in typeMap:
if isinstance(o, t[0]):
return type_object, type_name, t[1]
except:
traceback.print_exc()
#no match return default
return type_object, type_name, pydevd_resolver.defaultResolver
def frameVarsToXML(frame_f_locals):
""" dumps frame variables to XML
<var name="var_name" scope="local" type="type" value="value"/>
"""
xml = ""
keys = frame_f_locals.keys()
if hasattr(keys, 'sort'):
keys.sort() #Python 3.0 does not have it
else:
keys = sorted(keys) #Jython 2.1 does not have it
for k in keys:
try:
v = frame_f_locals[k]
xml += varToXML(v, str(k))
except Exception:
traceback.print_exc()
pydev_log.error("Unexpected error, recovered safely.\n")
return xml
def varToXML(val, name, doTrim=True):
""" single variable or dictionary to xml representation """
is_exception_on_eval = isinstance(val, ExceptionOnEvaluate)
if is_exception_on_eval:
v = val.result
else:
v = val
type, typeName, resolver = getType(v)
try:
if hasattr(v, '__class__'):
try:
cName = str(v.__class__)
if cName.find('.') != -1:
cName = cName.split('.')[-1]
elif cName.find("'") != -1: #does not have '.' (could be something like <type 'int'>)
cName = cName[cName.index("'") + 1:]
if cName.endswith("'>"):
cName = cName[:-2]
except:
cName = str(v.__class__)
value = '%s: %s' % (cName, v)
else:
value = str(v)
except:
try:
value = repr(v)
except:
value = 'Unable to get repr for %s' % v.__class__
xml = '<var name="%s" type="%s"' % (makeValidXmlValue(quote(name, '/>_= ')), makeValidXmlValue(typeName))
if value:
#cannot be too big... communication may not handle it.
if len(value) > MAXIMUM_VARIABLE_REPRESENTATION_SIZE and doTrim:
value = value[0:MAXIMUM_VARIABLE_REPRESENTATION_SIZE]
value += '...'
#fix to work with unicode values
try:
if not IS_PY3K:
if isinstance(value, unicode):
value = value.encode('utf-8')
else:
if isinstance(value, bytes):
value = value.encode('utf-8')
except TypeError: #in java, unicode is a function
pass
xmlValue = ' value="%s"' % (makeValidXmlValue(quote(value, '/>_= ')))
else:
xmlValue = ''
if is_exception_on_eval:
xmlCont = ' isErrorOnEval="True"'
else:
if resolver is not None:
xmlCont = ' isContainer="True"'
else:
xmlCont = ''
return ''.join((xml, xmlValue, xmlCont, ' />\n'))
@@ -2,13 +2,14 @@ package com.jetbrains.python.debugger;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.xdebugger.frame.XValueChildrenList;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
/**
* @author yole
*/
public interface IPyDebugProcess {
public interface IPyDebugProcess extends PyEvaluator {
PyPositionConverter getPositionConverter();
void threadSuspended(PyThreadInfo thread);
@@ -21,8 +22,6 @@ public interface IPyDebugProcess {
void threadResumed(PyThreadInfo thread);
PyDebugValue evaluate(String expression, boolean exec, boolean doTrunc) throws PyDebuggerException;
void printToConsole(String text, ConsoleViewContentType contentType);
void init();
@@ -0,0 +1,14 @@
package com.jetbrains.python.debugger;
import com.intellij.xdebugger.frame.XValueChildrenList;
import org.jetbrains.annotations.Nullable;
/**
* @author traff
*/
public interface PyEvaluator {
PyDebugValue evaluate(final String expression, final boolean execute, boolean doTrunc) throws PyDebuggerException;
@Nullable
XValueChildrenList loadFrame() throws PyDebuggerException;
}
+1
View File
@@ -20,6 +20,7 @@
<orderEntry type="module" module-name="testRunner" />
<orderEntry type="module" module-name="smRunner" />
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="module" module-name="xdebugger-impl" />
</component>
</module>
@@ -16,6 +16,7 @@
package com.jetbrains.python.actions;
import com.intellij.execution.ExecutionHelper;
import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.execution.console.LanguageConsoleViewImpl;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.RunContentDescriptor;
@@ -217,7 +218,7 @@ public class ExecuteInConsoleAction extends AnAction {
PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context);
runner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
@Override
public void handleConsoleInitialized(LanguageConsoleViewImpl consoleView) {
public void handleConsoleInitialized(LanguageConsoleView consoleView) {
if (consoleView instanceof PyCodeExecutor) {
consumer.consume((PyCodeExecutor)consoleView);
}
@@ -0,0 +1,325 @@
package com.jetbrains.python.console;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunnerLayoutUi;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.util.EventDispatcher;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebugSessionListener;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.frame.XExecutionStack;
import com.intellij.xdebugger.frame.XStackFrame;
import com.intellij.xdebugger.frame.XSuspendContext;
import com.intellij.xdebugger.impl.XSourcePositionImpl;
import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
import com.intellij.xdebugger.stepping.XSmartStepIntoVariant;
import com.jetbrains.python.debugger.PyDebuggerEditorsProvider;
import com.jetbrains.python.debugger.PyStackFrame;
import com.jetbrains.python.debugger.PyStackFrameInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import javax.swing.*;
import javax.swing.event.HyperlinkListener;
/**
* @author traff
*/
public class DebugSessionConsoleAdapter implements XDebugSession {
private Project myProject;
private PydevConsoleCommunication myCommunication;
private final EventDispatcher<XDebugSessionListener> myDispatcher = EventDispatcher.create(XDebugSessionListener.class);
public DebugSessionConsoleAdapter(Project project, PydevConsoleCommunication communication) {
myProject = project;
myCommunication = communication;
}
@NotNull
@Override
public Project getProject() {
return myProject;
}
@NotNull
@Override
public XDebugProcess getDebugProcess() {
return new XDebugProcess(this) {
@NotNull
@Override
public XDebuggerEditorsProvider getEditorsProvider() {
return new PyDebuggerEditorsProvider();
}
@Override
public void startStepOver() {
throw new NotImplementedException();
}
@Override
public void startStepInto() {
throw new NotImplementedException();
}
@Override
public void startStepOut() {
throw new NotImplementedException();
}
@Override
public void stop() {
throw new NotImplementedException();
}
@Override
public void resume() {
throw new NotImplementedException();
}
@Override
public void runToPosition(@NotNull XSourcePosition position) {
throw new NotImplementedException();
}
};
}
@Override
public boolean isSuspended() {
return !myCommunication.isExecuting();
}
@Nullable
@Override
public XStackFrame getCurrentStackFrame() {
return new PyStackFrame(myProject, myCommunication, new PyStackFrameInfo("", "", "", null), null);
}
@Override
public XSuspendContext getSuspendContext() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Nullable
@Override
public XSourcePosition getCurrentPosition() {
return new XSourcePosition() {
@Override
public int getLine() {
return -1;
}
@Override
public int getOffset() {
return -1;
}
@NotNull
@Override
public VirtualFile getFile() {
return myCommunication.getConsoleFile();
}
@NotNull
@Override
public Navigatable createNavigatable(@NotNull Project project) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
};
}
@Override
public void stepOver(boolean ignoreBreakpoints) {
throw new NotImplementedException();
}
@Override
public void stepInto() {
throw new NotImplementedException();
}
@Override
public void stepOut() {
throw new NotImplementedException();
}
@Override
public void forceStepInto() {
throw new NotImplementedException();
}
@Override
public void runToPosition(@NotNull XSourcePosition position, boolean ignoreBreakpoints) {
throw new NotImplementedException();
}
@Override
public void pause() {
throw new NotImplementedException();
}
@Override
public void resume() {
myDispatcher.getMulticaster().sessionResumed();
}
@Override
public void showExecutionPoint() {
throw new NotImplementedException();
}
@Override
public void setCurrentStackFrame(@NotNull XExecutionStack executionStack, @NotNull XStackFrame frame) {
throw new NotImplementedException();
}
@Override
public void setCurrentStackFrame(@NotNull XStackFrame frame) {
throw new NotImplementedException();
}
@Override
public void updateBreakpointPresentation(@NotNull XLineBreakpoint<?> breakpoint, @Nullable Icon icon, @Nullable String errorMessage) {
throw new NotImplementedException();
}
@Override
public boolean breakpointReached(@NotNull XBreakpoint<?> breakpoint,
@Nullable String evaluatedLogExpression,
@NotNull XSuspendContext suspendContext) {
throw new NotImplementedException();
}
@Override
public boolean breakpointReached(@NotNull XBreakpoint<?> breakpoint, @NotNull XSuspendContext suspendContext) {
throw new NotImplementedException();
}
@Override
public void positionReached(@NotNull XSuspendContext suspendContext) {
throw new NotImplementedException();
}
@Override
public void sessionResumed() {
throw new NotImplementedException();
}
@Override
public void stop() {
throw new NotImplementedException();
}
@Override
public void setBreakpointMuted(boolean muted) {
throw new NotImplementedException();
}
@Override
public boolean areBreakpointsMuted() {
throw new NotImplementedException();
}
@Override
public void addSessionListener(@NotNull final XDebugSessionListener listener) {
myDispatcher.addListener(listener);
}
@Override
public void removeSessionListener(@NotNull final XDebugSessionListener listener) {
myDispatcher.removeListener(listener);
}
@Override
public void reportError(@NotNull String message) {
throw new NotImplementedException();
}
@Override
public void reportMessage(@NotNull String message, @NotNull MessageType type) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void reportMessage(@NotNull String message, @NotNull MessageType type, @Nullable HyperlinkListener listener) {
//To change body of implemented methods use File | Settings | File Templates.
}
@NotNull
@Override
public String getSessionName() {
return "Python Console"; //TODO
}
@NotNull
@Override
public RunContentDescriptor getRunContentDescriptor() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Nullable
@Override
public RunProfile getRunProfile() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void setPauseActionSupported(boolean isSupported) {
throw new NotImplementedException();
}
@Override
public void setAutoInitBreakpoints(boolean value) {
throw new NotImplementedException();
}
@Override
public void rebuildViews() {
throw new NotImplementedException();
}
@Override
public <V extends XSmartStepIntoVariant> void smartStepInto(XSmartStepIntoHandler<V> handler, V variant) {
throw new NotImplementedException();
}
@Override
public void updateExecutionPosition() {
throw new NotImplementedException();
}
@Override
public void initBreakpoints() {
throw new NotImplementedException();
}
@Override
public ConsoleView getConsoleView() {
throw new NotImplementedException();
}
@Override
public RunnerLayoutUi getUI() {
throw new NotImplementedException();
}
@Override
public boolean isStopped() {
return false; //TODO
}
@Override
public boolean isPaused() {
return false;
}
}
@@ -12,13 +12,19 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.xdebugger.frame.XValueChildrenList;
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.PydevXmlUtils;
import com.jetbrains.python.debugger.pydev.ProtocolParser;
import org.apache.xmlrpc.WebServer;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.MalformedURLException;
import java.util.Collections;
@@ -30,11 +36,13 @@ import java.util.Vector;
*
* @author Fabio
*/
public class PydevConsoleCommunication extends AbstractConsoleCommunication implements IScriptConsoleCommunication, XmlRpcHandler {
public class PydevConsoleCommunication extends AbstractConsoleCommunication implements IScriptConsoleCommunication, XmlRpcHandler,
PyEvaluator {
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 HANDSHAKE = "handshake";
private static final String CLOSE = "close";
/**
@@ -409,4 +417,32 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
public boolean isExecuting() {
return myExecuting;
}
@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.
}
@Nullable
@Override
public XValueChildrenList loadFrame() throws PyDebuggerException {
if (myClient != null) {
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;
}
}
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();
}
}
@@ -2,6 +2,7 @@ package com.jetbrains.python.console;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.execution.console.LanguageConsoleImpl;
import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.execution.console.LanguageConsoleViewImpl;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ConsoleExecuteActionHandler;
@@ -32,7 +33,7 @@ import java.util.Scanner;
*/
public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandler implements ConsoleCommunicationListener {
private final LanguageConsoleViewImpl myConsoleView;
private final LanguageConsoleView myConsoleView;
private String myInMultilineStringState = null;
private StringBuilder myInputBuffer;
@@ -41,7 +42,7 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
private final ConsoleCommunication myConsoleCommunication;
private boolean myEnabled = false;
public PydevConsoleExecuteActionHandler(LanguageConsoleViewImpl consoleView,
public PydevConsoleExecuteActionHandler(LanguageConsoleView consoleView,
ProcessHandler myProcessHandler,
ConsoleCommunication consoleCommunication) {
super(myProcessHandler, false);
@@ -7,6 +7,7 @@ import com.intellij.execution.ExecutionHelper;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.console.ConsoleHistoryController;
import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.execution.console.LanguageConsoleViewImpl;
import com.intellij.execution.process.CommandLineArgumentsProvider;
import com.intellij.execution.process.ProcessAdapter;
@@ -16,6 +17,7 @@ import com.intellij.execution.runners.AbstractConsoleRunnerWithHistory;
import com.intellij.execution.runners.ConsoleExecuteActionHandler;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
@@ -45,6 +47,7 @@ import com.intellij.util.IJSwingUtilities;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.net.NetUtils;
import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.impl.frame.XVariablesView;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.console.completion.PydevConsoleElement;
import com.jetbrains.python.console.parsing.PythonConsoleData;
@@ -64,6 +67,7 @@ import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import static com.jetbrains.python.sdk.PythonEnvUtil.setPythonIOEncoding;
import static com.jetbrains.python.sdk.PythonEnvUtil.setPythonUnbuffered;
@@ -134,6 +138,9 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
actions.add(backspaceHandlingAction);
actions.add(interruptAction);
AnAction showVarsAction = new ShowVarsAction();
toolbarActions.add(showVarsAction);
return actions;
}
@@ -608,14 +615,14 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
myConsoleListeners.remove(consoleListener);
}
private void fireConsoleInitializedEvent(LanguageConsoleViewImpl consoleView) {
private void fireConsoleInitializedEvent(LanguageConsoleView consoleView) {
for (ConsoleListener listener : myConsoleListeners) {
listener.handleConsoleInitialized(consoleView);
}
}
public interface ConsoleListener {
void handleConsoleInitialized(LanguageConsoleViewImpl consoleView);
void handleConsoleInitialized(LanguageConsoleView consoleView);
}
@@ -656,4 +663,38 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
}
}.queue();
}
private class ShowVarsAction extends ToggleAction {
private boolean mySelected = false;
public ShowVarsAction() {
super("Show Variables", "Shows active console variables", AllIcons.Debugger.Watches);
}
@Override
public boolean isSelected(AnActionEvent e) {
return mySelected;
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
mySelected = state;
if (mySelected) {
DebugSessionConsoleAdapter session = new DebugSessionConsoleAdapter(getProject(), myPydevConsoleCommunication);
XVariablesView view = new XVariablesView(session, new Disposable() {
@Override
public void dispose() {
//TODO: pass correct disposable
}
});
session.resume();
getConsoleView().showVariables(view);
}
else {
getConsoleView().hideVariables();
}
}
}
}
@@ -2,10 +2,17 @@ package com.jetbrains.python.console;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.execution.console.LanguageConsoleImpl;
import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.execution.console.LanguageConsoleViewImpl;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.filters.OpenFileHyperlinkInfo;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.ui.ObservableConsoleView;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -22,6 +29,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.impl.frame.XVariablesView;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.console.completion.PythonConsoleAutopopupBlockingHandler;
import com.jetbrains.python.console.pydev.ConsoleCommunication;
@@ -31,10 +39,13 @@ import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
/**
* @author traff
*/
public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCodeExecutor {
public class PythonConsoleView extends JPanel implements LanguageConsoleView, ObservableConsoleView, PyCodeExecutor {
private static final Logger LOG = Logger.getInstance(PythonConsoleView.class);
@@ -46,11 +57,18 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
private EditorColorsScheme myScheme;
private boolean myHyperlink;
private final MyLanguageConsoleViewImpl myLanguageConsoleView;
public PythonConsoleView(final Project project, final String title, Sdk sdk) {
super(new PythonLanguageConsole(project, title, sdk));
super(new BorderLayout());
myLanguageConsoleView = new MyLanguageConsoleViewImpl(project, title, sdk);
add(myLanguageConsoleView.getComponent(), BorderLayout.CENTER);
getPythonLanguageConsole().setPythonConsoleView(this);
getPythonLanguageConsole().setPrompt(PyConsoleUtil.ORDINARY_PROMPT);
setUpdateFoldingsEnabled(false);
myLanguageConsoleView.setUpdateFoldingsEnabled(false);
myProject = project;
//noinspection ConstantConditions
myPyHighlighter = new PyHighlighter(
@@ -68,16 +86,16 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
public void requestFocus() {
IdeFocusManager.findInstance().requestFocus(getPythonLanguageConsole().getConsoleEditor().getContentComponent(), true);
updateUI();
myLanguageConsoleView.updateUI();
getLanguageConsole().getHistoryViewer().getComponent().updateUI();
}
private PythonLanguageConsole getPythonLanguageConsole() {
return ((PythonLanguageConsole)myConsole);
return ((PythonLanguageConsole)getLanguageConsole());
}
public LanguageConsoleImpl getLanguageConsole() {
return myConsole;
return myLanguageConsoleView.getConsole();
}
@Override
@@ -144,7 +162,7 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
}
public void printText(String text, final ConsoleViewContentType outputType) {
super.print(text, outputType);
myLanguageConsoleView.print(text, outputType);
}
public void print(String text, final ConsoleViewContentType outputType) {
@@ -163,7 +181,7 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
}
else {
//Print text normally with converted attributes
super.print(text, outputType);
myLanguageConsoleView.print(text, outputType);
}
myHyperlink = detectHyperlink(text);
if (mySourceHighlighter == null && myIsIPythonOutput && PyConsoleUtil.detectSourcePrinting(text)) {
@@ -181,6 +199,77 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
}
}
@Override
public void clear() {
myLanguageConsoleView.clear();
}
@Override
public void scrollTo(int offset) {
myLanguageConsoleView.scrollTo(offset);
}
@Override
public void attachToProcess(ProcessHandler processHandler) {
myLanguageConsoleView.attachToProcess(processHandler);
}
@Override
public void setOutputPaused(boolean value) {
myLanguageConsoleView.setOutputPaused(value);
}
@Override
public boolean isOutputPaused() {
return myLanguageConsoleView.isOutputPaused();
}
@Override
public boolean hasDeferredOutput() {
return myLanguageConsoleView.hasDeferredOutput();
}
@Override
public void performWhenNoDeferredOutput(Runnable runnable) {
myLanguageConsoleView.performWhenNoDeferredOutput(runnable);
}
@Override
public void setHelpId(String helpId) {
myLanguageConsoleView.setHelpId(helpId);
}
@Override
public void addMessageFilter(Filter filter) {
myLanguageConsoleView.addMessageFilter(filter);
}
@Override
public void printHyperlink(String hyperlinkText, HyperlinkInfo info) {
myLanguageConsoleView.printHyperlink(hyperlinkText, info);
}
@Override
public int getContentSize() {
return myLanguageConsoleView.getContentSize();
}
@Override
public boolean canPause() {
return myLanguageConsoleView.canPause();
}
@NotNull
@Override
public AnAction[] createConsoleActions() {
return myLanguageConsoleView.createConsoleActions();
}
@Override
public void allowHeavyFilters() {
myLanguageConsoleView.allowHeavyFilters();
}
public void detectIPython(String text, final ConsoleViewContentType outputType) {
VirtualFile file = getConsoleVirtualFile();
if (file != null) {
@@ -197,7 +286,7 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
}
public VirtualFile getConsoleVirtualFile() {
return getConsole().getFile().getVirtualFile();
return getLanguageConsole().getFile().getVirtualFile();
}
private boolean detectHyperlink(@NotNull String text) {
@@ -211,10 +300,10 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
if (vFile != null) {
OpenFileHyperlinkInfo hyperlink = new OpenFileHyperlinkInfo(myProject, vFile, -1);
printHyperlink(text, hyperlink);
myLanguageConsoleView.printHyperlink(text, hyperlink);
}
else {
super.print(text, contentType);
myLanguageConsoleView.print(text, contentType);
}
}
}
@@ -238,6 +327,52 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
getPythonLanguageConsole().setSdk(sdk);
}
@Override
public JComponent getComponent() {
return this;
}
@Override
public JComponent getPreferredFocusableComponent() {
return myLanguageConsoleView.getPreferredFocusableComponent();
}
@Override
public void dispose() {
myLanguageConsoleView.dispose();
}
@Override
public void addChangeListener(@NotNull ChangeListener listener, @NotNull Disposable parent) {
myLanguageConsoleView.addChangeListener(listener, parent);
}
@NotNull
@Override
public LanguageConsoleImpl getConsole() {
return myLanguageConsoleView.getConsole();
}
public void showVariables(XVariablesView view) {
removeAll();
view.getPanel().setPreferredSize(new Dimension(150, 500));
JSplitPane p = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
p.add(myLanguageConsoleView.getComponent(), JSplitPane.LEFT);
p.add(view.getPanel(), JSplitPane.RIGHT);
p.setDividerLocation(0.7);
//p.setDividerLocation(200);
add(p, BorderLayout.CENTER);
}
public void hideVariables() {
removeAll();
add(myLanguageConsoleView.getComponent(), BorderLayout.CENTER);
}
public void beforeExternalAddContentToDocument(int length, ConsoleViewContentType contentType) {
myLanguageConsoleView.beforeExternalAddContentToDocument(length, contentType);
}
private static class PythonLanguageConsole extends LanguageConsoleImpl {
private PythonConsoleView myPythonConsoleView;
@@ -278,10 +413,20 @@ public class PythonConsoleView extends LanguageConsoleViewImpl implements PyCode
}
}
@Override
protected EditorEx createRealEditor() {
EditorEx editor = myConsole.getHistoryViewer();
editor.setHighlighter(createHighlighter());
return editor;
private static class MyLanguageConsoleViewImpl extends LanguageConsoleViewImpl {
public MyLanguageConsoleViewImpl(Project project, String title, Sdk sdk) {
super(new PythonLanguageConsole(project, title, sdk));
}
@Override
protected EditorEx createRealEditor() {
EditorEx editor = myConsole.getHistoryViewer();
editor.setHighlighter(createHighlighter());
return editor;
}
public void beforeExternalAddContentToDocument(int length, ConsoleViewContentType contentType) {
super.beforeExternalAddContentToDocument(length, contentType);
}
}
}
@@ -46,7 +46,6 @@ public class PythonDebugLanguageConsoleView extends JPanel implements ConsoleVie
private ProcessHandler myProcessHandler;
public PythonDebugLanguageConsoleView(final Project project, Sdk sdk, ConsoleView consoleView) {
super(new CardLayout());
myPydevConsoleView = createConsoleView(project, sdk);
@@ -140,8 +139,8 @@ public class PythonDebugLanguageConsoleView extends JPanel implements ConsoleVie
@Override
public void scrollTo(int offset) {
myPydevConsoleView.getConsole().getHistoryViewer().getCaretModel().moveToOffset(offset);
myPydevConsoleView.getConsole().getHistoryViewer().getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
myPydevConsoleView.getLanguageConsole().getHistoryViewer().getCaretModel().moveToOffset(offset);
myPydevConsoleView.getLanguageConsole().getHistoryViewer().getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
myTextConsole.scrollTo(offset);
}
@@ -455,6 +455,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
}
}
@Override
@Nullable
public XValueChildrenList loadFrame() throws PyDebuggerException {
final PyStackFrame frame = currentFrame();
@@ -646,7 +647,8 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
}
public PyStackFrame createStackFrame(PyStackFrameInfo frameInfo) {
return new PyStackFrame(this, frameInfo);
return new PyStackFrame(this.getSession().getProject(), this, frameInfo,
getPositionConverter().convertFromPython(frameInfo.getPosition()));
}
@Override
@@ -14,9 +14,11 @@ public class PyDebuggerEvaluator extends XDebuggerEvaluator {
private static final PyDebugValue NONE = new PyDebugValue("", "NoneType", "None", false, false, null, null);
private final PyDebugProcess myDebugProcess;
private Project myProject;
private final PyEvaluator myDebugProcess;
public PyDebuggerEvaluator(@NotNull final PyDebugProcess debugProcess) {
public PyDebuggerEvaluator(@NotNull Project project, @NotNull final PyEvaluator debugProcess) {
myProject = project;
myDebugProcess = debugProcess;
}
@@ -32,8 +34,7 @@ public class PyDebuggerEvaluator extends XDebuggerEvaluator {
return;
}
final Project project = myDebugProcess.getSession().getProject();
final boolean isExpression = PyDebugSupportUtils.isExpression(project, expression);
final boolean isExpression = PyDebugSupportUtils.isExpression(myProject, expression);
try {
// todo: think on getting results from EXEC
final PyDebugValue value = myDebugProcess.evaluate(expression, !isExpression, doTrunc);
@@ -24,14 +24,18 @@ public class PyStackFrame extends XStackFrame {
private static final Object STACK_FRAME_EQUALITY_OBJECT = new Object();
private final PyDebugProcess myDebugProcess;
private Project myProject;
private final PyEvaluator myDebugProcess;
private final PyStackFrameInfo myFrameInfo;
private final XSourcePosition myPosition;
public PyStackFrame(@NotNull final PyDebugProcess debugProcess, @NotNull final PyStackFrameInfo frameInfo) {
public PyStackFrame(@NotNull Project project,
@NotNull final PyEvaluator debugProcess,
@NotNull final PyStackFrameInfo frameInfo, XSourcePosition position) {
myProject = project;
myDebugProcess = debugProcess;
myFrameInfo = frameInfo;
myPosition = myDebugProcess.getPositionConverter().convertFromPython(frameInfo.getPosition());
myPosition = position;
}
@Override
@@ -46,7 +50,7 @@ public class PyStackFrame extends XStackFrame {
@Override
public XDebuggerEvaluator getEvaluator() {
return new PyDebuggerEvaluator(myDebugProcess);
return new PyDebuggerEvaluator(myProject, myDebugProcess);
}
@Override
@@ -62,8 +66,7 @@ public class PyStackFrame extends XStackFrame {
final VirtualFile file = myPosition.getFile();
final Document document = FileDocumentManager.getInstance().getDocument(file);
if (document != null) {
final Project project = myDebugProcess.getSession().getProject();
isExternal = !ProjectRootManager.getInstance(project).getFileIndex().isInContent(file);
isExternal = !ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(file);
}
component.append(myFrameInfo.getName(), gray(SimpleTextAttributes.REGULAR_ATTRIBUTES, isExternal));
@@ -120,5 +123,4 @@ public class PyStackFrame extends XStackFrame {
protected XSourcePosition getPosition() {
return myPosition;
}
}
@@ -1,6 +1,6 @@
package com.jetbrains.python.debugger;
import com.intellij.execution.console.LanguageConsoleViewImpl;
import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.xdebugger.XDebugSessionListener;
import com.jetbrains.python.console.PydevConsoleExecuteActionHandler;
@@ -11,7 +11,7 @@ import com.jetbrains.python.console.pydev.ConsoleCommunication;
*/
public class PydevDebugConsoleExecuteActionHandler extends PydevConsoleExecuteActionHandler implements XDebugSessionListener {
public PydevDebugConsoleExecuteActionHandler(LanguageConsoleViewImpl consoleView,
public PydevDebugConsoleExecuteActionHandler(LanguageConsoleView consoleView,
ProcessHandler myProcessHandler,
ConsoleCommunication consoleCommunication) {
super(consoleView, myProcessHandler, consoleCommunication);