Continued with the multiprocess debugger. multi_processing

Fri, 14 Feb 2020 19:52:37 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 14 Feb 2020 19:52:37 +0100
branch
multi_processing
changeset 7412
0a995393d2ba
parent 7411
6d8dcb3551b3
child 7415
e953b2a449a9

Continued with the multiprocess debugger.

eric6/DebugClients/Python/DebugClient.py file | annotate | diff | comparison | revisions
eric6/DebugClients/Python/DebugClientBase.py file | annotate | diff | comparison | revisions
eric6/DebugClients/Python/DebugUtilities.py file | annotate | diff | comparison | revisions
eric6/DebugClients/Python/QProcessExtension.py file | annotate | diff | comparison | revisions
eric6/DebugClients/Python/ThreadExtension.py file | annotate | diff | comparison | revisions
eric6/Debugger/DebugServer.py file | annotate | diff | comparison | revisions
eric6/Debugger/DebugViewer.py file | annotate | diff | comparison | revisions
eric6/Debugger/DebuggerInterfaceNone.py file | annotate | diff | comparison | revisions
eric6/Debugger/DebuggerInterfacePython.py file | annotate | diff | comparison | revisions
eric6/QScintilla/Shell.py file | annotate | diff | comparison | revisions
--- a/eric6/DebugClients/Python/DebugClient.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/DebugClients/Python/DebugClient.py	Fri Feb 14 19:52:37 2020 +0100
@@ -16,9 +16,6 @@
 class DebugClient(DebugClientBase, DebugBase, ThreadExtension):
     """
     Class implementing the client side of the debugger.
-    
-    This variant of the debugger implements the standard debugger client
-    by subclassing all relevant base classes.
     """
     def __init__(self):
         """
@@ -31,8 +28,6 @@
         ThreadExtension.__init__(self)
         
         self.__moduleLoader = ModuleLoader(self)
-        
-        self.variant = 'Standard'
 
 # We are normally called by the debugger to execute directly.
 
--- a/eric6/DebugClients/Python/DebugClientBase.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/DebugClients/Python/DebugClientBase.py	Fri Feb 14 19:52:37 2020 +0100
@@ -246,8 +246,6 @@
         
         self.callTraceEnabled = None
         
-        self.variant = 'You should not see this'
-        
         self.compile_command = codeop.CommandCompiler()
         
         self.coding_re = re.compile(r"coding[:=]\s*([-\w_.]+)")
@@ -450,7 +448,6 @@
             self.sendJsonCommand("ResponseBanner", {
                 "version": "Python {0}".format(sys.version),
                 "platform": socket.gethostname(),
-                "dbgclient": self.variant,
             })
         
         elif method == "RequestSetFilter":
--- a/eric6/DebugClients/Python/DebugUtilities.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/DebugClients/Python/DebugUtilities.py	Fri Feb 14 19:52:37 2020 +0100
@@ -8,6 +8,7 @@
 """
 
 import json
+import os
 
 #
 # Taken from inspect.py of Python 3.4
@@ -145,5 +146,72 @@
     }
     return json.dumps(commandDict) + '\n'
 
+
+def isPythonProgram(program, arguments):
+    """
+    Function to check, if program is a Python interpreter and
+    arguments don't include '-m'.
+    
+    @param program program to be executed
+    @type str
+    @param arguments list of command line arguments
+    @type list of str
+    @return flag indicating a python program and a tuple containing the
+        interpreter to be used and the arguments
+    @rtype tuple of (bool, tuple of (str, list of str))
+    """
+    prog = program.lower()
+    ok = (
+        ("python" in prog and arguments[0] != '-m') or
+        "pypy" in prog
+    )
+    return ok, (program, arguments[:])
+
+
+def patchArguments(debugClient, arguments, multiprocessSupport,
+                   noRedirect=False):
+    """
+    Function to patch the arguments given to start a program in order to
+    execute it in our debugger.
+    
+    @param debugClient reference to the debug client object
+    @type DebugClient
+    @param arguments list of program arguments
+    @type list of str
+    @param multiprocessSupport flag indicating multi process debug support
+    @type bool
+    @param noRedirect flag indicating to not redirect stdin and stdout
+    @type bool
+    @return modified argument list
+    @rtype list of str
+    """
+    (wd, host, port, exceptions, tracePython, redirect, noencoding
+     ) = debugClient.startOptions[:7]
+    
+    modifiedArguments = [
+        os.path.join(os.path.dirname(__file__), "DebugClient.py"),
+        "-h", host,
+        "-p", str(port),
+        "--no-passive",
+    ]
+    
+    if wd:
+        modifiedArguments.extend(["-w", wd])
+    if not exceptions:
+        modifiedArguments.append("-e")
+    if tracePython:
+        modifiedArguments.append("-t")
+    if noRedirect or not redirect:
+        modifiedArguments.append("-n")
+    if noencoding:
+        modifiedArguments.append("--no-encoding")
+    if multiprocessSupport:
+        modifiedArguments.append("--multiprocess")
+    modifiedArguments.append("--")
+    # end the arguments for DebugClient
+    modifiedArguments.extend(arguments)
+    
+    return modifiedArguments
+
 #
 # eflag: noqa = M702
