Continued with the multiprocess debugger. multi_processing

Sat, 15 Feb 2020 20:00:22 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 15 Feb 2020 20:00:22 +0100
branch
multi_processing
changeset 7419
9c1163735448
parent 7418
6214fa980a9d
child 7420
0d596bb4a60d

Continued with the multiprocess debugger.

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
--- a/eric6/DebugClients/Python/DebugClientBase.py	Sat Feb 15 16:30:08 2020 +0100
+++ b/eric6/DebugClients/Python/DebugClientBase.py	Sat Feb 15 20:00:22 2020 +0100
@@ -2117,6 +2117,8 @@
         @param multiprocessSupport flag indicating to enable multiprocess
             debugging support
         @type bool
+        @return exit code of the debugged program
+        @rtype int
         """
         if host is None:
             host = os.getenv('ERICHOST', 'localhost')
@@ -2160,9 +2162,10 @@
         code = self.__compileFileSource(self.running)
         if code:
             res = self.mainThread.run(code, self.debugMod.__dict__, debug=True)
-            self.progTerminated(res)
         else:
-            self.progTerminated(42)     # should not happen
+            res = 42        # should not happen
+        self.progTerminated(res)
+        return res
 
     def run_call(self, scriptname, func, *args):
         """
@@ -2278,12 +2281,12 @@
                 )
                 if not self.noencoding:
                     self.__coding = self.defaultCoding
-                self.startProgInDebugger(args, wd, host, port,
-                                         exceptions=exceptions,
-                                         tracePython=tracePython,
-                                         redirect=redirect,
-                                         passive=passive,
-                                         multiprocessSupport=multiprocess)
+                res = self.startProgInDebugger(
+                    args, wd, host, port, exceptions=exceptions,
+                    tracePython=tracePython, redirect=redirect,
+                    passive=passive, multiprocessSupport=multiprocess
+                )
+                sys.exit(res)
         else:
             if sys.argv[1] == '--no-encoding':
                 self.noencoding = True
--- a/eric6/DebugClients/Python/DebugUtilities.py	Sat Feb 15 16:30:08 2020 +0100
+++ b/eric6/DebugClients/Python/DebugUtilities.py	Sat Feb 15 20:00:22 2020 +0100
@@ -9,6 +9,8 @@
 
 import json
 import os
+import traceback
+import sys
 
 #
 # Taken from inspect.py of Python 3.4
@@ -146,30 +148,84 @@
     }
     return json.dumps(commandDict) + '\n'
 
+###########################################################################
+## Things related to monkey patching below
+###########################################################################
 
-def isPythonProgram(program, arguments):
+
+PYTHON_NAMES = ["python", "pypy"]
+
+
+def isWindowsPlatform():
     """
-    Function to check, if program is a Python interpreter and
-    arguments don't include '-m'.
+    Function to check, if this is a Windows platform.
     
-    @param program program to be executed
+    @return flag indicating Windows platform
+    @rtype bool
+    """
+    return sys.platform.startswith(("win", "cygwin"))
+
+
+def isExecutable(program):
+    """
+    Function to check, if the given program is executable.
+    
+    @param program program path to be checked
     @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))
+    @return flag indicating an executable program
+    @rtype bool
     """
-    prog = program.lower()
-    ok = (
-        ("python" in prog and arguments[0] != '-m') or
-        "pypy" in prog
-    )
-    return ok, (program, arguments[:])
+    return os.access(os.path.abspath(program), os.X_OK)
 
 
-def patchArguments(debugClient, arguments, multiprocessSupport,
-                   noRedirect=False):
+def startsWithShebang(program):
+    """
+    Function to check, if the given program start with a Shebang line.
+    
+    @param program program path to be checked
+    @type str
+    @return flag indicating an existing and valid shebang line
+    @rtype bool
+    """
+    try:
+        with open(program) as f:
+            for line in f:
+                line = line.strip()
+                if line:
+                    for name in PYTHON_NAMES:
+                        if line.startswith('#!/usr/bin/env {0}'.format(name)):
+                            return True
+                    return False
+    except UnicodeDecodeError:
+        return False
+    except Exception:
+        traceback.print_exc()
+        return False
+
+
+def isPythonProgram(program):
+    """
+    Function to check, if the given program is a Python interpreter or
+    program.
+    
+    @param program program to be checked
+    @type str
+    @return flag indicating a Python interpreter or program
+    @rtype bool
+    """
+    prog = os.path.basename(program).lower()
+    for pyname in PYTHON_NAMES:
+        if pyname in prog:
+            return True
+    
+    return (
+        not isWindowsPlatform() and
+        isExecutable(program) and
+        startsWithShebang(program)
+    )
+
+
+def patchArguments(debugClient, arguments, noRedirect=False):
     """
     Function to patch the arguments given to start a program in order to
     execute it in our debugger.
@@ -178,17 +234,17 @@
     @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
     """
