eric6/DebugClients/Python/DebugBase.py

branch
multi_processing
changeset 7802
eefe954f01e8
parent 7646
39e3db2b4936
parent 7767
d0a86562934e
child 7894
4370a8b30648
--- a/eric6/DebugClients/Python/DebugBase.py	Sun Jul 05 11:11:24 2020 +0200
+++ b/eric6/DebugClients/Python/DebugBase.py	Sun Oct 18 12:35:30 2020 +0200
@@ -14,6 +14,7 @@
 import inspect
 import ctypes
 import time
+import dis
 
 from BreakpointWatch import Breakpoint, Watch
 
@@ -873,10 +874,12 @@
         self.isBroken = True
         self.isException = True
         
+        disassembly = None
         stack = []
         if exctb:
             frlist = self.__extract_stack(exctb)
             frlist.reverse()
+            disassembly = self.__disassemble(frlist[0][0])
             
             self.currentFrame = frlist[0][0]
             stack = self.getStack(frlist[self.skipFrames:])
@@ -885,6 +888,7 @@
         self._dbgClient.currentThread = self
         self._dbgClient.currentThreadExec = self
         self._dbgClient.sendException(exctypetxt, excvaltxt, stack)
+        self._dbgClient.setDisassembly(disassembly)
         self._dbgClient.dumpThreadList()
         
         if exctb is not None:
@@ -929,6 +933,60 @@
         tb = None
         return stack
 
+    def __disassemble(self, frame):
+        """
+        Private method to generate a disassembly of the given code object.
+        
+        @param frame frame object to be disassembled
+        @type code
+        @return dictionary containing the disassembly information
+        @rtype dict
+        """
+        co = frame.f_code
+        disDict = {
+            "lasti": frame.f_lasti,
+            "firstlineno": co.co_firstlineno,
+            "instructions": [],
+        }
+        
+        # 1. disassembly info
+        for instr in dis.get_instructions(co):
+            instrDict = {
+                "lineno":
+                    0 if instr.starts_line is None else instr.starts_line,
+                "isJumpTarget": instr.is_jump_target,
+                "offset": instr.offset,
+                "opname": instr.opname,
+                "arg": instr.arg,
+                "argrepr": instr.argrepr,
+            }
+            disDict["instructions"].append(instrDict)
+        
+        # 2. code info
+        # Note: keep in sync with PythonDisViewer.__createCodeInfo()
+        disDict["codeinfo"] = {
+            "name": co.co_name,
+            "filename": co.co_filename,
+            "firstlineno": co.co_firstlineno,
+            "argcount": co.co_argcount,
+            "kwonlyargcount": co.co_kwonlyargcount,
+            "nlocals": co.co_nlocals,
+            "stacksize": co.co_stacksize,
+            "flags": dis.pretty_flags(co.co_flags),
+            "consts": [str(const) for const in co.co_consts],
+            "names": [str(name) for name in co.co_names],
+            "varnames": [str(name) for name in co.co_varnames],
+            "freevars": [str(var) for var in co.co_freevars],
+            "cellvars": [str(var) for var in co.co_cellvars],
+        }
+        try:
+            disDict["codeinfo"]["posonlyargcount"] = co.co_posonlyargcount
+        except AttributeError:
+            # does not exist prior to 3.8.0
+            disDict["codeinfo"]["posonlyargcount"] = 0
+        
+        return disDict
+    
     def __extractSystemExitMessage(self, excinfo):
         """
         Private method to get the SystemExit code and message.

eric ide

mercurial