--- a/eric6/DebugClients/Python/QProcessExtension.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/DebugClients/Python/QProcessExtension.py	Fri Feb 14 19:52:37 2020 +0100
@@ -10,28 +10,9 @@
 
 import os
 
-_debugClient = None
-
+from DebugUtilities import isPythonProgram, patchArguments
 
-def _isPythonProgram(program, arguments):
-    """
-    Protected function to check, if program is a Python interpreter and
-    arguments don't include '-m'.
-    
-    @param program program to be executed
-    @type str
-    @param arguments list of command line arguments
-    @type list of str
-    @return flag indicating a python program and a tuple containing the
-        interpreter to be used and the arguments
-    @rtype tuple of (bool, tuple of (str, list of str))
-    """
-    prog = program.lower()
-    ok = (
-        ("python" in prog and arguments[0] != '-m') or
-        "pypy" in prog
-    )
-    return ok, (program, arguments[:])
+_debugClient = None
 
 
 def patchQProcess(module, debugClient):
@@ -45,6 +26,8 @@
     """     # __IGNORE_WARNING_D234__
     global _debugClient
     
+    # TODO: implement a process tracer
+    # i.e. report which processes are started
     class QProcessWrapper(module.QProcess):
         """
         Wrapper class for *.QProcess.
@@ -57,44 +40,6 @@
             """
             super(QProcessWrapper, self).__init__(parent)
         
-        @classmethod
-        def modifyArgs(cls, arguments, multiprocessSupport):
-            """
-            Private method to modify the arguments given to the start method.
-            
-            @param arguments list of program arguments
-            @type list of str
-            @return modified argument list
-            @rtype list of str
-            """
-            (wd, host, port, exceptions, tracePython, redirect,
-             noencoding) = _debugClient.startOptions[:7]
-            
-            modifiedArguments = [
-                os.path.join(os.path.dirname(__file__), "DebugClient.py"),
-                "-h", host,
-                "-p", str(port),
-                "--no-passive",
-            ]
-            
-            if wd:
-                modifiedArguments.extend(["-w", wd])
-            if not exceptions:
-                modifiedArguments.append("-e")
-            if tracePython:
-                modifiedArguments.append("-t")
-            if not redirect:
-                modifiedArguments.append("-n")
-            if noencoding:
-                modifiedArguments.append("--no-encoding")
-            if multiprocessSupport:
-                modifiedArguments.append("--multiprocess")
-            modifiedArguments.append("--")
-            # end the arguments for DebugClient
-            modifiedArguments.extend(arguments)
-            
-            return modifiedArguments
-        
         ###################################################################
         ## Handling of 'start(...)' below
         ###################################################################
@@ -133,14 +78,14 @@
                         mode = args[0]
                     else:
                         mode = module.QIODevice.ReadWrite
-                ok, (program, arguments) = _isPythonProgram(program, arguments)
+                ok, (program, arguments) = isPythonProgram(program, arguments)
                 if (
                     ok and (
                         not os.path.basename(arguments[0])
                         in _debugClient.noDebugList
                     )
                 ):
-                    newArgs = self.modifyArgs(
+                    newArgs = patchArguments(
                         arguments, _debugClient.multiprocessSupport)
                     super(QProcessWrapper, self).start(program, newArgs, mode)
                 else:
@@ -197,7 +142,7 @@
                 arguments = self.arguments()
                 wd = self.workingDirectory()
                 
-                ok, (program, arguments) = _isPythonProgram(program, arguments)
+                ok, (program, arguments) = isPythonProgram(program, arguments)
                 if ok:
                     return QProcessWrapper.startDetachedStatic(
                         program, arguments, wd)
@@ -235,9 +180,9 @@
                     wd = args[2]
                 else:
                     wd = ""
-                ok, (program, arguments) = _isPythonProgram(program, arguments)
+                ok, (program, arguments) = isPythonProgram(program, arguments)
                 if ok:
-                    newArgs = QProcessWrapper.modifyArgs(
+                    newArgs = patchArguments(
                         arguments, _debugClient.multiprocessSupport)
                     return QProcessWrapper._origQProcessStartDetached(
                         program, newArgs, wd)
--- a/eric6/DebugClients/Python/ThreadExtension.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/DebugClients/Python/ThreadExtension.py	Fri Feb 14 19:52:37 2020 +0100
@@ -407,6 +407,8 @@
                 super(QThreadWrapper, self).__init__(*args, **kwargs)
         
         module.QThread = QThreadWrapper
+    
+    # TODO: add support for QRunnable
 
 #
 # eflag: noqa = M702
--- a/eric6/Debugger/DebugServer.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/Debugger/DebugServer.py	Fri Feb 14 19:52:37 2020 +0100
@@ -82,7 +82,7 @@
         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
+    @signal clientBanner(version, platform, venvname) emitted after
         the client banner data was received
     @signal clientCapabilities(capabilities, cltype, venvname) emitted after
         the clients capabilities were received
@@ -119,8 +119,8 @@
         toFunction, debuggerId)
     @signal appendStdout(msg) emitted when a passive debug connection is
         established or lost
-    @signal clientDebuggerIds(debuggerIds) emitted to give the list of IDs of
-        attached debugger backends
+    @signal clientDebuggerId(debuggerId) emitted to indicate a newly connected
+        debugger backend
     """
     clientClearBreak = pyqtSignal(str, int, str)
     clientClearWatch = pyqtSignal(str, str)
