diff -r 39e3db2b4936 -r eefe954f01e8 eric6/DebugClients/Python/DebugBase.py --- 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.