--- a/eric6/Debugger/DebugServer.py Sun Feb 02 12:01:27 2020 +0100 +++ b/eric6/Debugger/DebugServer.py Sun Feb 02 16:41:40 2020 +0100 @@ -11,7 +11,7 @@ import os import sys -from PyQt5.QtCore import pyqtSignal, QModelIndex +from PyQt5.QtCore import pyqtSignal, pyqtSlot, QModelIndex from PyQt5.QtNetwork import ( QTcpServer, QHostAddress, QHostInfo, QNetworkInterface ) @@ -42,8 +42,8 @@ @signal clientProcessStderr(str) emitted after the client has sent some output via stderr @signal clientOutput(str) emitted after the client has sent some output - @signal clientRawInputSent() emitted after the data was sent to the - debug client + @signal clientRawInputSent(debuggerId) emitted after the data was sent + to the indicated debug client @signal clientLine(filename, lineno, debuggerId, forStack) emitted after the debug client has executed a line of code @signal clientStack(stack, debuggerId) emitted after the debug client has @@ -72,16 +72,16 @@ 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 - signaled a syntax error in a breakpoint condition - @signal clientClearWatch(condition) emitted after the debug client - has decided to clear a temporary watch expression - @signal clientWatchConditionError(condition) emitted after the client has - signaled a syntax error in a watch expression - @signal clientRawInput(prompt, echo) emitted after a raw input request was - received + @signal clientClearBreak(filename, lineno, debuggerId) emitted after the + debug client has decided to clear a temporary breakpoint + @signal clientBreakConditionError(fn, lineno, debuggerId) emitted after the + client has signaled a syntax error in a breakpoint condition + @signal clientClearWatch(condition, debuggerId) emitted after the debug + client has decided to clear a temporary watch expression + @signal clientWatchConditionError(condition, debuggerId) emitted after the + client has signaled a syntax error in a watch expression + @signal clientRawInput(prompt, echo, debuggerId) emitted after a raw input + request was received @signal clientBanner(version, platform, dbgclient, venvname) emitted after the client banner data was received @signal clientCapabilities(capabilities, cltype, venvname) emitted after @@ -122,12 +122,13 @@ @signal clientDebuggerIds(debuggerIds) emitted to give the list of IDs of attached debugger backends """ - clientClearBreak = pyqtSignal(str, int) - clientClearWatch = pyqtSignal(str) + clientClearBreak = pyqtSignal(str, int, str) + clientClearWatch = pyqtSignal(str, str) + # TODO: check this signal for debuggerId clientGone = pyqtSignal(bool) clientProcessStdout = pyqtSignal(str) clientProcessStderr = pyqtSignal(str) - clientRawInputSent = pyqtSignal() + clientRawInputSent = pyqtSignal(str) clientOutput = pyqtSignal(str) clientLine = pyqtSignal(str, int, str, bool) clientStack = pyqtSignal(list, str) @@ -141,12 +142,13 @@ 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) + clientBreakConditionError = pyqtSignal(str, int, str) + clientWatchConditionError = pyqtSignal(str, str) + clientRawInput = pyqtSignal(str, bool, str) clientBanner = pyqtSignal(str, str, str, str) clientCapabilities = pyqtSignal(int, str, str) clientCompletionList = pyqtSignal(list, str) + # TODO: check this signal for debuggerId clientInterpreterChanged = pyqtSignal(str) clientDebuggerIds = pyqtSignal(list) utDiscovered = pyqtSignal(list, str, str) @@ -195,6 +197,10 @@ self.watchSpecialChanged = self.tr( "changed", "must be same as in EditWatchpointDialog") + # arrays to track already reported issues + self.__reportedBreakpointIssues = [] + self.__reportedWatchpointIssues = [] + self.networkInterface = Preferences.getDebugger("NetworkInterface") if self.networkInterface == "all": hostAddress = QHostAddress("0.0.0.0") # QHostAddress.Any) @@ -259,15 +265,16 @@ self.__maxVariableSize = Preferences.getDebugger("MaxVariableSize") self.__registerDebuggerInterfaces() - + def getHostAddress(self, localhost): """ Public method to get the IP address or hostname the debug server is listening. @param localhost flag indicating to return the address for localhost - (boolean) - @return IP address or hostname (string) + @type bool + @return IP address or hostname + @rtype str """ if self.networkInterface == "all": if localhost: @@ -282,14 +289,16 @@ else: return "{0}@@i{1}".format(self.networkInterface, self.networkInterfaceIndex) - + def __getNetworkInterfaceAndIndex(self, address): """ Private method to determine the network interface and the interface index. - @param address address to determine the info for (string) - @return tuple of network interface name (string) and index (integer) + @param address address to determine the info for + @type str + @return tuple of network interface name and index + @rtype tuple of (str, int) """ if address not in ["all", "allv6"]: for networkInterface in QNetworkInterface.allInterfaces(): @@ -302,7 +311,7 @@ networkInterface.index()) return "", 0 - + def preferencesChanged(self): """ Public slot to handle the preferencesChanged signal. @@ -318,7 +327,7 @@ reregister=True) self.__maxVariableSize = Preferences.getDebugger("MaxVariableSize") - + def registerDebuggerInterface(self, interfaceName, getRegistryData, reregister=False): """ @@ -352,7 +361,7 @@ self.__debuggerInterfaceRegistry[clientLanguage] = [ clientCapabilities, clientExtensions, interfaceCreator, interfaceName] - + def unregisterDebuggerInterface(self, interfaceName): """ Public method to unregister a debugger interface. @@ -369,7 +378,7 @@ for clientLanguage in clientLanguages: del self.__debuggerInterfaceRegistry[clientLanguage] del self.__debuggerInterfaces[interfaceName] - + def __findLanguageForExtension(self, ext): """ Private method to get the language associated with a file extension. @@ -384,7 +393,7 @@ return language return "" - + def __registerDebuggerInterfaces(self): """ Private method to register the available internal debugger interfaces. @@ -397,14 +406,16 @@ mod = getattr(mod, comp) self.registerDebuggerInterface(name, mod.getRegistryData) - + def getSupportedLanguages(self, shellOnly=False): """ Public slot to return the supported programming languages. @param shellOnly flag indicating only languages supporting an interactive shell should be returned - @return list of supported languages (list of strings) + @type bool + @return list of supported languages + @rtype list of str """ languages = list(self.__debuggerInterfaceRegistry.keys()) try: @@ -418,25 +429,27 @@ DebugClientCapabilities.HasShell] return languages[:] - + def getExtensions(self, language): """ Public slot to get the extensions associated with the given language. - @param language language to get extensions for (string) + @param language language to get extensions for + @type str @return tuple of extensions associated with the language - (tuple of strings) + @rtype tuple of str """ if language in self.__debuggerInterfaceRegistry: return tuple(self.__debuggerInterfaceRegistry[language][1]) else: return () - + def __createDebuggerInterface(self, clientType=None): """ Private slot to create the debugger interface object. - @param clientType type of the client interface to be created (string) + @param clientType type of the client interface to be created + @type str """ if self.lastClientType != self.clientType or clientType is not None: if clientType is None: @@ -450,18 +463,19 @@ self.__debuggerInterfaceRegistry["None"][2]( self, self.passive)) self.clientType = "None" - + def __setClientType(self, clType): """ Private method to set the client type. - @param clType type of client to be started (string) + @param clType type of client to be started + @type str """ if clType is not None and clType in self.getSupportedLanguages(): self.clientType = clType Preferences.Prefs.settings.setValue( 'DebugClient/Type', self.clientType) - + def startClient(self, unplanned=True, clType=None, forProject=False, runInConsole=False, venvName="", workingDir=None): """ @@ -547,7 +561,7 @@ if clientInterpreter != self.clientInterpreter: self.clientInterpreter = clientInterpreter self.clientInterpreterChanged.emit(clientInterpreter) - + def __clientProcessOutput(self): """ Private slot to process client output received via stdout. @@ -556,7 +570,7 @@ Preferences.getSystem("IOEncoding"), 'replace') self.clientProcessStdout.emit(output) - + def __clientProcessError(self): """ Private slot to process client output received via stderr. @@ -565,25 +579,33 @@ Preferences.getSystem("IOEncoding"), 'replace') self.clientProcessStderr.emit(error) - + + @pyqtSlot(str, int) def __clientClearBreakPoint(self, fn, lineno): """ Private slot to handle the clientClearBreak signal. - @param fn filename of breakpoint to clear (string) - @param lineno line number of breakpoint to clear (integer) + @param fn filename of breakpoint to clear + @type str + @param lineno line number of breakpoint to clear + @type int """ if self.debugging: index = self.breakpointModel.getBreakPointIndex(fn, lineno) self.breakpointModel.deleteBreakPointByIndex(index) - + if (fn, lineno) in self.__reportedBreakpointIssues: + self.__reportedBreakpointIssues.remove((fn, lineno)) + def __deleteBreakPoints(self, parentIndex, start, end): """ Private slot to delete 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 """ if self.debugging: for row in range(start, end + 1): @@ -592,30 +614,36 @@ self.breakpointModel.getBreakPointByIndex(index)[0:2]) # delete the breakpoints of all connected backends self.remoteBreakpoint("", fn, lineno, False) - + if (fn, lineno) in self.__reportedBreakpointIssues: + self.__reportedBreakpointIssues.remove((fn, lineno)) + def __changeBreakPoints(self, startIndex, endIndex): """ Private slot to set changed breakpoints. - @param startIndex starting index of the change breakpoins (QModelIndex) - @param endIndex ending index of the change breakpoins (QModelIndex) + @param startIndex starting index of the change breakpoins + @type QModelIndex + @param endIndex ending index of the change breakpoins + @type QModelIndex """ if self.debugging: self.__addBreakPoints( QModelIndex(), startIndex.row(), endIndex.row()) - + def __breakPointDataAboutToBeChanged(self, startIndex, endIndex): """ Private slot to handle the dataAboutToBeChanged signal of the breakpoint 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.__deleteBreakPoints( QModelIndex(), startIndex.row(), endIndex.row()) - + def __addBreakPoints(self, parentIndex, start, end, debuggerId=""): """ Private slot to add breakpoints. @@ -633,22 +661,30 @@ if self.debugging: for row in range(start, end + 1): index = self.breakpointModel.index(row, 0, parentIndex) - fn, line, cond, temp, enabled, ignorecount = ( + fn, lineno, cond, temp, enabled, ignorecount = ( self.breakpointModel.getBreakPointByIndex(index)[:6]) - self.remoteBreakpoint(debuggerId, fn, line, True, cond, temp) + + if (fn, lineno) in self.__reportedBreakpointIssues: + self.__reportedBreakpointIssues.remove((fn, lineno)) + + self.remoteBreakpoint(debuggerId, fn, lineno, True, cond, temp) if not enabled: - self.__remoteBreakpointEnable(debuggerId, fn, line, False) + self.__remoteBreakpointEnable( + debuggerId, fn, lineno, False) if ignorecount: self.__remoteBreakpointIgnore( - debuggerId, fn, line, ignorecount) - + debuggerId, fn, lineno, ignorecount) + def __makeWatchCondition(self, cond, special): """ Private method to construct the condition string. - @param cond condition (string) - @param special special condition (string) - @return condition string (string) + @param cond condition + @type str + @param special special condition + @type str + @return condition string + @rtype str """ if special == "": _cond = cond @@ -658,14 +694,15 @@ elif special == self.watchSpecialChanged: _cond = "{0} ??changed??".format(cond) return _cond - + def __splitWatchCondition(self, cond): """ Private method to split a remote watch expression. - @param cond remote expression (string) + @param cond remote expression + @type str @return tuple of local expression (string) and special condition - (string) + @rtype str """ if cond.endswith(" ??created??"): cond, special = cond.split() @@ -678,18 +715,22 @@ special = "" return cond, special - + + @pyqtSlot(str) def __clientClearWatchPoint(self, condition): """ Private slot to handle the clientClearWatch signal. - @param condition expression of watch expression to clear (string) + @param condition expression of watch expression to clear + @type str """ if self.debugging: cond, special = self.__splitWatchCondition(condition) index = self.watchpointModel.getWatchPointIndex(cond, special) self.watchpointModel.deleteWatchPointByIndex(index) - + if condition in self.__reportedWatchpointIssues: + self.__reportedWatchpointIssues.remove(condition) + def __deleteWatchPoints(self, parentIndex, start, end): """ Private slot to delete watch expressions. @@ -708,7 +749,9 @@ self.watchpointModel.getWatchPointByIndex(index)[0:2]) cond = self.__makeWatchCondition(cond, special) self.__remoteWatchpoint("", cond, False) - + if cond in self.__reportedWatchpointIssues: + self.__reportedWatchpointIssues.remove(cond) + def __watchPointDataAboutToBeChanged(self, startIndex, endIndex): """ Private slot to handle the dataAboutToBeChanged signal of the @@ -722,7 +765,7 @@ if self.debugging: self.__deleteWatchPoints( QModelIndex(), startIndex.row(), endIndex.row()) - + def __addWatchPoints(self, parentIndex, start, end, debuggerId=""): """ Private slot to set a watch expression. @@ -743,41 +786,50 @@ cond, special, temp, enabled, ignorecount = ( self.watchpointModel.getWatchPointByIndex(index)[:5]) cond = self.__makeWatchCondition(cond, special) + + if cond in self.__reportedWatchpointIssues: + self.__reportedWatchpointIssues.remove(cond) + self.__remoteWatchpoint(debuggerId, cond, True, temp) if not enabled: self.__remoteWatchpointEnable(debuggerId, cond, False) if ignorecount: self.__remoteWatchpointIgnore(debuggerId, cond, ignorecount) - + def __changeWatchPoints(self, startIndex, endIndex): """ Private slot to set changed watch expressions. - @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.__addWatchPoints( QModelIndex(), startIndex.row(), endIndex.row()) - + def getClientCapabilities(self, clientType): """ Public method to retrieve the debug clients capabilities. - @param clientType debug client type (string) - @return debug client capabilities (integer) + @param clientType debug client type + @type str + @return debug client capabilities + @rtype int """ try: return self.__debuggerInterfaceRegistry[clientType][0] except KeyError: return 0 # no capabilities - + def getClientInterpreter(self): """ Public method to get the interpreter of the debug client. - @return interpreter of the debug client (string) + @return interpreter of the debug client + @rtype str """ return self.clientInterpreter @@ -843,7 +895,7 @@ self.remoteBanner() elif self.passive: self.remoteBanner() - + def shutdownServer(self): """ Public method to cleanly shut down. @@ -853,12 +905,13 @@ """ if self.debuggerInterface is not None: self.debuggerInterface.shutdown() - + def remoteEnvironment(self, env): """ Public method to set the environment for a program to debug, run, ... - @param env environment settings (string) + @param env environment settings + @type str """ envlist = Utilities.parseEnvironmentString(env) envdict = {} @@ -871,7 +924,7 @@ except ValueError: pass self.debuggerInterface.remoteEnvironment(envdict) - + def remoteLoad(self, venvName, fn, argv, wd, env, autoClearShell=True, tracePython=False, autoContinue=True, forProject=False, runInConsole=False, autoFork=False, forkChild=False, @@ -948,7 +1001,7 @@ self.running = True self.__restoreBreakpoints() self.__restoreWatchpoints() - + def remoteRun(self, venvName, fn, argv, wd, env, autoClearShell=True, forProject=False, runInConsole=False, autoFork=False, forkChild=False, clientType=""): @@ -1010,7 +1063,7 @@ self.debuggerInterface.remoteRun(fn, argv, wd, autoFork, forkChild) self.debugging = False self.running = True - + def remoteCoverage(self, venvName, fn, argv, wd, env, autoClearShell=True, erase=False, forProject=False, runInConsole=False, clientType=""): @@ -1071,7 +1124,7 @@ self.debuggerInterface.remoteCoverage(fn, argv, wd, erase) self.debugging = False self.running = True - + def remoteProfile(self, venvName, fn, argv, wd, env, autoClearShell=True, erase=False, forProject=False, runInConsole=False, clientType=""): @@ -1132,7 +1185,7 @@ self.debuggerInterface.remoteProfile(fn, argv, wd, erase) self.debugging = False self.running = True - + def remoteStatement(self, debuggerId, stmt): """ Public method to execute a Python statement. @@ -1143,7 +1196,7 @@ @type str """ self.debuggerInterface.remoteStatement(debuggerId, stmt.rstrip()) - + def remoteStep(self, debuggerId): """ Public method to single step the debugged program. @@ -1152,7 +1205,7 @@ @type str """ self.debuggerInterface.remoteStep(debuggerId) - + def remoteStepOver(self, debuggerId): """ Public method to step over the debugged program. @@ -1161,7 +1214,7 @@ @type str """ self.debuggerInterface.remoteStepOver(debuggerId) - + def remoteStepOut(self, debuggerId): """ Public method to step out the debugged program. @@ -1170,7 +1223,7 @@ @type str """ self.debuggerInterface.remoteStepOut(debuggerId) - + def remoteStepQuit(self, debuggerId): """ Public method to stop the debugged program. @@ -1179,7 +1232,7 @@ @type str """ self.debuggerInterface.remoteStepQuit(debuggerId) - + def remoteContinue(self, debuggerId, special=False): """ Public method to continue the debugged program. @@ -1189,7 +1242,7 @@ @param special flag indicating a special continue operation """ self.debuggerInterface.remoteContinue(debuggerId, special) - + def remoteMoveIP(self, debuggerId, line): """ Public method to move the instruction pointer to a different line. @@ -1200,7 +1253,7 @@ @type int """ self.debuggerInterface.remoteMoveIP(debuggerId, line) - + def remoteBreakpoint(self, debuggerId, fn, line, setBreakpoint, cond=None, temp=False): """ @@ -1221,7 +1274,7 @@ """ self.debuggerInterface.remoteBreakpoint( debuggerId, fn, line, setBreakpoint, cond, temp) - + def __remoteBreakpointEnable(self, debuggerId, fn, line, enable): """ Private method to enable or disable a breakpoint. @@ -1237,7 +1290,7 @@ """ self.debuggerInterface.remoteBreakpointEnable( debuggerId, fn, line, enable) - + def __remoteBreakpointIgnore(self, debuggerId, fn, line, count): """ Private method to ignore a breakpoint the next couple of occurrences. @@ -1253,7 +1306,7 @@ """ self.debuggerInterface.remoteBreakpointIgnore( debuggerId, fn, line, count) - + def __remoteWatchpoint(self, debuggerId, cond, setWatch, temp=False): """ Private method to set or clear a watch expression. @@ -1300,15 +1353,18 @@ # cond is combination of cond and special (s. watch expression viewer) self.debuggerInterface.remoteWatchpointIgnore(debuggerId, cond, count) - def remoteRawInput(self, s): + def remoteRawInput(self, debuggerId, inputString): """ Public method to send the raw input to the debugged program. - @param s the raw input (string) + @param debuggerId ID of the debugger backend + @type str + @param inputString the raw input + @type str """ - self.debuggerInterface.remoteRawInput(s) - self.clientRawInputSent.emit() - + self.debuggerInterface.remoteRawInput(debuggerId, inputString) + self.clientRawInputSent.emit(debuggerId) + def remoteThreadList(self, debuggerId): """ Public method to request the list of threads from the client. @@ -1317,7 +1373,7 @@ @type str """ self.debuggerInterface.remoteThreadList(debuggerId) - + def remoteSetThread(self, debuggerId, tid): """ Public method to request to set the given thread as current thread. @@ -1353,7 +1409,7 @@ """ self.debuggerInterface.remoteClientVariables( debuggerId, scope, filterList, framenr, self.__maxVariableSize) - + def remoteClientVariable(self, debuggerId, scope, filterList, var, framenr=0, maxSize=0): """ @@ -1377,17 +1433,21 @@ self.debuggerInterface.remoteClientVariable( debuggerId, scope, filterList, var, framenr, self.__maxVariableSize) - - def remoteClientSetFilter(self, scope, filterStr): + + def remoteClientSetFilter(self, debuggerId, scope, filterStr): """ Public method to set a variables filter list. + @param debuggerId ID of the debugger backend + @type str @param scope the scope of the variables (0 = local, 1 = global) + @type int @param filterStr regexp string for variable names to filter out - (string) + @type str """ - self.debuggerInterface.remoteClientSetFilter(scope, filterStr) - + self.debuggerInterface.remoteClientSetFilter( + debuggerId, scope, filterStr) + def setCallTraceEnabled(self, debuggerId, on): """ Public method to set the call trace state. @@ -1398,19 +1458,19 @@ @type bool """ self.debuggerInterface.setCallTraceEnabled(debuggerId, on) - + def remoteBanner(self): """ Public slot to get the banner info of the remote client. """ self.debuggerInterface.remoteBanner() - + def remoteCapabilities(self): """ Public slot to get the debug clients capabilities. """ self.debuggerInterface.remoteCapabilities() - + def remoteCompletion(self, text): """ Public slot to get the a list of possible commandline completions @@ -1533,7 +1593,7 @@ if debug: self.__restoreBreakpoints() self.__restoreWatchpoints() - + def remoteUTRun(self, debug=False, failfast=False): """ Public method to start a unittest run. @@ -1544,13 +1604,13 @@ @type bool """ self.debuggerInterface.remoteUTRun(debug, failfast) - + def remoteUTStop(self): """ public method to stop a unittest run. """ self.debuggerInterface.remoteUTStop() - + def signalClientOutput(self, line, debuggerId): """ Public method to process a line of client output. @@ -1564,7 +1624,7 @@ self.clientOutput.emit("{0}: {1}".format(debuggerId, line)) else: self.clientOutput.emit(line) - + def signalClientLine(self, filename, lineno, debuggerId, forStack=False): """ Public method to process client position feedback. @@ -1579,7 +1639,7 @@ @type bool """ self.clientLine.emit(filename, lineno, debuggerId, forStack) - + def signalClientStack(self, stack, debuggerId): """ Public method to process a client's stack information. @@ -1591,7 +1651,7 @@ @type str """ self.clientStack.emit(stack, debuggerId) - + def signalClientThreadList(self, currentId, threadList, debuggerId): """ Public method to process the client thread list info. @@ -1604,7 +1664,7 @@ @type str """ self.clientThreadList.emit(currentId, threadList, debuggerId) - + def signalClientThreadSet(self, debuggerId): """ Public method to handle the change of the client thread. @@ -1613,7 +1673,7 @@ @type str """ self.clientThreadSet.emit(debuggerId) - + def signalClientVariables(self, scope, variables, debuggerId): """ Public method to process the client variables info. @@ -1627,7 +1687,7 @@ @type str """ self.clientVariables.emit(scope, variables, debuggerId) - + def signalClientVariable(self, scope, variables, debuggerId): """ Public method to process the client variable info. @@ -1641,7 +1701,7 @@ @type str """ self.clientVariable.emit(scope, variables, debuggerId) - + def signalClientStatement(self, more, debuggerId): """ Public method to process the input response from the client. @@ -1652,7 +1712,7 @@ @type str """ self.clientStatement.emit(more, debuggerId) - + def signalClientException(self, exceptionType, exceptionMessage, stackTrace, debuggerId): """ @@ -1672,7 +1732,7 @@ if self.running: self.clientException.emit(exceptionType, exceptionMessage, stackTrace, debuggerId) - + def signalClientSyntaxError(self, message, filename, lineNo, characterNo, debuggerId): """ @@ -1692,7 +1752,7 @@ if self.running: self.clientSyntaxError.emit(message, filename, lineNo, characterNo, debuggerId) - + def signalClientSignal(self, message, filename, lineNo, funcName, funcArgs, debuggerId): """ @@ -1714,7 +1774,7 @@ if self.running: self.clientSignal.emit(message, filename, lineNo, funcName, funcArgs, debuggerId) - + def signalClientExit(self, status, message, debuggerId): """ Public method to process the client exit status. @@ -1745,49 +1805,71 @@ self.signalClientStatement(False, "") self.running = False - def signalClientClearBreak(self, filename, lineno): + def signalClientClearBreak(self, filename, lineno, debuggerId): """ Public method to process the client clear breakpoint command. - @param filename filename of the breakpoint (string) - @param lineno line umber of the breakpoint (integer) + @param filename filename of the breakpoint + @type str + @param lineno line umber of the breakpoint + @type int + @param debuggerId ID of the debugger backend + @type str """ - self.clientClearBreak.emit(filename, lineno) - - def signalClientBreakConditionError(self, filename, lineno): + self.clientClearBreak.emit(filename, lineno, debuggerId) + + def signalClientBreakConditionError(self, filename, lineno, debuggerId): """ Public method to process the client breakpoint condition error info. - @param filename filename of the breakpoint (string) - @param lineno line umber of the breakpoint (integer) + @param filename filename of the breakpoint + @type str + @param lineno line umber of the breakpoint + @type int + @param debuggerId ID of the debugger backend + @type str """ - self.clientBreakConditionError.emit(filename, lineno) - - def signalClientClearWatch(self, condition): + if (filename, lineno) not in self.__reportedBreakpointIssues: + self.__reportedBreakpointIssues.append((filename, lineno)) + self.clientBreakConditionError.emit(filename, lineno, debuggerId) + + def signalClientClearWatch(self, condition, debuggerId): """ Public slot to handle the clientClearWatch signal. - @param condition expression of watch expression to clear (string) + @param condition expression of watch expression to clear + @type str + @param debuggerId ID of the debugger backend + @type str """ - self.clientClearWatch.emit(condition) - - def signalClientWatchConditionError(self, condition): + self.clientClearWatch.emit(condition, debuggerId) + + def signalClientWatchConditionError(self, condition, debuggerId): """ Public method to process the client watch expression error info. - @param condition expression of watch expression to clear (string) + @param condition expression of watch expression to clear + @type str + @param debuggerId ID of the debugger backend + @type str """ - self.clientWatchConditionError.emit(condition) - - def signalClientRawInput(self, prompt, echo): + if condition not in self.__reportedWatchpointIssues: + self.__reportedWatchpointIssues.append(condition) + self.clientWatchConditionError.emit(condition, debuggerId) + + def signalClientRawInput(self, prompt, echo, debuggerId): """ Public method to process the client raw input command. - @param prompt the input prompt (string) - @param echo flag indicating an echoing of the input (boolean) + @param prompt the input prompt + @type str + @param echo flag indicating an echoing of the input + @type bool + @param debuggerId ID of the debugger backend + @type str """ - self.clientRawInput.emit(prompt, echo) - + self.clientRawInput.emit(prompt, echo, debuggerId) + def signalClientBanner(self, version, platform, debugClient, venvName): """ Public method to process the client banner info. @@ -1820,16 +1902,18 @@ except KeyError: # ignore silently pass - + def signalClientCompletionList(self, completionList, text): """ Public method to process the client auto completion info. - @param completionList list of possible completions (list of strings) - @param text the text to be completed (string) + @param completionList list of possible completions + @type list of str + @param text the text to be completed + @type str """ self.clientCompletionList.emit(completionList, text) - + def signalClientCallTrace(self, isCall, fromFile, fromLine, fromFunction, toFile, toLine, toFunction, debuggerId): """ @@ -1868,81 +1952,100 @@ @type str """ self.utDiscovered.emit(testCases, exceptionType, exceptionValue) - + def clientUtPrepared(self, result, exceptionType, exceptionValue): """ Public method to process the client unittest prepared info. - @param result number of test cases (0 = error) (integer) - @param exceptionType exception type (string) - @param exceptionValue exception message (string) + @param result number of test cases (0 = error) + @type int + @param exceptionType exception type + @type str + @param exceptionValue exception message + @type str """ self.utPrepared.emit(result, exceptionType, exceptionValue) - + def clientUtStartTest(self, testname, doc): """ Public method to process the client start test info. - @param testname name of the test (string) - @param doc short description of the test (string) + @param testname name of the test + @type str + @param doc short description of the test + @type str """ self.utStartTest.emit(testname, doc) - + def clientUtStopTest(self): """ Public method to process the client stop test info. """ self.utStopTest.emit() - + def clientUtTestFailed(self, testname, traceback, testId): """ Public method to process the client test failed info. - @param testname name of the test (string) - @param traceback lines of traceback info (list of strings) - @param testId id of the test (string) + @param testname name of the test + @type str + @param traceback lines of traceback info + @type list of str + @param testId id of the test + @type str """ self.utTestFailed.emit(testname, traceback, testId) - + def clientUtTestErrored(self, testname, traceback, testId): """ Public method to process the client test errored info. - @param testname name of the test (string) - @param traceback lines of traceback info (list of strings) - @param testId id of the test (string) + @param testname name of the test + @type str + @param traceback lines of traceback info + @type list of str + @param testId id of the test + @type str """ self.utTestErrored.emit(testname, traceback, testId) - + def clientUtTestSkipped(self, testname, reason, testId): """ Public method to process the client test skipped info. - @param testname name of the test (string) - @param reason reason for skipping the test (string) - @param testId id of the test (string) + @param testname name of the test + @type str + @param reason reason for skipping the test + @type str + @param testId id of the test + @type str """ self.utTestSkipped.emit(testname, reason, testId) - + def clientUtTestFailedExpected(self, testname, traceback, testId): """ Public method to process the client test failed expected info. - @param testname name of the test (string) - @param traceback lines of traceback info (list of strings) - @param testId id of the test (string) + @param testname name of the test + @type str + @param traceback lines of traceback info + @type list of str + @param testId id of the test + @type str """ self.utTestFailedExpected.emit(testname, traceback, testId) - + def clientUtTestSucceededUnexpected(self, testname, testId): """ Public method to process the client test succeeded unexpected info. - @param testname name of the test (string) - @param testId id of the test (string) + @param testname name of the test + @type str + @param testId id of the test + @type str """ self.utTestSucceededUnexpected.emit(testname, testId) - + def clientUtFinished(self, status): """ Public method to process the client unit test finished info. @@ -1955,13 +2058,15 @@ self.clientExit.emit(int(status), "", True, "") self.debugging = False self.running = False - + def passiveStartUp(self, fn, exc): """ Public method to handle a passive debug connection. - @param fn filename of the debugged script (string) - @param exc flag to enable exception reporting of the IDE (boolean) + @param fn filename of the debugged script + @type str + @param exc flag to enable exception reporting of the IDE + @type bool """ self.appendStdout.emit(self.tr("Passive debug connection received\n")) self.passiveClientExited = False @@ -1970,7 +2075,7 @@ self.__restoreBreakpoints() self.__restoreWatchpoints() self.passiveDebugStarted.emit(fn, exc) - + def __passiveShutDown(self): """ Private method to shut down a passive debug connection. @@ -1978,7 +2083,7 @@ self.passiveClientExited = True self.shutdownServer() self.appendStdout.emit(self.tr("Passive debug connection closed\n")) - + def __restoreBreakpoints(self, debuggerId=""): """ Private method to restore the breakpoints after a restart. @@ -2009,16 +2114,17 @@ """ Public slot to get a reference to the breakpoint model object. - @return reference to the breakpoint model object (BreakPointModel) + @return reference to the breakpoint model object + @rtype BreakPointModel """ return self.breakpointModel - + def getWatchPointModel(self): """ Public slot to get a reference to the watch expression model object. @return reference to the watch expression model object - (WatchPointModel) + @rtype WatchPointModel """ return self.watchpointModel @@ -2026,7 +2132,8 @@ """ Public method to test, if the debug server is connected to a backend. - @return flag indicating a connection (boolean) + @return flag indicating a connection + @rtype bool """ return self.debuggerInterface and self.debuggerInterface.isConnected()