32 Constructor |
32 Constructor |
33 """ |
33 """ |
34 self.threadNumber = 1 |
34 self.threadNumber = 1 |
35 self.enableImportHooks = True |
35 self.enableImportHooks = True |
36 self._original_start_new_thread = None |
36 self._original_start_new_thread = None |
|
37 self._qtThread = None |
37 |
38 |
38 self.clientLock = threading.RLock() |
39 self.clientLock = threading.RLock() |
39 |
40 |
40 # dictionary of all threads running {id: DebugBase} |
41 # dictionary of all threads running {id: DebugBase} |
41 self.threads = {_thread.get_ident(): self} |
42 self.threads = {_thread.get_ident(): self} |
248 @return module loader object |
249 @return module loader object |
249 @rtype object |
250 @rtype object |
250 """ |
251 """ |
251 if fullname in sys.modules or not self.debugging: |
252 if fullname in sys.modules or not self.debugging: |
252 return None |
253 return None |
253 if fullname == self.threadModName and self.enableImportHooks: |
254 |
|
255 if fullname in [self.threadModName, 'PyQt4.QtCore', 'PyQt5.QtCore', |
|
256 'PySide.QtCore'] and self.enableImportHooks: |
254 # Disable hook to be able to import original module |
257 # Disable hook to be able to import original module |
255 self.enableImportHooks = False |
258 self.enableImportHooks = False |
256 return self |
259 return self |
257 |
260 |
258 return None |
261 return None |
271 if (fullname == self.threadModName and |
274 if (fullname == self.threadModName and |
272 self._original_start_new_thread is None): |
275 self._original_start_new_thread is None): |
273 # make thread hooks available to system |
276 # make thread hooks available to system |
274 self._original_start_new_thread = module.start_new_thread |
277 self._original_start_new_thread = module.start_new_thread |
275 module.start_new_thread = self.attachThread |
278 module.start_new_thread = self.attachThread |
|
279 elif fullname in ['PyQt4.QtCore', 'PyQt5.QtCore', |
|
280 'PySide.QtCore'] and self._qtThread is None: |
|
281 self._qtThread = module.QtCore.QThread |
|
282 # _debugClient as a class attribute can't be accessed in following |
|
283 # class. Therefore we need a global variable. |
|
284 _debugClient = self |
|
285 |
|
286 class QThreadWrapper(module.QtCore.QThread): |
|
287 __qtThreadNumber = 1 |
|
288 |
|
289 def __init__(self, *args, **kwargs): |
|
290 # Overwrite the provided run method with our own, to |
|
291 # intercept the thread creation by Qt |
|
292 self._ApplicationRun = self.run |
|
293 self.run = self.__bootstrapQThread |
|
294 |
|
295 super(QThreadWrapper, self).__init__(*args, **kwargs) |
|
296 |
|
297 def __bootstrapQThread(self): |
|
298 newThread = DebugBase(_debugClient) |
|
299 ident = _thread.get_ident() |
|
300 name = 'QtThread-{0}'.format(self.__qtThreadNumber) |
|
301 self.__qtThreadNumber += 1 |
|
302 |
|
303 newThread.id = ident |
|
304 newThread.name = name |
|
305 |
|
306 _debugClient.threads[ident] = newThread |
|
307 |
|
308 frame = sys._getframe() |
|
309 newThread.botframe = frame |
|
310 frame.f_trace = newThread.trace_dispatch |
|
311 # see DebugBase.bootstrap |
|
312 sys.settrace( |
|
313 lambda frame, event, arg: newThread.trace_dispatch) |
|
314 |
|
315 return self._ApplicationRun() |
|
316 |
|
317 module.QThread = QThreadWrapper |
276 |
318 |
277 self.enableImportHooks = True |
319 self.enableImportHooks = True |
278 return module |
320 return module |
279 |
321 |
280 |
322 |