eric6/Debugger/DebugServer.py

branch
multi_processing
changeset 7389
770ffcb88be5
parent 7379
72a72fd56494
child 7390
052ce4cf06c6
--- 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()
     

eric ide

mercurial