Fri, 24 Feb 2017 18:51:36 +0100
Merged with debugger changes done by Tobias.
changelog | file | annotate | diff | comparison | revisions |
--- a/DebugClients/Python/DebugBase.py Thu Feb 23 19:15:36 2017 +0100 +++ b/DebugClients/Python/DebugBase.py Fri Feb 24 18:51:36 2017 +0100 @@ -317,7 +317,7 @@ return self.trace_dispatch else: # No need to trace this function - return + return if event == 'return': return @@ -420,8 +420,10 @@ @type str or CodeType @keyparam globals dictionary of global variables for cmd @type dict - @keyparam locals dictionary of local variables for cmd + @keyparam locals dictionary of local variables for cmd @type dict + @keyparam debug flag if command should run under debugger control + @type bool """ if globals is None: import __main__
--- a/DebugClients/Python/DebugClientBase.py Thu Feb 23 19:15:36 2017 +0100 +++ b/DebugClients/Python/DebugClientBase.py Fri Feb 24 18:51:36 2017 +0100 @@ -727,7 +727,7 @@ self.eventExit = True elif method == "RequestContinue": - self.currentThread.go(params["special"]) + self.currentThreadExec.go(params["special"]) self.eventExit = True elif method == "RawInput":
--- a/DebugClients/Python/ThreadExtension.py Thu Feb 23 19:15:36 2017 +0100 +++ b/DebugClients/Python/ThreadExtension.py Fri Feb 24 18:51:36 2017 +0100 @@ -20,6 +20,8 @@ from DebugBase import DebugBase +_qtThreadNumber = 1 + class ThreadExtension(object): """ @@ -36,7 +38,7 @@ self.enableImportHooks = True self._original_start_new_thread = None self.threadingAttached = False - self._qtThread = None + self.qtThreadAttached = False self.clientLock = threading.RLock() @@ -285,6 +287,12 @@ _debugClient = self def _bootstrap(self, run): + """ + Bootstrap for threading, which reports exceptions correctly. + + @param run the run method of threading.Thread + @type method pointer + """ newThread = _debugClient.threads[self.ident] newThread.name = self.name # see DebugBase.bootstrap @@ -296,6 +304,7 @@ newThread.user_exception(excinfo, True) class ThreadWrapper(module.Thread): + """ Wrapper class for threading.Thread. """ def __init__(self, *args, **kwargs): # Overwrite the provided run method with our own, to @@ -306,50 +315,61 @@ module.Thread = ThreadWrapper + # Add hook for *.QThread elif (fullname in ['PyQt4.QtCore', 'PyQt5.QtCore', 'PySide.QtCore', 'PySide2.QtCore'] and - self._qtThread is None): - self._qtThread = module.QThread + self.qtThreadAttached is False): + self.qtThreadAttached = True # _debugClient as a class attribute can't be accessed in following # class. Therefore we need a global variable. _debugClient = self + + def _bootstrapQThread(self, run): + """ + Bootstrap for QThread, which reports exceptions correctly. + + @param run the run method of *.QThread + @type method pointer + """ + global _qtThreadNumber + + newThread = DebugBase(_debugClient) + ident = _thread.get_ident() + name = 'QtThread-{0}'.format(_qtThreadNumber) + + _qtThreadNumber += 1 + newThread.id = ident + newThread.name = name + + _debugClient.threads[ident] = newThread + + # see DebugBase.bootstrap + sys.settrace(newThread.trace_dispatch) + try: + run() + except SystemExit: + # *.QThreads doesn't like SystemExit + pass + except Exception: + excinfo = sys.exc_info() + newThread.user_exception(excinfo, True) + class QThreadWrapper(module.QThread): - __qtThreadNumber = 1 + """ Wrapper class for *.QThread. """ def __init__(self, *args, **kwargs): # Overwrite the provided run method with our own, to # intercept the thread creation by Qt - self._ApplicationRun = self.run - self.run = self.__bootstrapQThread + self.run = lambda s=self, run=self.run: ( + _bootstrapQThread(s, run)) super(QThreadWrapper, self).__init__(*args, **kwargs) - - def __bootstrapQThread(self): - newThread = DebugBase(_debugClient) - ident = _thread.get_ident() - name = 'QtThread-{0}'.format(self.__qtThreadNumber) - self.__qtThreadNumber += 1 - - newThread.id = ident - newThread.name = name - - _debugClient.threads[ident] = newThread - - frame = sys._getframe() - newThread.botframe = frame - frame.f_trace = newThread.trace_dispatch - # see DebugBase.bootstrap - sys.settrace( - lambda frame, event, arg: newThread.trace_dispatch) - - return self._ApplicationRun() module.QThread = QThreadWrapper self.enableImportHooks = True return module - # # eflag: noqa = M702
--- a/changelog Thu Feb 23 19:15:36 2017 +0100 +++ b/changelog Fri Feb 24 18:51:36 2017 +0100 @@ -5,6 +5,10 @@ - Checkers -- upgraded pycodestyle to version 2.3.1 -- upgraded pyflakes to version 1.5.0 +- Debugger + -- catch unhandled exceptions again + -- support for PySide2 added + -- atexit handling works as specified in any condition - Mercurial Interface -- improved the log browser in several ways -- improved the status dialog