--- 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