Sun, 18 Oct 2020 12:35:30 +0200
Merged with default branch.
# -*- coding: utf-8 -*- # Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing a function to patch QProcess to support debugging of the process. """ import os from DebugUtilities import isPythonProgram, startsWithShebang, patchArguments _debugClient = None def patchQProcess(module, debugClient): """ Function to patch the QtCore module's QProcess. @param module reference to the imported module to be patched @type module @param debugClient reference to the debug client object @type DebugClient """ # __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. """ _origQProcessStartDetached = module.QProcess.startDetached def __init__(self, parent=None): """ Constructor """ super(QProcessWrapper, self).__init__(parent) ################################################################### ## Handling of 'start(...)' below ################################################################### def start(self, *args, **kwargs): """ Public method to start the process. This method patches the arguments such, that a debug client is started for the Python script. A Python script is assumed, if the program to be started contains the string 'python'. @param args arguments of the start call @type list @param kwargs keyword arguments of the start call @type dict """ if ( _debugClient.debugging and _debugClient.multiprocessSupport and ((len(args) >= 2 and isinstance(args[1], list)) or (len(args) == 1 and not isinstance(args[0], str)) or len(args) == 0) ): if len(args) >= 2: program = args[0] arguments = args[1] if len(args) > 2: mode = args[2] else: mode = module.QIODevice.ReadWrite else: program = self.program() arguments = self.arguments() if len(args) == 1: mode = args[0] else: mode = module.QIODevice.ReadWrite ok = isPythonProgram(program) if ok: if startsWithShebang(program): scriptName = os.path.basename(program) else: scriptName = os.path.basename(arguments[0]) if scriptName not in _debugClient.noDebugList: newArgs = patchArguments( _debugClient, [program] + arguments, ) super(QProcessWrapper, self).start( newArgs[0], newArgs[1:], mode) return super(QProcessWrapper, self).start(*args, **kwargs) ################################################################### ## Handling of 'startDetached(...)' below ################################################################### def startDetached(self, *args, **kwargs): """ Public method to start the detached process. This method patches the arguments such, that a debug client is started for the Python script. A Python script is assumed, if the program to be started contains the string 'python'. @param args arguments of the start call @type list @param kwargs keyword arguments of the start call @type dict @return flag indicating a successful start @rtype bool """ if isinstance(self, str): return QProcessWrapper.startDetachedStatic( self, *args) else: return self.__startDetached(*args, **kwargs) def __startDetached(self, *args, **kwargs): """ Private method to start the detached process. This method patches the arguments such, that a debug client is started for the Python script. A Python script is assumed, if the program to be started contains the string 'python'. @param args arguments of the start call @type list @param kwargs keyword arguments of the start call @type dict @return flag indicating a successful start @rtype bool """ if ( _debugClient.debugging and _debugClient.multiprocessSupport and len(args) == 0 ): program = self.program() arguments = self.arguments() wd = self.workingDirectory() ok = isPythonProgram(program) if ok: return QProcessWrapper.startDetachedStatic( program, arguments, wd) return super(QProcessWrapper, self).startDetached(*args, **kwargs) @staticmethod def startDetachedStatic(*args, **kwargs): """ Static method to start the detached process. This method patches the arguments such, that a debug client is started for the Python script. A Python script is assumed, if the program to be started contains the string 'python'. @param args arguments of the start call @type list @param kwargs keyword arguments of the start call @type dict @return flag indicating a successful start @rtype bool """ if ( _debugClient.debugging and _debugClient.multiprocessSupport and (len(args) >= 2 and isinstance(args[1], list)) ): program = args[0] arguments = args[1] if len(args) >= 3: wd = args[2] else: wd = "" ok = isPythonProgram(program) if ok: if startsWithShebang(program): scriptName = os.path.basename(program) else: scriptName = os.path.basename(arguments[0]) if scriptName not in _debugClient.noDebugList: newArgs = patchArguments( _debugClient, [program] + arguments, ) return QProcessWrapper._origQProcessStartDetached( newArgs[0], newArgs[1:], wd) return QProcessWrapper._origQProcessStartDetached( *args, **kwargs) _debugClient = debugClient module.QProcess = QProcessWrapper