Debugger/DebugServer.py

branch
maintenance
changeset 6395
613e37fabd96
parent 6319
df201b9fbad4
parent 6376
201067699041
child 6455
22a6fc33ab6d
diff -r 4c45d163c6ac -r 613e37fabd96 Debugger/DebugServer.py
--- a/Debugger/DebugServer.py	Sat Jun 02 12:46:57 2018 +0200
+++ b/Debugger/DebugServer.py	Mon Jul 02 18:59:30 2018 +0200
@@ -218,10 +218,10 @@
         # Change clientType if dependent interpreter not exist anymore
         # (maybe deinstalled,...)
         elif self.clientType == 'Python2' and Preferences.getDebugger(
-                "PythonInterpreter") == '':
+                "Python2VirtualEnv") == '':
             self.clientType = 'Python3'
         elif self.clientType == 'Python3' and Preferences.getDebugger(
-                "Python3Interpreter") == '':
+                "Python3VirtualEnv") == '':
             self.clientType = 'Python2'
         
         self.lastClientType = ''
@@ -301,14 +301,15 @@
             registeredInterfaces[interfaceName] = \
                 self.__debuggerInterfaces[interfaceName]
         
-        self.__debuggerInterfaces = {}
         self.__debuggerInterfaceRegistry = {}
         for interfaceName, getRegistryData in registeredInterfaces.items():
-            self.registerDebuggerInterface(interfaceName, getRegistryData)
+            self.registerDebuggerInterface(interfaceName, getRegistryData,
+                                           reregister=True)
         
         self.__maxVariableSize = Preferences.getDebugger("MaxVariableSize")
         
-    def registerDebuggerInterface(self, interfaceName, getRegistryData):
+    def registerDebuggerInterface(self, interfaceName, getRegistryData,
+                                  reregister=False):
         """
         Public method to register a debugger interface.
         
@@ -320,8 +321,10 @@
             list of associated file extensions and a function reference
             to create the debugger interface (see __createDebuggerInterface())
         @type function
+        @param reregister flag indicating to re-register the interface
+        @type bool
         """
-        if interfaceName in self.__debuggerInterfaces:
+        if interfaceName in self.__debuggerInterfaces and not reregister:
             E5MessageBox.warning(
                 None,
                 self.tr("Register Debugger Interface"),
@@ -329,9 +332,10 @@
                         """ been registered. Ignoring this request.</p>"""))
             return
         
+        if not reregister:
+            self.__debuggerInterfaces[interfaceName] = getRegistryData
         registryDataList = getRegistryData()
         if registryDataList:
-            self.__debuggerInterfaces[interfaceName] = getRegistryData
             for clientLanguage, clientCapabilities, clientExtensions, \
                     interfaceCreator in registryDataList:
                 self.__debuggerInterfaceRegistry[clientLanguage] = [
@@ -449,17 +453,21 @@
                 'DebugClient/Type', self.clientType)
         
     def startClient(self, unplanned=True, clType=None, forProject=False,
-                    runInConsole=False, interpreter=""):
+                    runInConsole=False, venvName=""):
         """
         Public method to start a debug client.
         
-        @keyparam unplanned flag indicating that the client has died (boolean)
-        @keyparam clType type of client to be started (string)
-        @keyparam forProject flag indicating a project related action (boolean)
+        @keyparam unplanned flag indicating that the client has died
+        @type bool
+        @keyparam clType type of client to be started
+        @type str
+        @keyparam forProject flag indicating a project related action
+        @type bool
         @keyparam runInConsole flag indicating to start the debugger in a
-            console window (boolean)
-        @keyparam interpreter interpreter to be used to execute the remote
-            side (string)
+            console window
+        @type bool
+        @keyparam venvName name of the virtual environment to be used
+        @type str
         """
         self.running = False
         
@@ -469,6 +477,10 @@
                 self.clientGone.emit(unplanned and self.debugging)
         
         if clType:
+            if clType not in self.getSupportedLanguages():
+                # a not supported client language was requested
+                return
+            
             self.__setClientType(clType)
         
         # only start the client, if we are not in passive mode
