added stdout and stderr redirection in remote debug mode

This commit is contained in:
Dmitry Trofimov
2010-12-03 17:18:57 +03:00
parent 63233b171c
commit da5348a8e7
11 changed files with 92 additions and 21 deletions

View File

View File

@@ -87,6 +87,7 @@ if IS_PY3K:
connected = False
bufferStdOutToServer = False
bufferStdErrToServer = False
remote = False
PyDBUseLocks = True
@@ -599,7 +600,9 @@ class PyDB:
elif cmd_id == CMD_CONSOLE_EXEC:
#command to exec expression in console, in case expression is only partially valid 'False' is returned
#text is: thread\tstackframe\tLOCAL\texpression
thread_id, frame_id, scope, expression = text.split('\t', 3)
int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression)
self.postInternalCommand(int_cmd, thread_id)
@@ -997,11 +1000,14 @@ def settrace(host='localhost', stdoutToServer=False, stderrToServer=False, port=
@param suspend: whether a breakpoint should be emulated as soon as this function is called.
@param trace_only_current_thread: determines if only the current thread will be traced or all future threads will also have the tracing enabled.
'''
global remote
global connected
global bufferStdOutToServer
global bufferStdErrToServer
remote = True
if not connected :
connected = True
bufferStdOutToServer = stdoutToServer

View File

@@ -130,7 +130,6 @@ class PyDBFrame:
return self.trace_dispatch
except:
traceback.print_exc()
raise
#step handling. We stop when we hit the right frame

View File

@@ -11,6 +11,9 @@ class IORedirector:
r.write(s)
except:
pass
def flush(self):
pass
class IOBuf:
'''This class works as a replacement for stdio and stderr.
@@ -28,4 +31,5 @@ class IOBuf:
def write(self, s):
self.buflist.append(s)

View File

@@ -1,5 +1,7 @@
package com.jetbrains.python.debugger;
import com.intellij.execution.ui.ConsoleViewContentType;
import java.util.List;
/**
@@ -19,4 +21,6 @@ public interface IPyDebugProcess {
void threadResumed(PyThreadInfo thread);
PyDebugValue evaluate(String expression, boolean exec, boolean doTrunc) throws PyDebuggerException;
void printToConsole(String text, ConsoleViewContentType contentType);
}

View File

@@ -0,0 +1,22 @@
package com.jetbrains.python.debugger;
/**
* @author traff
*/
public class PyIo {
private final String text;
private final int ctx;
public PyIo(String text, int ctx) {
this.text = text;
this.ctx = ctx;
}
public String getText() {
return text;
}
public int getCtx() {
return ctx;
}
}

View File

@@ -21,6 +21,7 @@ public abstract class AbstractCommand {
public static final int EVALUATE = 113;
public static final int GET_FRAME = 114;
public static final int EXECUTE = 115;
public static final int WRITE_TO_CONSOLE = 116;
public static final int CHANGE_VARIABLE = 117;
public static final int GET_COMPLETIONS = 120;
public static final int CONSOLE_EXEC = 121;
@@ -75,6 +76,10 @@ public abstract class AbstractCommand {
}
}
public static boolean isWriteToConsole(final int command) {
return command == WRITE_TO_CONSOLE;
}
protected static class Payload {
private final StringBuilder myBuilder = new StringBuilder();
private static final char SEPARATOR = '\t';

View File

@@ -14,7 +14,8 @@ import java.util.List;
public class ProtocolParser {
private ProtocolParser() { }
private ProtocolParser() {
}
public static String decode(final String value) throws PyDebuggerException {
try {
@@ -29,6 +30,17 @@ public class ProtocolParser {
return StringUtil.replace(expression, "\n", "@LINE@");
}
public static PyIo parseIo(final String text) throws PyDebuggerException {
final XppReader reader = openReader(text, true);
reader.moveDown();
if (!"io".equals(reader.getNodeName())) {
throw new PyDebuggerException("Expected <io>, found " + reader.getNodeName());
}
final String s = readString(reader, "s", "");
final int ctx = readInt(reader, "ctx", 1);
return new PyIo(s, ctx);
}
@NotNull
public static PyThreadInfo parseThread(final String text, final PyPositionConverter positionConverter) throws PyDebuggerException {
final XppReader reader = openReader(text, true);
@@ -58,10 +70,10 @@ public class ProtocolParser {
@NotNull
public static String getThreadId(@NotNull String payload) {
return payload.split("\t")[0];
}
}
private static PyStackFrameInfo parseFrame(final XppReader reader, final String threadId, final PyPositionConverter positionConverter)
throws PyDebuggerException {
throws PyDebuggerException {
if (!"frame".equals(reader.getNodeName())) {
throw new PyDebuggerException("Expected <frame>, found " + reader.getNodeName());
}
@@ -168,5 +180,4 @@ public class ProtocolParser {
}
return value;
}
}

View File

@@ -5,13 +5,11 @@
*/
package com.jetbrains.python.debugger.pydev;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.jetbrains.python.debugger.IPyDebugProcess;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyDebuggerException;
import com.jetbrains.python.debugger.PyThreadInfo;
import com.jetbrains.python.debugger.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -268,6 +266,10 @@ public class RemoteDebugger {
os.write('\n');
os.flush();
}
catch (SocketException se) {
LOG.error(se);
disconnect();
}
catch (IOException e) {
LOG.error(e);
}
@@ -338,6 +340,9 @@ public class RemoteDebugger {
if (AbstractThreadCommand.isThreadCommand(frame.getCommand())) {
processThreadEvent(frame);
}
else if (AbstractCommand.isWriteToConsole(frame.getCommand())) {
writeToConsole(parseIoEvent(frame));
}
else {
placeResponse(frame.getSequence(), frame);
}
@@ -390,6 +395,10 @@ public class RemoteDebugger {
}
}
private PyIo parseIoEvent(ProtocolFrame frame) throws PyDebuggerException {
return ProtocolParser.parseIo(frame.getPayload());
}
private PyThreadInfo parseThreadEvent(ProtocolFrame frame) throws PyDebuggerException {
return ProtocolParser.parseThread(frame.getPayload(), myDebugProcess.getPositionConverter());
}
@@ -403,6 +412,17 @@ public class RemoteDebugger {
}
}
private void writeToConsole(PyIo io) {
ConsoleViewContentType contentType;
if (io.getCtx() == 2) {
contentType = ConsoleViewContentType.ERROR_OUTPUT;
}
else {
contentType = ConsoleViewContentType.NORMAL_OUTPUT;
}
myDebugProcess.printToConsole(io.getText(), contentType);
}
private static class TempVarsHolder {
private final Map<String, Map<String, Set<String>>> myData = new HashMap<String, Map<String, Set<String>>>();

View File

@@ -139,11 +139,11 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
private void handshake() throws PyDebuggerException {
final String remoteVersion = myDebugger.handshake();
printToConsole("Connected to pydevd (version " + remoteVersion + ")\n");
printToConsole("Connected to pydevd (version " + remoteVersion + ")\n", ConsoleViewContentType.SYSTEM_OUTPUT);
}
protected void printToConsole(String text) {
((ConsoleView)myExecutionConsole).print(text, ConsoleViewContentType.SYSTEM_OUTPUT);
public void printToConsole(String text, ConsoleViewContentType contentType) {
((ConsoleView)myExecutionConsole).print(text, contentType);
}
private void registerBreakpoints() {
@@ -394,13 +394,12 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
@Override
public void processTerminated(ProcessEvent event) {
myClosing = true;
myDebugger.close();
}
@Override
public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
myClosing = true;
myDebugger.close();
}
@Override

View File

@@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull;
public class PythonRunner extends DefaultProgramRunner {
@NotNull
public String getRunnerId() {
public String getRunnerId() {
return "PythonRunner";
}
@@ -35,8 +35,7 @@ public class PythonRunner extends DefaultProgramRunner {
RunProfileState state,
RunContentDescriptor contentToReuse,
ExecutionEnvironment env
) throws ExecutionException
{
) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
ExecutionResult executionResult;
@@ -44,7 +43,9 @@ public class PythonRunner extends DefaultProgramRunner {
if (state instanceof PythonCommandLineState && profile instanceof CommandLinePatcher) {
executionResult = ((PythonCommandLineState)state).execute(executor, (CommandLinePatcher)profile);
}
else executionResult = state.execute(executor, this);
else {
executionResult = state.execute(executor, this);
}
if (executionResult == null) return null;
final RunContentBuilder contentBuilder = new RunContentBuilder(project, this, executor);