+    # TODO: support #! line
     (wd, host, port, exceptions, tracePython, redirect, noencoding
      ) = debugClient.startOptions[:7]
     
     modifiedArguments = [
+        arguments[0],           # interpreter (should be modified if #! line
         os.path.join(os.path.dirname(__file__), "DebugClient.py"),
         "-h", host,
         "-p", str(port),
@@ -205,11 +261,13 @@
         modifiedArguments.append("-n")
     if noencoding:
         modifiedArguments.append("--no-encoding")
-    if multiprocessSupport:
+    if debugClient.multiprocessSupport:
         modifiedArguments.append("--multiprocess")
     modifiedArguments.append("--")
     # end the arguments for DebugClient
-    modifiedArguments.extend(arguments)
+    
+    # append the arguments for the program to be debugged
+    modifiedArguments.extend(arguments[1:])
     
     return modifiedArguments
 
--- a/eric6/DebugClients/Python/QProcessExtension.py	Sat Feb 15 16:30:08 2020 +0100
+++ b/eric6/DebugClients/Python/QProcessExtension.py	Sat Feb 15 20:00:22 2020 +0100
@@ -78,7 +78,7 @@
                         mode = args[0]
                     else:
                         mode = module.QIODevice.ReadWrite
-                ok, (program, arguments) = isPythonProgram(program, arguments)
+                ok = isPythonProgram(program)
                 if (
                     ok and (
                         not os.path.basename(arguments[0])
@@ -86,12 +86,14 @@
                     )
                 ):
                     newArgs = patchArguments(
-                        arguments, _debugClient.multiprocessSupport)
-                    super(QProcessWrapper, self).start(program, newArgs, mode)
-                else:
-                    super(QProcessWrapper, self).start(*args, **kwargs)
-            else:
-                super(QProcessWrapper, self).start(*args, **kwargs)
+                        _debugClient,
+                        [program] + arguments,
+                    )
+                    super(QProcessWrapper, self).start(
+                        newArgs[0], newArgs[1:], mode)
+                    return
+            
+            super(QProcessWrapper, self).start(*args, **kwargs)
         
         ###################################################################
         ## Handling of 'startDetached(...)' below
@@ -142,16 +144,12 @@
                 arguments = self.arguments()
                 wd = self.workingDirectory()
                 
-                ok, (program, arguments) = isPythonProgram(program, arguments)
+                ok = isPythonProgram(program)
                 if ok:
                     return QProcessWrapper.startDetachedStatic(
                         program, arguments, wd)
-                else:
-                    return super(QProcessWrapper, self).startDetached(
-                        *args, **kwargs)
-            else:
-                return super(QProcessWrapper, self).startDetached(
-                    *args, **kwargs)
+            
+            return super(QProcessWrapper, self).startDetached(*args, **kwargs)
         
         @staticmethod
         def startDetachedStatic(*args, **kwargs):
@@ -180,18 +178,17 @@
                     wd = args[2]
                 else:
                     wd = ""
-                ok, (program, arguments) = isPythonProgram(program, arguments)
+                ok = isPythonProgram(program)
                 if ok:
                     newArgs = patchArguments(
-                        arguments, _debugClient.multiprocessSupport)
-                    return QProcessWrapper._origQProcessStartDetached(
-                        program, newArgs, wd)
-                else:
+                        _debugClient,
+                        [program] + arguments,
+                    )
                     return QProcessWrapper._origQProcessStartDetached(
-                        *args, **kwargs)
-            else:
-                return QProcessWrapper._origQProcessStartDetached(
-                    *args, **kwargs)
+                        newArgs[0], newArgs[1:], wd)
+            
+            return QProcessWrapper._origQProcessStartDetached(
+                *args, **kwargs)
     
     _debugClient = debugClient
     module.QProcess = QProcessWrapper
--- a/eric6/DebugClients/Python/ThreadExtension.py	Sat Feb 15 16:30:08 2020 +0100
+++ b/eric6/DebugClients/Python/ThreadExtension.py	Sat Feb 15 20:00:22 2020 +0100
@@ -422,9 +422,6 @@
         
         module.QThread = QThreadWrapper
         module.QRunnable = QRunnableWrapper
-        
-        self.enableImportHooks = True
-        return module
 
 #
 # eflag: noqa = M702

eric ide

mercurial