--- a/src/eric7/Debugger/DebuggerInterfacePython.py Tue Oct 31 09:23:05 2023 +0100 +++ b/src/eric7/Debugger/DebuggerInterfacePython.py Wed Nov 29 14:23:36 2023 +0100 @@ -202,8 +202,6 @@ self.__inShutdown = False - debugClient = self.__determineDebugClient() - redirect = ( str(configOverride["redirect"]) if configOverride and configOverride["enable"] @@ -215,23 +213,35 @@ multiprocessEnabled = ( "--multiprocess" if Preferences.getDebugger("MultiProcessEnabled") else "" ) + callTraceOptimization = ( + "--call-trace-optimization" + if Preferences.getDebugger("PythonCallTraceOptimization") + else "" + ) if Preferences.getDebugger("RemoteDbgEnabled"): + # remote debugging code ipaddr = self.debugServer.getHostAddress(False) rexec = Preferences.getDebugger("RemoteExecution") rhost = Preferences.getDebugger("RemoteHost") if rhost == "": rhost = "localhost" if rexec: + rdebugClient = Preferences.getDebugger("RemoteDebugClient") + if not rdebugClient and rhost == "localhost": + # it is a remote debugging session on the same host + rdebugClient = self.__determineDebugClient() args = Utilities.parseOptionString(rexec) + [ rhost, interpreter, - debugClient, + rdebugClient, ] if noencoding: args.append(noencoding) if multiprocessEnabled: args.append(multiprocessEnabled) + if callTraceOptimization: + args.append(callTraceOptimization) args.extend([str(port), redirect, ipaddr]) if OSUtilities.isWindowsPlatform(): if not os.path.splitext(args[0])[1]: @@ -267,76 +277,94 @@ else: self.translate = self.__identityTranslation return process, self.__isNetworked, "" - - # set translation function - self.translate = self.__identityTranslation + else: + EricMessageBox.critical( + None, + self.tr("Start Debugger"), + self.tr( + "<p>Remote debugging is configured but no command for remote" + " login was given.</p>" + ), + ) + return None, False, "" - # setup the environment for the debugger - if Preferences.getDebugger("DebugEnvironmentReplace"): - clientEnv = {} else: - clientEnv = os.environ.copy() - if originalPathString: - clientEnv["PATH"] = originalPathString - envlist = shlex.split(Preferences.getDebugger("DebugEnvironment")) - for el in envlist: - with contextlib.suppress(ValueError): - key, value = el.split("=", 1) - clientEnv[str(key)] = str(value) - if execPath: - if "PATH" in clientEnv: - clientEnv["PATH"] = os.pathsep.join([execPath, clientEnv["PATH"]]) + # local debugging code below + debugClient = self.__determineDebugClient() + + # set translation function + self.translate = self.__identityTranslation + + # setup the environment for the debugger + if Preferences.getDebugger("DebugEnvironmentReplace"): + clientEnv = {} else: - clientEnv["PATH"] = execPath + clientEnv = os.environ.copy() + if originalPathString: + clientEnv["PATH"] = originalPathString + envlist = shlex.split(Preferences.getDebugger("DebugEnvironment")) + for el in envlist: + with contextlib.suppress(ValueError): + key, value = el.split("=", 1) + clientEnv[str(key)] = str(value) + if execPath: + if "PATH" in clientEnv: + clientEnv["PATH"] = os.pathsep.join([execPath, clientEnv["PATH"]]) + else: + clientEnv["PATH"] = execPath - ipaddr = self.debugServer.getHostAddress(True) - if runInConsole or Preferences.getDebugger("ConsoleDbgEnabled"): - ccmd = Preferences.getDebugger("ConsoleDbgCommand") - if ccmd: - args = Utilities.parseOptionString(ccmd) + [ - interpreter, - os.path.abspath(debugClient), - ] - if noencoding: - args.append(noencoding) - if multiprocessEnabled: - args.append(multiprocessEnabled) - args.extend([str(port), "0", ipaddr]) - args[0] = FileSystemUtilities.getExecutablePath(args[0]) - process = self.__startProcess( - args[0], args[1:], clientEnv, workingDir=workingDir + ipaddr = self.debugServer.getHostAddress(True) + if runInConsole or Preferences.getDebugger("ConsoleDbgEnabled"): + ccmd = Preferences.getDebugger("ConsoleDbgCommand") + if ccmd: + args = Utilities.parseOptionString(ccmd) + [ + interpreter, + os.path.abspath(debugClient), + ] + if noencoding: + args.append(noencoding) + if multiprocessEnabled: + args.append(multiprocessEnabled) + if callTraceOptimization: + args.append(callTraceOptimization) + args.extend([str(port), "0", ipaddr]) + args[0] = FileSystemUtilities.getExecutablePath(args[0]) + process = self.__startProcess( + args[0], args[1:], clientEnv, workingDir=workingDir + ) + if process is None: + EricMessageBox.critical( + None, + self.tr("Start Debugger"), + self.tr( + """<p>The debugger backend could not be""" + """ started.</p>""" + ), + ) + return process, self.__isNetworked, interpreter + + args = [debugClient] + if noencoding: + args.append(noencoding) + if multiprocessEnabled: + args.append(multiprocessEnabled) + if callTraceOptimization: + args.append(callTraceOptimization) + args.extend([str(port), redirect, ipaddr]) + process = self.__startProcess( + interpreter, args, clientEnv, workingDir=workingDir + ) + if process is None: + self.__startedVenv = "" + EricMessageBox.critical( + None, + self.tr("Start Debugger"), + self.tr("""<p>The debugger backend could not be started.</p>"""), ) - if process is None: - EricMessageBox.critical( - None, - self.tr("Start Debugger"), - self.tr( - """<p>The debugger backend could not be""" - """ started.</p>""" - ), - ) - return process, self.__isNetworked, interpreter + else: + self.__startedVenv = venvName - args = [debugClient] - if noencoding: - args.append(noencoding) - if multiprocessEnabled: - args.append(multiprocessEnabled) - args.extend([str(port), redirect, ipaddr]) - process = self.__startProcess( - interpreter, args, clientEnv, workingDir=workingDir - ) - if process is None: - self.__startedVenv = "" - EricMessageBox.critical( - None, - self.tr("Start Debugger"), - self.tr("""<p>The debugger backend could not be started.</p>"""), - ) - else: - self.__startedVenv = venvName - - return process, self.__isNetworked, interpreter + return process, self.__isNetworked, interpreter def __determineDebugClient(self): """ @@ -397,10 +425,6 @@ return None, self.__isNetworked, "" # start debugger with project specific settings - debugClient = project.getDebugProperty("DEBUGCLIENT") - if not bool(debugClient) or not os.path.exists(debugClient): - debugClient = self.__determineDebugClient() - redirect = ( str(configOverride["redirect"]) if configOverride and configOverride["enable"] @@ -410,6 +434,11 @@ multiprocessEnabled = ( "--multiprocess" if Preferences.getDebugger("MultiProcessEnabled") else "" ) + callTraceOptimization = ( + "--call-trace-optimization" + if Preferences.getDebugger("PythonCallTraceOptimization") + else "" + ) if venvName and venvName != self.debugServer.getProjectEnvironmentString(): venvManager = ericApp().getObject("VirtualEnvManager") @@ -430,21 +459,28 @@ self.__inShutdown = False if project.getDebugProperty("REMOTEDEBUGGER"): + # remote debugging code ipaddr = self.debugServer.getHostAddress(False) rexec = project.getDebugProperty("REMOTECOMMAND") rhost = project.getDebugProperty("REMOTEHOST") if rhost == "": rhost = "localhost" if rexec: + rdebugClient = project.getDebugProperty("REMOTEDEBUGCLIENT") + if not rdebugClient and rhost == "localhost": + # it is a remote debugging session on the same host + rdebugClient = self.__determineDebugClient() args = Utilities.parseOptionString(rexec) + [ rhost, interpreter, - debugClient, + rdebugClient, ] if noencoding: args.append(noencoding) if multiprocessEnabled: args.append(multiprocessEnabled) + if callTraceOptimization: + args.append(callTraceOptimization) args.extend([str(port), redirect, ipaddr]) if OSUtilities.isWindowsPlatform(): if not os.path.splitext(args[0])[1]: @@ -479,77 +515,87 @@ # remote shell command is missing return None, self.__isNetworked, "" - # set translation function - self.translate = self.__identityTranslation + else: + # local debugging code below + debugClient = project.getDebugProperty("DEBUGCLIENT") + if not bool(debugClient) or not os.path.exists(debugClient): + debugClient = self.__determineDebugClient() + + # set translation function + self.translate = self.__identityTranslation - # setup the environment for the debugger - if project.getDebugProperty("ENVIRONMENTOVERRIDE"): - clientEnv = {} - else: - clientEnv = os.environ.copy() - if originalPathString: - clientEnv["PATH"] = originalPathString - envlist = shlex.split(project.getDebugProperty("ENVIRONMENTSTRING")) - for el in envlist: - with contextlib.suppress(ValueError): - key, value = el.split("=", 1) - clientEnv[str(key)] = str(value) - if execPath: - if "PATH" in clientEnv: - clientEnv["PATH"] = os.pathsep.join([execPath, clientEnv["PATH"]]) + # setup the environment for the debugger + if project.getDebugProperty("ENVIRONMENTOVERRIDE"): + clientEnv = {} else: - clientEnv["PATH"] = execPath + clientEnv = os.environ.copy() + if originalPathString: + clientEnv["PATH"] = originalPathString + envlist = shlex.split(project.getDebugProperty("ENVIRONMENTSTRING")) + for el in envlist: + with contextlib.suppress(ValueError): + key, value = el.split("=", 1) + clientEnv[str(key)] = str(value) + if execPath: + if "PATH" in clientEnv: + clientEnv["PATH"] = os.pathsep.join([execPath, clientEnv["PATH"]]) + else: + clientEnv["PATH"] = execPath - ipaddr = self.debugServer.getHostAddress(True) - if runInConsole or project.getDebugProperty("CONSOLEDEBUGGER"): - ccmd = project.getDebugProperty( - "CONSOLECOMMAND" - ) or Preferences.getDebugger("ConsoleDbgCommand") - if ccmd: - args = Utilities.parseOptionString(ccmd) + [ - interpreter, - os.path.abspath(debugClient), - ] - if noencoding: - args.append(noencoding) - if multiprocessEnabled: - args.append(multiprocessEnabled) - args.extend([str(port), "0", ipaddr]) - args[0] = FileSystemUtilities.getExecutablePath(args[0]) - process = self.__startProcess( - args[0], args[1:], clientEnv, workingDir=workingDir + ipaddr = self.debugServer.getHostAddress(True) + if runInConsole or project.getDebugProperty("CONSOLEDEBUGGER"): + ccmd = project.getDebugProperty( + "CONSOLECOMMAND" + ) or Preferences.getDebugger("ConsoleDbgCommand") + if ccmd: + args = Utilities.parseOptionString(ccmd) + [ + interpreter, + os.path.abspath(debugClient), + ] + if noencoding: + args.append(noencoding) + if multiprocessEnabled: + args.append(multiprocessEnabled) + if callTraceOptimization: + args.append(callTraceOptimization) + args.extend([str(port), "0", ipaddr]) + args[0] = FileSystemUtilities.getExecutablePath(args[0]) + process = self.__startProcess( + args[0], args[1:], clientEnv, workingDir=workingDir + ) + if process is None: + EricMessageBox.critical( + None, + self.tr("Start Debugger"), + self.tr( + """<p>The debugger backend could not be""" + """ started.</p>""" + ), + ) + return process, self.__isNetworked, interpreter + + args = [debugClient] + if noencoding: + args.append(noencoding) + if multiprocessEnabled: + args.append(multiprocessEnabled) + if callTraceOptimization: + args.append(callTraceOptimization) + args.extend([str(port), redirect, ipaddr]) + process = self.__startProcess( + interpreter, args, clientEnv, workingDir=workingDir + ) + if process is None: + self.__startedVenv = "" + EricMessageBox.critical( + None, + self.tr("Start Debugger"), + self.tr("""<p>The debugger backend could not be started.</p>"""), ) - if process is None: - EricMessageBox.critical( - None, - self.tr("Start Debugger"), - self.tr( - """<p>The debugger backend could not be""" - """ started.</p>""" - ), - ) - return process, self.__isNetworked, interpreter + else: + self.__startedVenv = venvName - args = [debugClient] - if noencoding: - args.append(noencoding) - if multiprocessEnabled: - args.append(multiprocessEnabled) - args.extend([str(port), redirect, ipaddr]) - process = self.__startProcess( - interpreter, args, clientEnv, workingDir=workingDir - ) - if process is None: - self.__startedVenv = "" - EricMessageBox.critical( - None, - self.tr("Start Debugger"), - self.tr("""<p>The debugger backend could not be started.</p>"""), - ) - else: - self.__startedVenv = venvName - - return process, self.__isNetworked, interpreter + return process, self.__isNetworked, interpreter def getClientCapabilities(self): """ @@ -609,7 +655,6 @@ and self.__autoContinue and not self.__isStepCommand ): - self.__autoContinued.append(debuggerId) QTimer.singleShot(0, lambda: self.remoteContinue(debuggerId)) def __socketDisconnected(self, sock): @@ -740,6 +785,7 @@ traceInterpreter=False, autoContinue=True, enableMultiprocess=False, + reportAllExceptions=False, ): """ Public method to load a new program to debug. @@ -759,6 +805,9 @@ @param enableMultiprocess flag indicating to perform multiprocess debugging @type bool + @param reportAllExceptions flag indicating to report all exceptions + instead of unhandled exceptions only + @type bool """ self.__autoContinue = autoContinue self.__scriptName = os.path.abspath(fn) @@ -774,6 +823,7 @@ "argv": Utilities.parseOptionString(argv), "traceInterpreter": traceInterpreter, "multiprocess": enableMultiprocess, + "reportAllExceptions": reportAllExceptions, }, self.__mainDebugger, ) @@ -1569,7 +1619,7 @@ elif method == "PassiveStartup": self.debugServer.passiveStartUp( self.translate(params["filename"], True), - params["exceptions"], + params["reportAllExceptions"], params["debuggerId"], )