diff options
Diffstat (limited to 'Lib/dis.py')
-rw-r--r-- | Lib/dis.py | 53 |
1 files changed, 37 insertions, 16 deletions
@@ -262,6 +262,7 @@ _Instruction = collections.namedtuple( 'offset', 'start_offset', 'starts_line', + 'line_number', 'is_jump_target', 'positions' ], @@ -278,7 +279,8 @@ _Instruction.start_offset.__doc__ = ( "Start index of operation within bytecode sequence, including extended args if present; " "otherwise equal to Instruction.offset" ) -_Instruction.starts_line.__doc__ = "Line started by this opcode (if any), otherwise None" +_Instruction.starts_line.__doc__ = "True if this opcode starts a source line, otherwise False" +_Instruction.line_number.__doc__ = "source line number associated with this opcode (if any), otherwise None" _Instruction.is_jump_target.__doc__ = "True if other code jumps to here, otherwise False" _Instruction.positions.__doc__ = "dis.Positions object holding the span of source code covered by this instruction" @@ -321,7 +323,8 @@ class Instruction(_Instruction): offset - start index of operation within bytecode sequence start_offset - start index of operation within bytecode sequence including extended args if present; otherwise equal to Instruction.offset - starts_line - line started by this opcode (if any), otherwise None + starts_line - True if this opcode starts a source line, otherwise False + line_number - source line number associated with this opcode (if any), otherwise None is_jump_target - True if other code jumps to here, otherwise False positions - Optional dis.Positions object holding the span of source code covered by this instruction @@ -376,9 +379,10 @@ class Instruction(_Instruction): fields = [] # Column: Source code line number if lineno_width: - if self.starts_line is not None: - lineno_fmt = "%%%dd" % lineno_width - fields.append(lineno_fmt % self.starts_line) + if self.starts_line: + lineno_fmt = "%%%dd" if self.line_number is not None else "%%%ds" + lineno_fmt = lineno_fmt % lineno_width + fields.append(lineno_fmt % self.line_number) else: fields.append(' ' * lineno_width) # Column: Current instruction indicator @@ -527,12 +531,18 @@ def _get_instructions_bytes(code, varname_from_oparg=None, for start, end, target, _, _ in exception_entries: for i in range(start, end): labels.add(target) - starts_line = None + starts_line = False + local_line_number = None + line_number = None for offset, start_offset, op, arg in _unpack_opargs(original_code): if linestarts is not None: - starts_line = linestarts.get(offset, None) - if starts_line is not None: - starts_line += line_offset + starts_line = offset in linestarts + if starts_line: + local_line_number = linestarts[offset] + if local_line_number is not None: + line_number = local_line_number + line_offset + else: + line_number = None is_jump_target = offset in labels argval = None argrepr = '' @@ -599,7 +609,8 @@ def _get_instructions_bytes(code, varname_from_oparg=None, argrepr = _intrinsic_2_descs[arg] yield Instruction(_all_opname[op], op, arg, argval, argrepr, - offset, start_offset, starts_line, is_jump_target, positions) + offset, start_offset, starts_line, line_number, + is_jump_target, positions) if not caches: continue if not show_caches: @@ -618,7 +629,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None, else: argrepr = "" yield Instruction( - "CACHE", CACHE, 0, None, argrepr, offset, offset, None, False, + "CACHE", CACHE, 0, None, argrepr, offset, offset, False, None, False, Positions(*next(co_positions, ())) ) @@ -651,13 +662,21 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None, *, file=None, line_offset=0, exception_entries=(), co_positions=None, show_caches=False, original_code=None): # Omit the line number column entirely if we have no line number info - show_lineno = bool(linestarts) + if bool(linestarts): + linestarts_ints = [line for line in linestarts.values() if line is not None] + show_lineno = len(linestarts_ints) > 0 + else: + show_lineno = False + if show_lineno: - maxlineno = max(linestarts.values()) + line_offset + maxlineno = max(linestarts_ints) + line_offset if maxlineno >= 1000: lineno_width = len(str(maxlineno)) else: lineno_width = 3 + + if lineno_width < len(str(None)) and None in linestarts.values(): + lineno_width = len(str(None)) else: lineno_width = 0 maxoffset = len(code) - 2 @@ -673,7 +692,7 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None, show_caches=show_caches, original_code=original_code): new_source_line = (show_lineno and - instr.starts_line is not None and + instr.starts_line and instr.offset > 0) if new_source_line: print(file=file) @@ -755,10 +774,12 @@ def findlinestarts(code): """Find the offsets in a byte code which are start of lines in the source. Generate pairs (offset, lineno) + lineno will be an integer or None the offset does not have a source line. """ - lastline = None + + lastline = False # None is a valid line number for start, end, line in code.co_lines(): - if line is not None and line != lastline: + if line is not lastline: lastline = line yield start, line return |