@@ -144,11 +144,11 @@
     clientBreakConditionError = pyqtSignal(str, int, str)
     clientWatchConditionError = pyqtSignal(str, str)
     clientRawInput = pyqtSignal(str, bool, str)
-    clientBanner = pyqtSignal(str, str, str, str)
+    clientBanner = pyqtSignal(str, str, str)
     clientCapabilities = pyqtSignal(int, str, str)
     clientCompletionList = pyqtSignal(list, str, str)
     clientInterpreterChanged = pyqtSignal(str)
-    clientDebuggerIds = pyqtSignal(list)
+    clientDebuggerId = pyqtSignal(str)
     utDiscovered = pyqtSignal(list, str, str)
     utPrepared = pyqtSignal(int, str, str)
     utStartTest = pyqtSignal(str, str)
@@ -1883,7 +1883,7 @@
         """
         self.clientRawInput.emit(prompt, echo, debuggerId)
     
-    def signalClientBanner(self, version, platform, debugClient, venvName):
+    def signalClientBanner(self, version, platform, venvName):
         """
         Public method to process the client banner info.
         
@@ -1891,12 +1891,10 @@
         @type str
         @param platform hostname of the client
         @type str
-        @param debugClient additional debugger type info
-        @type str
         @param venvName name of the virtual environment
         @type str
         """
-        self.clientBanner.emit(version, platform, debugClient, venvName)
+        self.clientBanner.emit(version, platform, venvName)
     
     def signalClientCapabilities(self, capabilities, clientType, venvName):
         """
@@ -2172,16 +2170,16 @@
         """
         self.debugging = on
     
-    def signalClientDebuggerIds(self, debuggerIds):
+    def signalClientDebuggerId(self, debuggerId):
         """
         Public method to signal the receipt of a new debugger ID.
         
         This signal indicates, that a new debugger backend has connected.
         
-        @param debuggerIds list of IDs of the connected debugger backends
-        @type list of str
+        @param debuggerId ID of the newly connected debugger backend
+        @type str
         """
-        self.clientDebuggerIds.emit(debuggerIds)
+        self.clientDebuggerId.emit(debuggerId)
     
     def getDebuggerIds(self):
         """
