src/eric7/DebugClients/Python/ThreadExtension.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9473
3f23dbf37dbe
--- a/src/eric7/DebugClients/Python/ThreadExtension.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/DebugClients/Python/ThreadExtension.py	Wed Jul 13 14:55:47 2022 +0200
@@ -22,19 +22,20 @@
 class ThreadExtension:
     """
     Class implementing the thread support for the debugger.
-    
+
     Provides methods for intercepting thread creation, retrieving the running
     threads and their name and state.
     """
+
     def __init__(self):
         """
         Constructor
         """
         self.threadNumber = 1
         self._original_start_new_thread = None
-        
+
         self.clientLock = threading.RLock()
-        
+
         # dictionary of all threads running {id: DebugBase}
         self.threads = {_thread.get_ident(): self}
 
@@ -42,18 +43,17 @@
         self.currentThread = self
         # the thread we are at a breakpoint continuing at next command
         self.currentThreadExec = self
-        
+
         # special objects representing the main scripts thread and frame
         self.mainThread = self
 
-    def attachThread(self, target=None, args=None, kwargs=None,
-                     mainThread=False):
+    def attachThread(self, target=None, args=None, kwargs=None, mainThread=False):
         """
         Public method to setup a standard thread for DebugClient to debug.
-        
+
         If mainThread is True, then we are attaching to the already
         started mainthread of the app and the rest of the args are ignored.
-        
+
         @param target the start function of the target thread (i.e. the user
             code)
         @param args arguments to pass to target
@@ -64,33 +64,34 @@
         """
         if kwargs is None:
             kwargs = {}
-        
+
         if mainThread:
             ident = _thread.get_ident()
-            name = 'MainThread'
+            name = "MainThread"
             newThread = self.mainThread
             newThread.isMainThread = True
             if self.debugging:
                 sys.setprofile(newThread.profile)
-            
+
         else:
             newThread = DebugBase(self)
             ident = self._original_start_new_thread(
-                newThread.bootstrap, (target, args, kwargs))
-            name = 'Thread-{0}'.format(self.threadNumber)
+                newThread.bootstrap, (target, args, kwargs)
+            )
+            name = "Thread-{0}".format(self.threadNumber)
             self.threadNumber += 1
-        
+
         newThread.id = ident
         newThread.name = name
-        
+
         self.threads[ident] = newThread
 
         return ident
-    
+
     def threadTerminated(self, threadId):
         """
         Public method called when a DebugThread has exited.
-        
+
         @param threadId id of the DebugThread that has exited
         @type int
         """
@@ -100,25 +101,25 @@
                 del self.threads[threadId]
         finally:
             self.unlockClient()
-    
+
     def lockClient(self, blocking=True):
         """
         Public method to acquire the lock for this client.
-        
+
         @param blocking flag to indicating a blocking lock
         @type bool
         @return flag indicating successful locking
         @rtype bool
         """
         return self.clientLock.acquire(blocking)
-    
+
     def unlockClient(self):
         """
         Public method to release the lock for this client.
         """
         with contextlib.suppress(RuntimeError):
             self.clientLock.release()
-    
+
     def setCurrentThread(self, threadId):
         """
         Public method to set the current thread.
@@ -134,18 +135,18 @@
                 self.currentThread = self.threads.get(threadId)
         finally:
             self.unlockClient()
-    
+
     def dumpThreadList(self):
         """
         Public method to send the list of threads.
         """
         self.updateThreadList()
-        
+
         threadList = []
         currentId = _thread.get_ident()
         # update thread names set by user (threading.setName)
         threadNames = {t.ident: t.getName() for t in threading.enumerate()}
-        
+
         for threadId, thd in self.threads.items():
             d = {"id": threadId}
             try:
@@ -153,21 +154,24 @@
                 d["broken"] = thd.isBroken
                 d["except"] = thd.isException
             except Exception:
-                d["name"] = 'UnknownThread'
+                d["name"] = "UnknownThread"
                 d["broken"] = False
                 d["except"] = False
-            
+
             threadList.append(d)
-        
-        self.sendJsonCommand("ResponseThreadList", {
-            "currentID": currentId,
-            "threadList": threadList,
-        })
-    
+
+        self.sendJsonCommand(
+            "ResponseThreadList",
+            {
+                "currentID": currentId,
+                "threadList": threadList,
+            },
+        )
+
     def getExecutedFrame(self, frame):
         """
         Public method to return the currently executed frame.
-        
+
         @param frame the current frame
         @type frame object
         @return the frame which is excecuted (without debugger frames)
@@ -178,13 +182,18 @@
         while frame is not None:
             baseName = os.path.basename(frame.f_code.co_filename)
             if not baseName.startswith(
-                    ('DebugClientBase.py', 'DebugBase.py', 'AsyncFile.py',
-                     'ThreadExtension.py')):
+                (
+                    "DebugClientBase.py",
+                    "DebugBase.py",
+                    "AsyncFile.py",
+                    "ThreadExtension.py",
+                )
+            ):
                 break
             frame = frame.f_back
-        
+
         return frame