@@ -485,15 +497,15 @@
                 if not project.isDebugPropertiesLoaded():
                     self.clientProcess, isNetworked, clientInterpreter = \
                         self.debuggerInterface.startRemote(
-                            self.serverPort(), runInConsole, interpreter)
+                            self.serverPort(), runInConsole, venvName)
                 else:
                     self.clientProcess, isNetworked, clientInterpreter = \
                         self.debuggerInterface.startRemoteForProject(
-                            self.serverPort(), runInConsole, interpreter)
+                            self.serverPort(), runInConsole, venvName)
             else:
                 self.clientProcess, isNetworked, clientInterpreter = \
                     self.debuggerInterface.startRemote(
-                        self.serverPort(), runInConsole, interpreter)
+                        self.serverPort(), runInConsole, venvName)
             
             if self.clientProcess:
                 self.clientProcess.readyReadStandardError.connect(
@@ -733,7 +745,25 @@
         @return interpreter of the debug client (string)
         """
         return self.clientInterpreter
+    
+    def getClientType(self):
+        """
+        Public method to get the currently running debug client type.
         
+        @return debug client type
+        @rtype str
+        """
+        return self.clientType
+    
+    def isClientProcessUp(self):
+        """
+        Public method to check, if the debug client process is up.
+        
+        @return flag indicating a running debug client process
+        @rtype bool
+        """
+        return self.clientProcess is not None
+    
     def __newConnection(self):
         """
         Private slot to handle a new connection.
@@ -804,38 +834,61 @@
                 pass
         self.debuggerInterface.remoteEnvironment(envdict)
         
-    def remoteLoad(self, interpreter, fn, argv, wd, env, autoClearShell=True,
+    def remoteLoad(self, venvName, fn, argv, wd, env, autoClearShell=True,
                    tracePython=False, autoContinue=True, forProject=False,
                    runInConsole=False, autoFork=False, forkChild=False,
                    clientType="", enableCallTrace=False):
         """
         Public method to load a new program to debug.
         
-        @param interpreter interpreter to be used to execute the remote
-            side (string)
-        @param fn the filename to debug (string)
-        @param argv the commandline arguments to pass to the program (string)
-        @param wd the working directory for the program (string)
-        @param env environment settings (string)
+        @param venvName name of the virtual environment to be used
+        @type str
+        @param fn the filename to debug
+        @type str
+        @param argv the command line arguments to pass to the program
+        @type str
+        @param wd the working directory for the program
+        @type str
+        @param env environment parameter settings
+        @type str
         @keyparam autoClearShell flag indicating, that the interpreter window
-            should be cleared (boolean)
+            should be cleared
+        @type bool
         @keyparam tracePython flag indicating if the Python library should be
-            traced as well (boolean)
+            traced as well
+        @type bool
         @keyparam autoContinue flag indicating, that the debugger should not
-            stop at the first executable line (boolean)
-        @keyparam forProject flag indicating a project related action (boolean)
+            stop at the first executable line
+        @type bool
+        @keyparam forProject flag indicating a project related action
+        @type bool
         @keyparam runInConsole flag indicating to start the debugger in a
-            console window (boolean)
-        @keyparam autoFork flag indicating the automatic fork mode (boolean)
+            console window
+        @type bool
+        @keyparam autoFork flag indicating the automatic fork mode
+        @type bool
         @keyparam forkChild flag indicating to debug the child after forking
-            (boolean)
-        @keyparam clientType client type to be used (string)
+        @type bool
+        @keyparam clientType client type to be used
+        @type str
         @keyparam enableCallTrace flag indicating to enable the call trace
-            function (boolean)
+            function
+        @type bool
         """
         self.__autoClearShell = autoClearShell
         self.__autoContinue = autoContinue
         
+        if clientType not in self.getSupportedLanguages():
+            # a not supported client language was requested
+            E5MessageBox.critical(
+                None,
+                self.tr("Start Debugger"),
+                self.tr(
+                    """<p>The debugger type <b>{0}</b> is not supported"""
+                    """ or not configured.</p>""").format(clientType)
+            )
+            return
+        
         # Restart the client
         try:
             if clientType:
@@ -846,7 +899,7 @@
         except KeyError:
             self.__setClientType('Python3')    # assume it is a Python3 file
         self.startClient(False, forProject=forProject,
-                         runInConsole=runInConsole, interpreter=interpreter)
+                         runInConsole=runInConsole, venvName=venvName)
         
         self.setCallTraceEnabled(enableCallTrace)
         self.remoteEnvironment(env)
@@ -858,30 +911,50 @@
         self.__restoreBreakpoints()
         self.__restoreWatchpoints()
 
-    def remoteRun(self, interpreter, fn, argv, wd, env, autoClearShell=True,
+    def remoteRun(self, venvName, fn, argv, wd, env, autoClearShell=True,
                   forProject=False, runInConsole=False, autoFork=False,
                   forkChild=False, clientType=""):
         """
         Public method to load a new program to run.
         
-        @param interpreter interpreter to be used to execute the remote
-            side (string)
-        @param fn the filename to run (string)
-        @param argv the commandline arguments to pass to the program (string)
-        @param wd the working directory for the program (string)
-        @param env environment settings (string)
+        @param venvName name of the virtual environment to be used
+        @type str
+        @param fn the filename to debug
+        @type str
+        @param argv the command line arguments to pass to the program
+        @type str
+        @param wd the working directory for the program
+        @type str
+        @param env environment parameter settings
+        @type str
         @keyparam autoClearShell flag indicating, that the interpreter window
-            should be cleared (boolean)
-        @keyparam forProject flag indicating a project related action (boolean)
+            should be cleared
+        @type bool
+        @keyparam forProject flag indicating a project related action
+        @type bool
         @keyparam runInConsole flag indicating to start the debugger in a
-            console window (boolean)
-        @keyparam autoFork flag indicating the automatic fork mode (boolean)
+            console window
+        @type bool
+        @keyparam autoFork flag indicating the automatic fork mode
+        @type bool
         @keyparam forkChild flag indicating to debug the child after forking
-            (boolean)
-        @keyparam clientType client type to be used (string)
+        @type bool
+        @keyparam clientType client type to be used
+        @type str
         """
         self.__autoClearShell = autoClearShell
         
+        if clientType not in self.getSupportedLanguages():
+            E5MessageBox.critical(
+                None,
+                self.tr("Start Debugger"),
+                self.tr(
+                    """<p>The debugger type <b>{0}</b> is not supported"""
+                    """ or not configured.</p>""").format(clientType)
+            )
+            # a not supported client language was requested
+            return
+        
         # Restart the client
         try:
             if clientType:
@@ -892,7 +965,7 @@
         except KeyError:
             self.__setClientType('Python3')    # assume it is a Python3 file
         self.startClient(False, forProject=forProject,
-                         runInConsole=runInConsole, interpreter=interpreter)
+                         runInConsole=runInConsole, venvName=venvName)
         
         self.remoteEnvironment(env)
         
@@ -900,29 +973,49 @@
         self.debugging = False
         self.running = True
 
-    def remoteCoverage(self, interpreter, fn, argv, wd, env,
+    def remoteCoverage(self, venvName, fn, argv, wd, env,
                        autoClearShell=True, erase=False, forProject=False,
                        runInConsole=False, clientType=""):
         """
         Public method to load a new program to collect coverage data.
         
-        @param interpreter interpreter to be used to execute the remote
-            side (string)
-        @param fn the filename to run (string)
-        @param argv the commandline arguments to pass to the program (string)
-        @param wd the working directory for the program (string)
-        @param env environment settings (string)
+        @param venvName name of the virtual environment to be used
+        @type str
+        @param fn the filename to debug
+        @type str
+        @param argv the command line arguments to pass to the program
+        @type str
+        @param wd the working directory for the program
+        @type str
+        @param env environment parameter settings
+        @type str
         @keyparam autoClearShell flag indicating, that the interpreter window
-            should be cleared (boolean)
+            should be cleared
+        @type bool
         @keyparam erase flag indicating that coverage info should be
-            cleared first (boolean)
-        @keyparam forProject flag indicating a project related action (boolean)
+            cleared first
+        @type bool
+        @keyparam forProject flag indicating a project related action
+        @type bool
         @keyparam runInConsole flag indicating to start the debugger in a
-            console window (boolean)
-        @keyparam clientType client type to be used (string)
+            console window
+        @type bool
+        @keyparam clientType client type to be used
+        @type str
         """
         self.__autoClearShell = autoClearShell
         
+        if clientType not in self.getSupportedLanguages():
+            # a not supported client language was requested
+            E5MessageBox.critical(
+                None,
+                self.tr("Start Debugger"),
+                self.tr(
+                    """<p>The debugger type <b>{0}</b> is not supported"""
+                    """ or not configured.</p>""").format(clientType)
+            )
+            return
+        
         # Restart the client
         try:
             if clientType:
@@ -933,7 +1026,7 @@
         except KeyError:
             self.__setClientType('Python3')    # assume it is a Python3 file
         self.startClient(False, forProject=forProject,
-                         runInConsole=runInConsole, interpreter=interpreter)
+                         runInConsole=runInConsole, venvName=venvName)
         
         self.remoteEnvironment(env)
         
@@ -941,29 +1034,49 @@
         self.debugging = False
         self.running = True
 
-    def remoteProfile(self, interpreter, fn, argv, wd, env,
+    def remoteProfile(self, venvName, fn, argv, wd, env,
                       autoClearShell=True, erase=False, forProject=False,
                       runInConsole=False, clientType=""):
         """
         Public method to load a new program to collect profiling data.
         
-        @param interpreter interpreter to be used to execute the remote
-            side (string)
-        @param fn the filename to run (string)
-        @param argv the commandline arguments to pass to the program (string)
-        @param wd the working directory for the program (string)
-        @param env environment settings (string)
+        @param venvName name of the virtual environment to be used
+        @type str
+        @param fn the filename to debug
+        @type str
+        @param argv the command line arguments to pass to the program
+        @type str
+        @param wd the working directory for the program
+        @type str
+        @param env environment parameter settings
+        @type str
         @keyparam autoClearShell flag indicating, that the interpreter window
-            should be cleared (boolean)
-        @keyparam erase flag indicating that timing info should be cleared
-            first (boolean)
-        @keyparam forProject flag indicating a project related action (boolean)
+            should be cleared
+        @type bool
+        @keyparam erase flag indicating that coverage info should be
+            cleared first
+        @type bool
+        @keyparam forProject flag indicating a project related action
+        @type bool
         @keyparam runInConsole flag indicating to start the debugger in a
-            console window (boolean)
-        @keyparam clientType client type to be used (string)
+            console window
+        @type bool
+        @keyparam clientType client type to be used
+        @type str
         """
         self.__autoClearShell = autoClearShell
         
+        if clientType not in self.getSupportedLanguages():
+            # a not supported client language was requested
+            E5MessageBox.critical(
+                None,
+                self.tr("Start Debugger"),
+                self.tr(
+                    """<p>The debugger type <b>{0}</b> is not supported"""
+                    """ or not configured.</p>""").format(clientType)
+            )
+            return
+        
         # Restart the client
         try:
             if clientType:
@@ -974,7 +1087,7 @@
         except KeyError:
             self.__setClientType('Python3')    # assume it is a Python3 file
         self.startClient(False, forProject=forProject,
-                         runInConsole=runInConsole, interpreter=interpreter)
+                         runInConsole=runInConsole, venvName=venvName)
         
         self.remoteEnvironment(env)
         
@@ -1203,6 +1316,17 @@
             (boolean)
         @keyparam clientType client type to be used (string)
         """
+        if clientType not in self.getSupportedLanguages():
+            # a not supported client language was requested
+            E5MessageBox.critical(
+                None,
+                self.tr("Start Debugger"),
+                self.tr(
+                    """<p>The debugger type <b>{0}</b> is not supported"""
+                    """ or not configured.</p>""").format(clientType)
+            )
+            return
+        
         # Restart the client if there is already a program loaded.
         try:
             if clientType:
@@ -1432,8 +1556,12 @@
         @param capabilities bitmaks with the client capabilities (integer)
         @param clientType type of the debug client (string)
         """
-        self.__debuggerInterfaceRegistry[clientType][0] = capabilities
-        self.clientCapabilities.emit(capabilities, clientType)
+        try:
+            self.__debuggerInterfaceRegistry[clientType][0] = capabilities
+            self.clientCapabilities.emit(capabilities, clientType)
+        except KeyError:
+            # ignore silently
+            pass
         
     def signalClientCompletionList(self, completionList, text):
         """

eric ide

mercurial