--- a/eric6/Debugger/DebugViewer.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/Debugger/DebugViewer.py	Fri Feb 14 19:52:37 2020 +0100
@@ -272,8 +272,8 @@
             self.handleClientStack)
         self.debugServer.clientThreadList.connect(
             self.showThreadList)
-        self.debugServer.clientDebuggerIds.connect(
-            self.showDebuggersList)
+        self.debugServer.clientDebuggerId.connect(
+            self.__clientDebuggerId)
         self.debugServer.passiveDebugStarted.connect(
             self.handleDebuggingStarted)
         self.debugServer.clientLine.connect(
@@ -648,7 +648,7 @@
         else:
             icon = "exceptions"
             state = "exception"
-        self.__setDebuggerIconAndState("", icon, state)
+        self.__setDebuggerIconAndState(debuggerId, icon, state)
     
     def __threadSelected(self, current, previous):
         """
@@ -692,24 +692,14 @@
                 self.getSelectedDebuggerState() != "running")
             self.__showSource()
     
-    def showDebuggersList(self, debuggerIds):
+    def __clientDebuggerId(self, debuggerId):
         """
-        Public slot to receive the list of debugger backend IDs.
-        
-        @param debuggerIds list of debugger backend IDs
-        @type list of str
-        """
-        block = self.__debuggersCombo.blockSignals(True)
+        Private slot to receive the ID of a newly connected debugger backend.
         
-        currentDebuggerId = self.__debuggersCombo.currentText()
-        self.__debuggersCombo.clear()
-        self.__debuggersCombo.addItems(debuggerIds)
-        if currentDebuggerId:
-            self.__debuggersCombo.setCurrentText(currentDebuggerId)
-        else:
-            self.__debuggersCombo.setCurrentIndex(0)
-        
-        self.__debuggersCombo.blockSignals(block)
+        @param debuggerId ID of a newly connected debugger backend
+        @type str
+        """
+        self.__debuggersCombo.addItem(debuggerId)
     
     def getSelectedDebuggerId(self):
         """
--- a/eric6/Debugger/DebuggerInterfaceNone.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/Debugger/DebuggerInterfaceNone.py	Fri Feb 14 19:52:37 2020 +0100
@@ -16,6 +16,7 @@
 ClientTypeAssociations = []
 
 
+# TODO: synchronize debugger interface with Python one
 class DebuggerInterfaceNone(QObject):
     """
     Class implementing a dummy debugger interface for the debug server.
--- a/eric6/Debugger/DebuggerInterfacePython.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/Debugger/DebuggerInterfacePython.py	Fri Feb 14 19:52:37 2020 +0100
@@ -539,8 +539,7 @@
                 # Get the remote clients capabilities
                 self.remoteCapabilities(debuggerId)
             
-            self.debugServer.signalClientDebuggerIds(
-                sorted(self.__connections.keys()))
+            self.debugServer.signalClientDebuggerId(debuggerId)
             
             if debuggerId == self.__master:
                 self.__flush()
@@ -1426,7 +1425,6 @@
                 self.debugServer.signalClientBanner(
                     params["version"],
                     params["platform"],
-                    params["dbgclient"],
                     self.__startedVenv,
                 )
         
--- a/eric6/QScintilla/Shell.py	Thu Feb 13 19:27:10 2020 +0100
+++ b/eric6/QScintilla/Shell.py	Fri Feb 14 19:52:37 2020 +0100
@@ -822,7 +822,7 @@
         else:
             self.dbs.remoteBanner()
         
-    def __writeBanner(self, version, platform, dbgclient, venvName):
+    def __writeBanner(self, version, platform, venvName):
         """
         Private method to write a banner with info from the debug client.
         
@@ -830,8 +830,6 @@
         @type str
         @param platform platform of the remote interpreter
         @type str
-        @param dbgclient debug client variant used
-        @type str
         @param venvName name of the virtual environment
         @type str
         """
@@ -842,10 +840,8 @@
         else:
             self.__currentVenv = venvName
             version = version.replace("#", self.tr("No."))
-            if platform != "" and dbgclient != "":
-                self.__write(
-                    self.tr('{0} on {1}, {2}')
-                        .format(version, platform, dbgclient))
+            if platform != "":
+                self.__write(self.tr('{0} on {1}').format(version, platform))
             else:
                 self.__write(version)
             if venvName:

eric ide

mercurial