-    
+
     def updateThreadList(self):
         """
         Public method to update the list of running threads.
@@ -192,86 +201,89 @@
         frames = sys._current_frames()
         for threadId, frame in frames.items():
             # skip our own timer thread
-            if frame.f_code.co_name == '__eventPollTimer':
+            if frame.f_code.co_name == "__eventPollTimer":
                 continue
-            
+
             # Unknown thread
             if threadId not in self.threads:
                 newThread = DebugBase(self)
-                name = 'Thread-{0}'.format(self.threadNumber)
+                name = "Thread-{0}".format(self.threadNumber)
                 self.threadNumber += 1
-                
+
                 newThread.id = threadId
                 newThread.name = name
                 self.threads[threadId] = newThread
-            
+
             # adjust current frame
             if "__pypy__" not in sys.builtin_module_names:
                 # Don't update with None
                 currentFrame = self.getExecutedFrame(frame)
-                if (currentFrame is not None and
-                        self.threads[threadId].isBroken is False):
+                if (
+                    currentFrame is not None
+                    and self.threads[threadId].isBroken is False
+                ):
                     self.threads[threadId].currentFrame = currentFrame
-        
+
         # Clean up obsolet because terminated threads
-        self.threads = {id_: thrd for id_, thrd in self.threads.items()
-                        if id_ in frames}
-    
+        self.threads = {
+            id_: thrd for id_, thrd in self.threads.items() if id_ in frames
+        }
+
     #######################################################################
     ## Methods below deal with patching various modules to support
     ## debugging of threads.
     #######################################################################
-    
+
     def patchPyThread(self, module):
         """
         Public method to patch Python _thread module.
-        
+
         @param module reference to the imported module to be patched
         @type module
         """
         # make thread hooks available to system
         self._original_start_new_thread = module.start_new_thread
         module.start_new_thread = self.attachThread
-    
+
     def patchGreenlet(self, module):
         """
         Public method to patch the 'greenlet' module.
-        
+
         @param module reference to the imported module to be patched
         @type module
         @return flag indicating that the module was processed
         @rtype bool
         """
         # Check for greenlet.settrace
-        if hasattr(module, 'settrace'):
+        if hasattr(module, "settrace"):
             DebugBase.pollTimerEnabled = False
             return True
         return False
-    
+
     def patchPyThreading(self, module):
         """
         Public method to patch the Python threading module.
-        
+
         @param module reference to the imported module to be patched
         @type module
         """
         # _debugClient as a class attribute can't be accessed in following
         # class. Therefore we need a global variable.
         _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 = DebugBase(_debugClient)
             newThread.name = self.name
-            
+
             _debugClient.threads[self.ident] = newThread
             _debugClient.dumpThreadList()
-            
+
             # see DebugBase.bootstrap
             sys.settrace(newThread.trace_dispatch)
             try:
@@ -282,11 +294,12 @@
             finally:
                 sys.settrace(None)
                 _debugClient.dumpThreadList()
-        
+
         class ThreadWrapper(module.Thread):
             """
             Wrapper class for threading.Thread.
             """
+
             def __init__(self, *args, **kwargs):
                 """
                 Constructor
@@ -294,44 +307,45 @@
                 # Overwrite the provided run method with our own, to
                 # intercept the thread creation by threading.Thread
                 self.run = lambda s=self, run=self.run: _bootstrap(s, run)
-                
+
                 super().__init__(*args, **kwargs)
-        
+
         module.Thread = ThreadWrapper
-        
+
         # Special handling of threading.(_)Timer
         timer = module.Timer
-            
+
         class TimerWrapper(timer, ThreadWrapper):
             """
             Wrapper class for threading.(_)Timer.
             """
+
             def __init__(self, interval, function, *args, **kwargs):
                 """
                 Constructor
                 """
-                super().__init__(
-                    interval, function, *args, **kwargs)
-        
+                super().__init__(interval, function, *args, **kwargs)
+
         module.Timer = TimerWrapper
-    
+
         # Special handling of threading._DummyThread
         class DummyThreadWrapper(module._DummyThread, ThreadWrapper):
             """
             Wrapper class for threading._DummyThread.
             """
+
             def __init__(self, *args, **kwargs):
                 """
                 Constructor
                 """
                 super().__init__(*args, **kwargs)
-        
+
         module._DummyThread = DummyThreadWrapper
-    
+
     def patchQThread(self, module):
         """
         Public method to patch the QtCore module's QThread.
-        
+
         @param module reference to the imported module to be patched
         @type module
         """
@@ -342,24 +356,24 @@
         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)
-            
+            name = "QtThread-{0}".format(_qtThreadNumber)
+
             _qtThreadNumber += 1
-            
+
             newThread.id = ident
             newThread.name = name
-            
+
             _debugClient.threads[ident] = newThread
             _debugClient.dumpThreadList()
-            
+
             # see DebugBase.bootstrap
             sys.settrace(newThread.trace_dispatch)
             try:
@@ -373,36 +387,36 @@
             finally:
                 sys.settrace(None)
                 _debugClient.dumpThreadList()
-    
+
         class QThreadWrapper(module.QThread):
             """
             Wrapper class for *.QThread.
             """
+
             def __init__(self, *args, **kwargs):
                 """
                 Constructor
                 """
                 # Overwrite the provided run method with our own, to
                 # intercept the thread creation by Qt
-                self.run = lambda s=self, run=self.run: (
-                    _bootstrapQThread(s, run))
-                
+                self.run = lambda s=self, run=self.run: (_bootstrapQThread(s, run))
+
                 super().__init__(*args, **kwargs)
-        
+
         class QRunnableWrapper(module.QRunnable):
             """
             Wrapper class for *.QRunnable.
             """
+
             def __init__(self, *args, **kwargs):
                 """
                 Constructor
                 """
                 # Overwrite the provided run method with our own, to
                 # intercept the thread creation by Qt
-                self.run = lambda s=self, run=self.run: (
-                    _bootstrapQThread(s, run))
-                
+                self.run = lambda s=self, run=self.run: (_bootstrapQThread(s, run))
+
                 super().__init__(*args, **kwargs)
-        
+
         module.QThread = QThreadWrapper
         module.QRunnable = QRunnableWrapper

eric ide

mercurial