@@ -262,6 +262,7 @@ def show_code(co, *, file=None):
262
262
'offset' ,
263
263
'start_offset' ,
264
264
'starts_line' ,
265
+ 'line_number' ,
265
266
'is_jump_target' ,
266
267
'positions'
267
268
],
@@ -278,7 +279,8 @@ def show_code(co, *, file=None):
278
279
"Start index of operation within bytecode sequence, including extended args if present; "
279
280
"otherwise equal to Instruction.offset"
280
281
)
281
- _Instruction .starts_line .__doc__ = "Line started by this opcode (if any), otherwise None"
282
+ _Instruction .starts_line .__doc__ = "True if this opcode starts a source line, otherwise False"
283
+ _Instruction .line_number .__doc__ = "source line number associated with this opcode (if any), otherwise None"
282
284
_Instruction .is_jump_target .__doc__ = "True if other code jumps to here, otherwise False"
283
285
_Instruction .positions .__doc__ = "dis.Positions object holding the span of source code covered by this instruction"
284
286
@@ -321,7 +323,8 @@ class Instruction(_Instruction):
321
323
offset - start index of operation within bytecode sequence
322
324
start_offset - start index of operation within bytecode sequence including extended args if present;
323
325
otherwise equal to Instruction.offset
324
- starts_line - line started by this opcode (if any), otherwise None
326
+ starts_line - True if this opcode starts a source line, otherwise False
327
+ line_number - source line number associated with this opcode (if any), otherwise None
325
328
is_jump_target - True if other code jumps to here, otherwise False
326
329
positions - Optional dis.Positions object holding the span of source code
327
330
covered by this instruction
@@ -376,9 +379,10 @@ def _disassemble(self, lineno_width=3, mark_as_current=False, offset_width=4):
376
379
<
6D47
code class="diff-text syntax-highlighted-line"> fields = []
377
380
# Column: Source code line number
378
381
if lineno_width :
379
- if self .starts_line is not None :
380
- lineno_fmt = "%%%dd" % lineno_width
381
- fields .append (lineno_fmt % self .starts_line )
382
+ if self .starts_line :
383
+ lineno_fmt = "%%%dd" if self .line_number is not None else "%%%ds"
384
+ lineno_fmt = lineno_fmt % lineno_width
385
+ fields .append (lineno_fmt % self .line_number )
382
386
else :
383
387
fields .append (' ' * lineno_width )
384
388
# Column: Current instruction indicator
@@ -527,12 +531,18 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
527
531
for start , end , target , _ , _ in exception_entries :
528
532
for i in range (
9E81
start , end ):
529
533
labels .add (target )
530
- starts_line = None
534
+ starts_line = False
535
+ local_line_number = None
536
+ line_number = None
531
537
for offset , start_offset , op , arg in _unpack_opargs (original_code ):
532
538
if linestarts is not None :
533
- starts_line = linestarts .get (offset , None )
534
- if starts_line is not None :
535
- starts_line += line_offset
539
+ starts_line = offset in linestarts
540
+ if starts_line :
541
+ local_line_number = linestarts [offset ]
542
+ if local_line_number is not None :
543
+ line_number = local_line_number + line_offset
544
+ else :
545
+ line_number = None
536
546
is_jump_target = offset in labels
537
547
argval = None
538
548
argrepr = ''
@@ -599,7 +609,8 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
599
609
argrepr = _intrinsic_2_descs [arg ]
600
610
yield Instruction (_all_opname [op ], op ,
601
611
arg , argval , argrepr ,
602
- offset , start_offset , starts_line , is_jump_target , positions )
612
+ offset , start_offset , starts_line , line_number ,
613
+ is_jump_target , positions )
603
614
if not caches :
604
615
continue
605
616
if not show_caches :
@@ -618,7 +629,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
618
629
else :
619
630
argrepr = ""
620
631
yield Instruction (
621
- "CACHE" , CACHE , 0 , None , argrepr , offset , offset , None , False ,
632
+ "CACHE" , CACHE , 0 , None , argrepr , offset , offset , False , None , False ,
622
633
Positions (* next (co_positions , ()))
623
634
)
624
635
@@ -651,13 +662,21 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
651
662
* , file = None , line_offset = 0 , exception_entries = (),
652
663
co_positions = None , show_caches = False , original_code = None ):
653
664
# Omit the line number column entirely if we have no line number info
654
- show_lineno = bool (linestarts )
665
+ if bool (linestarts ):
666
+ linestarts_ints = [line for line in linestarts .values () if line is not None ]
667
+ show_lineno = len (linestarts_ints ) > 0
668
+ else :
669
+ show_lineno = False
670
+
655
671
if show_lineno :
656
- maxlineno = max (linestarts . values () ) + line_offset
672
+ maxlineno = max (linestarts_ints ) + line_offset
657
673
if maxlineno >= 1000 :
658
674
lineno_width = len (str (maxlineno ))
659
675
else :
660
676
lineno_width = 3
677
+
678
+ if lineno_width < len (str (None )) and None in linestarts .values ():
679
+ lineno_width = len (str (None ))
661
680
else :
662
681
lineno_width = 0
663
682
maxoffset = len (code ) - 2
@@ -673,7 +692,7 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
673
692
show_caches = show_caches ,
674
693
original_code = original_code ):
675
694
new_source_line = (show_lineno and
676
- instr .starts_line is not None and
695
+ instr .starts_line and
677
696
instr .offset > 0 )
678
697
if new_source_line :
679
698
print (file = file )
@@ -755,10 +774,12 @@ def findlinestarts(code):
755
774
"""Find the offsets in a byte code which are start of lines in the source.
756
775
757
776
Generate pairs (offset, lineno)
777
+ lineno will be an integer or None the offset does not have a source line.
758
778
"""
759
- lastline = None
779
+
780
+ lastline = False # None is a valid line number
760
781
for start , end , line in code .co_lines ():
761
- if line is not None and line != lastline :
782
+ if line is not lastline :
762
783
lastline = line
763
784
yield start , line
764
785
return
0 commit comments