294 except Exception: |
302 except Exception: |
295 excinfo = sys.exc_info() |
303 excinfo = sys.exc_info() |
296 newThread.user_exception(excinfo, True) |
304 newThread.user_exception(excinfo, True) |
297 |
305 |
298 class ThreadWrapper(module.Thread): |
306 class ThreadWrapper(module.Thread): |
|
307 """ Wrapper class for threading.Thread. """ |
299 |
308 |
300 def __init__(self, *args, **kwargs): |
309 def __init__(self, *args, **kwargs): |
301 # Overwrite the provided run method with our own, to |
310 # Overwrite the provided run method with our own, to |
302 # intercept the thread creation by threading.Thread |
311 # intercept the thread creation by threading.Thread |
303 self.run = lambda s=self, run=self.run: _bootstrap(s, run) |
312 self.run = lambda s=self, run=self.run: _bootstrap(s, run) |
304 |
313 |
305 super(ThreadWrapper, self).__init__(*args, **kwargs) |
314 super(ThreadWrapper, self).__init__(*args, **kwargs) |
306 |
315 |
307 module.Thread = ThreadWrapper |
316 module.Thread = ThreadWrapper |
308 |
317 |
|
318 # Add hook for *.QThread |
309 elif (fullname in ['PyQt4.QtCore', 'PyQt5.QtCore', |
319 elif (fullname in ['PyQt4.QtCore', 'PyQt5.QtCore', |
310 'PySide.QtCore', 'PySide2.QtCore'] and |
320 'PySide.QtCore', 'PySide2.QtCore'] and |
311 self._qtThread is None): |
321 self.qtThreadAttached is False): |
312 self._qtThread = module.QThread |
322 self.qtThreadAttached = True |
313 # _debugClient as a class attribute can't be accessed in following |
323 # _debugClient as a class attribute can't be accessed in following |
314 # class. Therefore we need a global variable. |
324 # class. Therefore we need a global variable. |
315 _debugClient = self |
325 _debugClient = self |
316 |
326 |
|
327 def _bootstrapQThread(self, run): |
|
328 """ |
|
329 Bootstrap for QThread, which reports exceptions correctly. |
|
330 |
|
331 @param run the run method of *.QThread |
|
332 @type method pointer |
|
333 """ |
|
334 global _qtThreadNumber |
|
335 |
|
336 newThread = DebugBase(_debugClient) |
|
337 ident = _thread.get_ident() |
|
338 name = 'QtThread-{0}'.format(_qtThreadNumber) |
|
339 |
|
340 _qtThreadNumber += 1 |
|
341 |
|
342 newThread.id = ident |
|
343 newThread.name = name |
|
344 |
|
345 _debugClient.threads[ident] = newThread |
|
346 |
|
347 # see DebugBase.bootstrap |
|
348 sys.settrace(newThread.trace_dispatch) |
|
349 try: |
|
350 run() |
|
351 except SystemExit: |
|
352 # *.QThreads doesn't like SystemExit |
|
353 pass |
|
354 except Exception: |
|
355 excinfo = sys.exc_info() |
|
356 newThread.user_exception(excinfo, True) |
|
357 |
317 class QThreadWrapper(module.QThread): |
358 class QThreadWrapper(module.QThread): |
318 __qtThreadNumber = 1 |
359 """ Wrapper class for *.QThread. """ |
319 |
360 |
320 def __init__(self, *args, **kwargs): |
361 def __init__(self, *args, **kwargs): |
321 # Overwrite the provided run method with our own, to |
362 # Overwrite the provided run method with our own, to |
322 # intercept the thread creation by Qt |
363 # intercept the thread creation by Qt |
323 self._ApplicationRun = self.run |
364 self.run = lambda s=self, run=self.run: ( |
324 self.run = self.__bootstrapQThread |
365 _bootstrapQThread(s, run)) |
325 |
366 |
326 super(QThreadWrapper, self).__init__(*args, **kwargs) |
367 super(QThreadWrapper, self).__init__(*args, **kwargs) |
327 |
|
328 def __bootstrapQThread(self): |
|
329 newThread = DebugBase(_debugClient) |
|
330 ident = _thread.get_ident() |
|
331 name = 'QtThread-{0}'.format(self.__qtThreadNumber) |
|
332 self.__qtThreadNumber += 1 |
|
333 |
|
334 newThread.id = ident |
|
335 newThread.name = name |
|
336 |
|
337 _debugClient.threads[ident] = newThread |
|
338 |
|
339 frame = sys._getframe() |
|
340 newThread.botframe = frame |
|
341 frame.f_trace = newThread.trace_dispatch |
|
342 # see DebugBase.bootstrap |
|
343 sys.settrace( |
|
344 lambda frame, event, arg: newThread.trace_dispatch) |
|
345 |
|
346 return self._ApplicationRun() |
|
347 |
368 |
348 module.QThread = QThreadWrapper |
369 module.QThread = QThreadWrapper |
349 |
370 |
350 self.enableImportHooks = True |
371 self.enableImportHooks = True |
351 return module |
372 return module |
352 |
373 |
353 |
|
354 # |
374 # |
355 # eflag: noqa = M702 |
375 # eflag: noqa = M702 |