diff -r cc920e534ac0 -r 72a72fd56494 eric6/Debugger/DebugServer.py --- a/eric6/Debugger/DebugServer.py Thu Jan 30 19:37:03 2020 +0100 +++ b/eric6/Debugger/DebugServer.py Sat Feb 01 19:48:21 2020 +0100 @@ -50,23 +50,28 @@ executed a line of code @signal clientThreadList(currentId, threadList, debuggerId) emitted after a thread list has been received - @signal clientThreadSet() emitted after the client has acknowledged the - change of the current thread - @signal clientVariables(scope, variables) emitted after a variables dump - has been received - @signal clientVariable(scope, variables) emitted after a dump for one class - variable has been received - @signal clientStatement(bool) emitted after an interactive command has - been executed. The parameter is 0 to indicate that the command is - complete and 1 if it needs more input. - @signal clientException(exception) emitted after an exception occured on - the client side - @signal clientSyntaxError(exception) emitted after a syntax error has been - detected on the client side - @signal clientSignal(signal) emitted after a signal has been generated on - the client side - @signal clientExit(int, str, bool) emitted after the client has exited - giving the exit status, an exit message and an indication to be quiet + @signal clientThreadSet(debuggerId) emitted after the client has + acknowledged the change of the current thread + @signal clientVariables(scope, variables, debuggerId) emitted after a + variables dump has been received + @signal clientVariable(scope, variables, debuggerId) emitted after a dump + for one class variable has been received + @signal clientStatement(continue, debuggerId) emitted after an interactive + command has been executed. The parameter is False to indicate that the + command is complete and True if it needs more input. + @signal clientException(exceptionType, exceptionMessage, stackTrace, + debuggerId) emitted after an exception occured on the client side + @signal clientSyntaxError(message, filename, linenumber, characternumber, + debuggerId) emitted after a syntax error has been detected on the + client side + @signal clientSignal(message, filename, linenumber, function name, + function arguments, debuggerId) emitted after a signal has been + generated on the client side + @signal clientExit(int, str, bool, str) emitted after the client has exited + giving the exit status, an exit message, an indication to be quiet and + the ID of the exited client + @signal lastClientExited() emitted to indicate that the last connected + debug client has terminated @signal clientClearBreak(filename, lineno) emitted after the debug client has decided to clear a temporary breakpoint @signal clientBreakConditionError(fn, lineno) emitted after the client has @@ -111,7 +116,7 @@ reported an unexpected test success @signal callTraceInfo emitted after the client reported the call trace data (isCall, fromFile, fromLine, fromFunction, toFile, toLine, - toFunction) + toFunction, debuggerId) @signal appendStdout(msg) emitted when a passive debug connection is established or lost @signal clientDebuggerIds(debuggerIds) emitted to give the list of IDs of @@ -127,14 +132,15 @@ clientLine = pyqtSignal(str, int, str, bool) clientStack = pyqtSignal(list, str) clientThreadList = pyqtSignal(int, list, str) - clientThreadSet = pyqtSignal() - clientVariables = pyqtSignal(int, list) - clientVariable = pyqtSignal(int, list) - clientStatement = pyqtSignal(bool) - clientException = pyqtSignal(str, str, list) - clientSyntaxError = pyqtSignal(str, str, int, int) - clientSignal = pyqtSignal(str, str, int, str, str) - clientExit = pyqtSignal(int, str, bool) + clientThreadSet = pyqtSignal(str) + clientVariables = pyqtSignal(int, list, str) + clientVariable = pyqtSignal(int, list, str) + clientStatement = pyqtSignal(bool, str) + clientException = pyqtSignal(str, str, list, str) + clientSyntaxError = pyqtSignal(str, str, int, int, str) + clientSignal = pyqtSignal(str, str, int, str, str, str) + clientExit = pyqtSignal(int, str, bool, str) + lastClientExited = pyqtSignal() clientBreakConditionError = pyqtSignal(str, int) clientWatchConditionError = pyqtSignal(str) clientRawInput = pyqtSignal(str, bool) @@ -154,7 +160,7 @@ utTestSucceededUnexpected = pyqtSignal(str, str) utFinished = pyqtSignal() passiveDebugStarted = pyqtSignal(str, bool) - callTraceInfo = pyqtSignal(bool, str, str, str, str, str, str) + callTraceInfo = pyqtSignal(bool, str, str, str, str, str, str, str) appendStdout = pyqtSignal(str) def __init__(self, originalPathString, preventPassiveDebugging=False): @@ -531,8 +537,6 @@ elif self.__autoClearShell: self.__autoClearShell = False self.remoteBanner() -## self.remoteClientVariables(0, [], 0) -## self.remoteClientVariables(1, [], 0) else: if clType and self.lastClientType: self.__setClientType(self.lastClientType) @@ -586,7 +590,8 @@ index = self.breakpointModel.index(row, 0, parentIndex) fn, lineno = ( self.breakpointModel.getBreakPointByIndex(index)[0:2]) - self.remoteBreakpoint(fn, lineno, False) + # delete the breakpoints of all connected backends + self.remoteBreakpoint("", fn, lineno, False) def __changeBreakPoints(self, startIndex, endIndex): """ @@ -611,24 +616,31 @@ self.__deleteBreakPoints( QModelIndex(), startIndex.row(), endIndex.row()) - def __addBreakPoints(self, parentIndex, start, end): + def __addBreakPoints(self, parentIndex, start, end, debuggerId=""): """ Private slot to add breakpoints. - @param parentIndex index of parent item (QModelIndex) - @param start start row (integer) - @param end end row (integer) + @param parentIndex index of parent item + @type QModelIndex + @param start start row + @type int + @param end end row + @type int + @param debuggerId ID of the debugger backend to send to. If this is + empty, they will be broadcast to all connected backends. + @type str """ if self.debugging: for row in range(start, end + 1): index = self.breakpointModel.index(row, 0, parentIndex) fn, line, cond, temp, enabled, ignorecount = ( self.breakpointModel.getBreakPointByIndex(index)[:6]) - self.remoteBreakpoint(fn, line, True, cond, temp) + self.remoteBreakpoint(debuggerId, fn, line, True, cond, temp) if not enabled: - self.__remoteBreakpointEnable(fn, line, False) + self.__remoteBreakpointEnable(debuggerId, fn, line, False) if ignorecount: - self.__remoteBreakpointIgnore(fn, line, ignorecount) + self.__remoteBreakpointIgnore( + debuggerId, fn, line, ignorecount) def __makeWatchCondition(self, cond, special): """ @@ -682,9 +694,12 @@ """ Private slot to delete watch expressions. - @param parentIndex index of parent item (QModelIndex) - @param start start row (integer) - @param end end row (integer) + @param parentIndex index of parent item + @type QModelIndex + @param start start row + @type int + @param end end row + @type int """ if self.debugging: for row in range(start, end + 1): @@ -692,27 +707,35 @@ cond, special = ( self.watchpointModel.getWatchPointByIndex(index)[0:2]) cond = self.__makeWatchCondition(cond, special) - self.__remoteWatchpoint(cond, False) + self.__remoteWatchpoint("", cond, False) def __watchPointDataAboutToBeChanged(self, startIndex, endIndex): """ Private slot to handle the dataAboutToBeChanged signal of the watch expression model. - @param startIndex start index of the rows to be changed (QModelIndex) - @param endIndex end index of the rows to be changed (QModelIndex) + @param startIndex start index of the rows to be changed + @type QModelIndex + @param endIndex end index of the rows to be changed + @type QModelIndex """ if self.debugging: self.__deleteWatchPoints( QModelIndex(), startIndex.row(), endIndex.row()) - def __addWatchPoints(self, parentIndex, start, end): + def __addWatchPoints(self, parentIndex, start, end, debuggerId=""): """ Private slot to set a watch expression. - @param parentIndex index of parent item (QModelIndex) - @param start start row (integer) - @param end end row (integer) + @param parentIndex index of parent item + @type QModelIndex + @param start start row + @type int + @param end end row + @type int + @param debuggerId ID of the debugger backend to send to. If this is + empty, they will be broadcast to all connected backends. + @type str """ if self.debugging: for row in range(start, end + 1): @@ -720,11 +743,12 @@ cond, special, temp, enabled, ignorecount = ( self.watchpointModel.getWatchPointByIndex(index)[:5]) cond = self.__makeWatchCondition(cond, special) - self.__remoteWatchpoint(cond, True, temp) + self.__remoteWatchpoint(debuggerId, cond, True, temp) if not enabled: - self.__remoteWatchpointEnable(cond, False) + self.__remoteWatchpointEnable(debuggerId, cond, False) if ignorecount: - self.__remoteWatchpointIgnore(cond, ignorecount) + self.__remoteWatchpointIgnore(debuggerId, cond, + ignorecount) def __changeWatchPoints(self, startIndex, endIndex): """ @@ -803,19 +827,22 @@ self.__createDebuggerInterface( Preferences.getDebugger("PassiveDbgType")) - accepted = self.debuggerInterface.newConnection(sock) - if accepted: - # Perform actions necessary, if client type has changed - if self.lastClientType != self.clientType: - self.lastClientType = self.clientType - self.remoteBanner() - elif self.__autoClearShell: - self.__autoClearShell = False - self.remoteBanner() - elif self.passive: - self.remoteBanner() - - self.debuggerInterface.flush() + self.debuggerInterface.newConnection(sock) + + def masterClientConnected(self): + """ + Public method to perform actions after the master client has finally + established the connection. + """ + # Perform actions necessary, if client type has changed + if self.lastClientType != self.clientType: + self.lastClientType = self.clientType + self.remoteBanner() + elif self.__autoClearShell: + self.__autoClearShell = False + self.remoteBanner() + elif self.passive: + self.remoteBanner() def shutdownServer(self): """ @@ -912,7 +939,7 @@ self.startClient(False, forProject=forProject, runInConsole=runInConsole, venvName=venvName) - self.setCallTraceEnabled(enableCallTrace) + self.setCallTraceEnabled("", enableCallTrace) self.remoteEnvironment(env) self.debuggerInterface.remoteLoad(fn, argv, wd, tracePython, @@ -1106,123 +1133,172 @@ self.debugging = False self.running = True - def remoteStatement(self, stmt): + def remoteStatement(self, debuggerId, stmt): """ Public method to execute a Python statement. - @param stmt the Python statement to execute (string). It - should not have a trailing newline. + @param debuggerId ID of the debugger backend + @type str + @param stmt the Python statement to execute. + @type str """ - self.debuggerInterface.remoteStatement(stmt) + self.debuggerInterface.remoteStatement(debuggerId, stmt.rstrip()) - def remoteStep(self): + def remoteStep(self, debuggerId): """ Public method to single step the debugged program. + + @param debuggerId ID of the debugger backend + @type str """ - self.debuggerInterface.remoteStep() + self.debuggerInterface.remoteStep(debuggerId) - def remoteStepOver(self): + def remoteStepOver(self, debuggerId): """ Public method to step over the debugged program. + + @param debuggerId ID of the debugger backend + @type str """ - self.debuggerInterface.remoteStepOver() + self.debuggerInterface.remoteStepOver(debuggerId) - def remoteStepOut(self): + def remoteStepOut(self, debuggerId): """ Public method to step out the debugged program. + + @param debuggerId ID of the debugger backend + @type str """ - self.debuggerInterface.remoteStepOut() + self.debuggerInterface.remoteStepOut(debuggerId) - def remoteStepQuit(self): + def remoteStepQuit(self, debuggerId): """ Public method to stop the debugged program. + + @param debuggerId ID of the debugger backend + @type str """ - self.debuggerInterface.remoteStepQuit() + self.debuggerInterface.remoteStepQuit(debuggerId) - def remoteContinue(self, special=False): + def remoteContinue(self, debuggerId, special=False): """ Public method to continue the debugged program. + @param debuggerId ID of the debugger backend + @type str @param special flag indicating a special continue operation """ - self.debuggerInterface.remoteContinue(special) + self.debuggerInterface.remoteContinue(debuggerId, special) - def remoteMoveIP(self, line): + def remoteMoveIP(self, debuggerId, line): """ Public method to move the instruction pointer to a different line. + @param debuggerId ID of the debugger backend + @type str @param line the new line, where execution should be continued + @type int """ - self.debuggerInterface.remoteMoveIP(line) + self.debuggerInterface.remoteMoveIP(debuggerId, line) - def remoteBreakpoint(self, fn, line, setBreakpoint, cond=None, temp=False): + def remoteBreakpoint(self, debuggerId, fn, line, setBreakpoint, cond=None, + temp=False): """ Public method to set or clear a breakpoint. - @param fn filename the breakpoint belongs to (string) - @param line linenumber of the breakpoint (int) + @param debuggerId ID of the debugger backend + @type str + @param fn filename the breakpoint belongs to + @type str + @param line linenumber of the breakpoint + @type int @param setBreakpoint flag indicating setting or resetting a breakpoint - (boolean) - @param cond condition of the breakpoint (string) - @param temp flag indicating a temporary breakpoint (boolean) + @type bool + @param cond condition of the breakpoint + @type str + @param temp flag indicating a temporary breakpoint + @type bool """ - self.debuggerInterface.remoteBreakpoint(fn, line, setBreakpoint, cond, - temp) + self.debuggerInterface.remoteBreakpoint( + debuggerId, fn, line, setBreakpoint, cond, temp) - def __remoteBreakpointEnable(self, fn, line, enable): + def __remoteBreakpointEnable(self, debuggerId, fn, line, enable): """ Private method to enable or disable a breakpoint. - @param fn filename the breakpoint belongs to (string) - @param line linenumber of the breakpoint (int) + @param debuggerId ID of the debugger backend + @type str + @param fn filename the breakpoint belongs to + @type str + @param line linenumber of the breakpoint + @type int @param enable flag indicating enabling or disabling a breakpoint - (boolean) + @type bool """ - self.debuggerInterface.remoteBreakpointEnable(fn, line, enable) + self.debuggerInterface.remoteBreakpointEnable( + debuggerId, fn, line, enable) - def __remoteBreakpointIgnore(self, fn, line, count): + def __remoteBreakpointIgnore(self, debuggerId, fn, line, count): """ Private method to ignore a breakpoint the next couple of occurrences. - @param fn filename the breakpoint belongs to (string) - @param line linenumber of the breakpoint (int) - @param count number of occurrences to ignore (int) + @param debuggerId ID of the debugger backend + @type str + @param fn filename the breakpoint belongs to + @type str + @param line linenumber of the breakpoint + @type int + @param count number of occurrences to ignore + @type int """ - self.debuggerInterface.remoteBreakpointIgnore(fn, line, count) + self.debuggerInterface.remoteBreakpointIgnore( + debuggerId, fn, line, count) - def __remoteWatchpoint(self, cond, setWatch, temp=False): + def __remoteWatchpoint(self, debuggerId, cond, setWatch, temp=False): """ Private method to set or clear a watch expression. - @param cond expression of the watch expression (string) + @param debuggerId ID of the debugger backend + @type str + @param cond expression of the watch expression + @type str @param setWatch flag indicating setting or resetting a watch expression - (boolean) - @param temp flag indicating a temporary watch expression (boolean) + @type bool + @param temp flag indicating a temporary watch expression + @type bool """ # cond is combination of cond and special (s. watch expression viewer) - self.debuggerInterface.remoteWatchpoint(cond, setWatch, temp) + self.debuggerInterface.remoteWatchpoint(debuggerId, cond, setWatch, + temp) - def __remoteWatchpointEnable(self, cond, enable): + def __remoteWatchpointEnable(self, debuggerId, cond, enable): """ Private method to enable or disable a watch expression. - @param cond expression of the watch expression (string) + @param debuggerId ID of the debugger backend + @type str + @param cond expression of the watch expression + @type str @param enable flag indicating enabling or disabling a watch expression - (boolean) + @type bool """ # cond is combination of cond and special (s. watch expression viewer) - self.debuggerInterface.remoteWatchpointEnable(cond, enable) + self.debuggerInterface.remoteWatchpointEnable(debuggerId, cond, enable) - def __remoteWatchpointIgnore(self, cond, count): + def __remoteWatchpointIgnore(self, debuggerId, cond, count): """ Private method to ignore a watch expression the next couple of occurrences. - @param cond expression of the watch expression (string) - @param count number of occurrences to ignore (int) + @param debuggerId ID of the debugger backend + @type str + @param cond expression of the watch expression + @type str + @param count number of occurrences to ignore + @type int """ # cond is combination of cond and special (s. watch expression viewer) - self.debuggerInterface.remoteWatchpointIgnore(cond, count) + self.debuggerInterface.remoteWatchpointIgnore(debuggerId, cond, count) def remoteRawInput(self, s): """ @@ -1233,64 +1309,74 @@ self.debuggerInterface.remoteRawInput(s) self.clientRawInputSent.emit() - def remoteThreadList(self, debuggerId=""): + def remoteThreadList(self, debuggerId): """ Public method to request the list of threads from the client. @param debuggerId ID of the debugger backend @type str """ - self.debuggerInterface.remoteThreadList(debuggerId=debuggerId) + self.debuggerInterface.remoteThreadList(debuggerId) - def remoteSetThread(self, tid, debuggerId=""): + def remoteSetThread(self, debuggerId, tid): """ Public method to request to set the given thread as current thread. - @param tid id of the thread - @type int @param debuggerId ID of the debugger backend @type str + @param tid id of the thread + @type int """ - self.debuggerInterface.remoteSetThread(tid, debuggerId=debuggerId) + self.debuggerInterface.remoteSetThread(debuggerId, tid) - def remoteClientStack(self, debuggerId=""): + def remoteClientStack(self, debuggerId): """ Public method to request the stack of the main thread. @param debuggerId ID of the debugger backend @type str """ - self.debuggerInterface.remoteClientStack(debuggerId=debuggerId) + self.debuggerInterface.remoteClientStack(debuggerId) - def remoteClientVariables(self, scope, filterList, framenr=0, - debuggerId=""): + def remoteClientVariables(self, debuggerId, scope, filterList, framenr=0): """ Public method to request the variables of the debugged program. + @param debuggerId ID of the debugger backend + @type str @param scope the scope of the variables (0 = local, 1 = global) @type int @param filterList list of variable types to filter out @type list of int @param framenr framenumber of the variables to retrieve @type int - @param debuggerId ID of the debugger backend - @type str """ self.debuggerInterface.remoteClientVariables( - scope, filterList, framenr, self.__maxVariableSize, - debuggerId=debuggerId) + debuggerId, scope, filterList, framenr, self.__maxVariableSize) - def remoteClientVariable(self, scope, filterList, var, framenr=0): + def remoteClientVariable(self, debuggerId, scope, filterList, var, + framenr=0, maxSize=0): """ Public method to request the variables of the debugged program. + @param debuggerId ID of the debugger backend + @type str @param scope the scope of the variables (0 = local, 1 = global) - @param filterList list of variable types to filter out (list of int) - @param var list encoded name of variable to retrieve (string) - @param framenr framenumber of the variables to retrieve (int) + @type int + @param filterList list of variable types to filter out + @type list of int + @param var list encoded name of variable to retrieve + @type list of str + @param framenr framenumber of the variables to retrieve + @type int + @param maxSize maximum size the formatted value of a variable will + be shown. If it is bigger than that, a 'too big' indication will + be given (@@TOO_BIG_TO_SHOW@@). + @type int """ self.debuggerInterface.remoteClientVariable( - scope, filterList, var, framenr, self.__maxVariableSize) + debuggerId, scope, filterList, var, framenr, + self.__maxVariableSize) def remoteClientSetFilter(self, scope, filterStr): """ @@ -1302,13 +1388,16 @@ """ self.debuggerInterface.remoteClientSetFilter(scope, filterStr) - def setCallTraceEnabled(self, on): + def setCallTraceEnabled(self, debuggerId, on): """ Public method to set the call trace state. - @param on flag indicating to enable the call trace function (boolean) + @param debuggerId ID of the debugger backend + @type str + @param on flag indicating to enable the call trace function + @type bool """ - self.debuggerInterface.setCallTraceEnabled(on) + self.debuggerInterface.setCallTraceEnabled(debuggerId, on) def remoteBanner(self): """ @@ -1516,71 +1605,96 @@ """ self.clientThreadList.emit(currentId, threadList, debuggerId) - def signalClientThreadSet(self): + def signalClientThreadSet(self, debuggerId): """ Public method to handle the change of the client thread. + + @param debuggerId ID of the debugger backend + @type str """ - self.clientThreadSet.emit() + self.clientThreadSet.emit(debuggerId) - def signalClientVariables(self, scope, variables): + def signalClientVariables(self, scope, variables, debuggerId): """ Public method to process the client variables info. @param scope scope of the variables (-1 = empty global, 1 = global, 0 = local) + @type int @param variables the list of variables from the client + @type list + @param debuggerId ID of the debugger backend + @type str """ - self.clientVariables.emit(scope, variables) + self.clientVariables.emit(scope, variables, debuggerId) - def signalClientVariable(self, scope, variables): + def signalClientVariable(self, scope, variables, debuggerId): """ Public method to process the client variable info. @param scope scope of the variables (-1 = empty global, 1 = global, 0 = local) + @type int @param variables the list of members of a classvariable from the client + @type list + @param debuggerId ID of the debugger backend + @type str """ - self.clientVariable.emit(scope, variables) + self.clientVariable.emit(scope, variables, debuggerId) - def signalClientStatement(self, more): + def signalClientStatement(self, more, debuggerId): """ Public method to process the input response from the client. @param more flag indicating that more user input is required + @type bool + @param debuggerId ID of the debugger backend + @type str """ - self.clientStatement.emit(more) + self.clientStatement.emit(more, debuggerId) def signalClientException(self, exceptionType, exceptionMessage, - stackTrace): + stackTrace, debuggerId): """ Public method to process the exception info from the client. - @param exceptionType type of exception raised (string) - @param exceptionMessage message given by the exception (string) + @param exceptionType type of exception raised + @type str + @param exceptionMessage message given by the exception + @type str @param stackTrace list of stack entries with the exception position first. Each stack entry is a list giving the filename and the linenumber. + @type list + @param debuggerId ID of the debugger backend + @type str """ if self.running: self.clientException.emit(exceptionType, exceptionMessage, - stackTrace) + stackTrace, debuggerId) - def signalClientSyntaxError(self, message, filename, lineNo, characterNo): + def signalClientSyntaxError(self, message, filename, lineNo, characterNo, + debuggerId): """ - Public method to process the syntax error info from the client. + Public method to process a syntax error info from the client. - @param message message of the syntax error (string) + @param message message of the syntax error + @type str @param filename translated filename of the syntax error position - (string) - @param lineNo line number of the syntax error position (integer) + @type str + @param lineNo line number of the syntax error position + @type int @param characterNo character number of the syntax error position - (integer) + @type int + @param debuggerId ID of the debugger backend + @type str """ if self.running: - self.clientSyntaxError.emit(message, filename, lineNo, characterNo) + self.clientSyntaxError.emit(message, filename, lineNo, characterNo, + debuggerId) def signalClientSignal(self, message, filename, lineNo, - funcName, funcArgs): + funcName, funcArgs, debuggerId): """ Public method to process a signal generated on the client side. @@ -1594,12 +1708,14 @@ @type str @param funcArgs function arguments @type str + @param debuggerId ID of the debugger backend + @type str """ if self.running: self.clientSignal.emit(message, filename, lineNo, - funcName, funcArgs) + funcName, funcArgs, debuggerId) - def signalClientExit(self, status, message=""): + def signalClientExit(self, status, message, debuggerId): """ Public method to process the client exit status. @@ -1607,10 +1723,18 @@ @type int @param message message sent with the exit @type str + @param debuggerId ID of the debugger backend + @type str + """ + self.clientExit.emit(int(status), message, False, debuggerId) + + def signalLastClientExited(self): + """ + Public method to process the last client exit event. """ if self.passive: self.__passiveShutDown() - self.clientExit.emit(int(status), message, False) + self.lastClientExited.emit() if Preferences.getDebugger("AutomaticReset") or (self.running and not self.debugging): self.debugging = False @@ -1618,9 +1742,9 @@ if self.passive: self.__createDebuggerInterface("None") self.signalClientOutput(self.tr('\nNot connected\n')) - self.signalClientStatement(False) + self.signalClientStatement(False, "") self.running = False - + def signalClientClearBreak(self, filename, lineno): """ Public method to process the client clear breakpoint command. @@ -1707,21 +1831,30 @@ self.clientCompletionList.emit(completionList, text) def signalClientCallTrace(self, isCall, fromFile, fromLine, fromFunction, - toFile, toLine, toFunction): + toFile, toLine, toFunction, debuggerId): """ Public method to process the client call trace data. - @param isCall flag indicating a 'call' (boolean) - @param fromFile name of the originating file (string) - @param fromLine line number in the originating file (string) - @param fromFunction name of the originating function (string) - @param toFile name of the target file (string) - @param toLine line number in the target file (string) - @param toFunction name of the target function (string) + @param isCall flag indicating a 'call' + @type bool + @param fromFile name of the originating file + @type str + @param fromLine line number in the originating file + @type str + @param fromFunction name of the originating function + @type str + @param toFile name of the target file + @type str + @param toLine line number in the target file + @type str + @param toFunction name of the target function + @type str + @param debuggerId ID of the debugger backend + @type str """ self.callTraceInfo.emit( isCall, fromFile, fromLine, fromFunction, - toFile, toLine, toFunction) + toFile, toLine, toFunction, debuggerId) def clientUtDiscovered(self, testCases, exceptionType, exceptionValue): """ @@ -1819,7 +1952,7 @@ """ self.utFinished.emit() - self.clientExit.emit(int(status), "", True) + self.clientExit.emit(int(status), "", True, "") self.debugging = False self.running = False @@ -1846,21 +1979,31 @@ self.shutdownServer() self.appendStdout.emit(self.tr("Passive debug connection closed\n")) - def __restoreBreakpoints(self): + def __restoreBreakpoints(self, debuggerId=""): """ Private method to restore the breakpoints after a restart. + + @param debuggerId ID of the debugger backend to send to. If this is + empty, they will be broadcast to all connected backends. + @type str """ if self.debugging: self.__addBreakPoints( - QModelIndex(), 0, self.breakpointModel.rowCount() - 1) + QModelIndex(), 0, self.breakpointModel.rowCount() - 1, + debuggerId) - def __restoreWatchpoints(self): + def __restoreWatchpoints(self, debuggerId=""): """ Private method to restore the watch expressions after a restart. + + @param debuggerId ID of the debugger backend to send to. If this is + empty, they will be broadcast to all connected backends. + @type str """ if self.debugging: self.__addWatchPoints( - QModelIndex(), 0, self.watchpointModel.rowCount() - 1) + QModelIndex(), 0, self.watchpointModel.rowCount() - 1, + debuggerId) def getBreakPointModel(self): """ @@ -1927,3 +2070,13 @@ return self.debuggerInterface.getDebuggerIds() else: return [] + + def initializeClient(self, debuggerId): + """ + Public method to initialize a freshly connected debug client. + + @param debuggerId ID of the connected debugger + @type str + """ + self.__restoreBreakpoints(debuggerId) + self.__restoreWatchpoints(debuggerId)