@@ -70,18 +70,12 @@ def get_const_info(const_index, const_list):
7070 if const_list is not None :
7171 arg_val = const_list [const_index ]
7272
73- arg_repr = (
74- prefer_double_quote (repr (arg_val ))
75- if isinstance (arg_val , str )
76- else repr (arg_val )
77- )
73+ arg_repr = prefer_double_quote (repr (arg_val )) if isinstance (arg_val , str ) else repr (arg_val )
7874
7975 # Float values "nan" and "inf" are not directly representable in Python at least
8076 # before 3.5 and even there it is via a library constant.
8177 # So we will canonicalize their representation as float('nan') and float('inf')
82- if isinstance (arg_val , float ) and str (arg_val ) in frozenset (
83- ["nan" , "-nan" , "inf" , "-inf" ]
84- ):
78+ if isinstance (arg_val , float ) and str (arg_val ) in frozenset (["nan" , "-nan" , "inf" , "-inf" ]):
8579 return arg_val , f"float('{ arg_val } ')"
8680 return arg_val , arg_repr
8781
@@ -140,6 +134,7 @@ def get_optype(opcode: int, opc) -> str:
140134
141135 return "??"
142136
137+
143138def offset2line (offset : int , linestarts ):
144139 """linestarts is expected to be a *list of (offset, line number)
145140 where both offset and line number are in increasing order.
@@ -177,9 +172,7 @@ def _parse_varint(iterator: Iterator[int]) -> int:
177172 return val
178173
179174
180- _ExceptionTableEntry = collections .namedtuple (
181- "_ExceptionTableEntry" , "start end target depth lasti"
182- )
175+ _ExceptionTableEntry = collections .namedtuple ("_ExceptionTableEntry" , "start end target depth lasti" )
183176
184177
185178def parse_exception_table (exception_table : bytes ) -> list :
@@ -215,6 +208,7 @@ def prefer_double_quote(string: str) -> str:
215208 return f'"{ string [1 :- 1 ]} "'
216209 return string
217210
211+
218212def is_fixed_wordsize_bytecode (opc ) -> bool :
219213 """
220214 Returns True if intructions in opc are fixed length (2 bytes)
@@ -225,6 +219,7 @@ def is_fixed_wordsize_bytecode(opc) -> bool:
225219 # See below FIXME.
226220 return True if opc .python_version >= (3 , 6 ) else False
227221
222+
228223def get_logical_instruction_at_offset (
229224 bytecode ,
230225 offset : int ,
@@ -277,9 +272,7 @@ def get_logical_instruction_at_offset(
277272 i = offset
278273
279274 # create a localsplusnames table that resolves duplicates.
280- localsplusnames = (varnames or tuple ()) + tuple (
281- name for name in (cells or tuple ()) if name not in varnames
282- )
275+ localsplusnames = (varnames or tuple ()) + tuple (name for name in (cells or tuple ()) if name not in varnames )
283276
284277 while i < n and last_op_was_extended_arg :
285278 op = code2num (bytecode , i )
@@ -306,11 +299,7 @@ def get_logical_instruction_at_offset(
306299 # FIXME: Python 3.6.0a1 is 2, for 3.6.a3 we have 1
307300 i += 1
308301 else :
309- arg = (
310- code2num (bytecode , i )
311- + code2num (bytecode , i + 1 ) * 0x100
312- + extended_arg
313- )
302+ arg = code2num (bytecode , i ) + code2num (bytecode , i + 1 ) * 0x100 + extended_arg
314303 i += 2
315304 extended_arg = arg * 0x10000 if opname == "EXTENDED_ARG" else 0
316305
@@ -339,7 +328,12 @@ def get_logical_instruction_at_offset(
339328 else :
340329 argval , argrepr = get_name_info (arg , names )
341330 elif op in opc .JREL_OPS :
342- signed_arg = - arg if "JUMP_BACKWARD" in opname else arg
331+ signed_arg = arg
332+ if "JUMP_BACKWARD" in opname :
333+ signed_arg = - arg
334+ elif opc .version_tuple >= (3 , 14 ) and "END_ASYNC_FOR" in opname :
335+ signed_arg = - arg
336+
343337 argval = i + get_jump_val (signed_arg , opc .python_version )
344338
345339 # check cache instructions for python 3.13
@@ -357,6 +351,9 @@ def get_logical_instruction_at_offset(
357351 if opc .version_tuple >= (3 , 12 ) and opname == "FOR_ITER" :
358352 argval += 2
359353 argrepr = "to " + repr (argval )
354+ if opc .version_tuple >= (3 , 14 ) and "END_ASYNC_FOR" in opname :
355+ argrepr = "from " + repr (argval )
356+
360357 elif op in opc .JABS_OPS :
361358 argval = get_jump_val (arg , opc .python_version )
362359 argrepr = "to " + repr (argval )
@@ -403,10 +400,7 @@ def get_logical_instruction_at_offset(
403400 assert opname == "CALL_FUNCTION_EX"
404401 argrepr = format_CALL_FUNCTION_EX (code2num (bytecode , i - 1 ))
405402 else :
406- if not (
407- fixed_length_instructions
408- or opname in ("RAISE_VARARGS" , "DUP_TOPX" , "MAKE_FUNCTION" )
409- ):
403+ if not (fixed_length_instructions or opname in ("RAISE_VARARGS" , "DUP_TOPX" , "MAKE_FUNCTION" )):
410404 argrepr = "%d positional, %d named" % (
411405 code2num (bytecode , i - 2 ),
412406 code2num (bytecode , i - 1 ),
@@ -527,9 +521,7 @@ class Bytecode:
527521 Iterating over these yields the bytecode operations as Instruction instances.
528522 """
529523
530- def __init__ (
531- self , x , opc , first_line = None , current_offset = None , dup_lines : bool = True
532- ) -> None :
524+ def __init__ (self , x , opc , first_line = None , current_offset = None , dup_lines : bool = True ) -> None :
533525 self .codeobj = co = get_code_object (x )
534526 self ._line_offset = 0
535527 self ._cell_names = tuple ()
@@ -550,11 +542,7 @@ def __init__(
550542 self .opnames = opc .opname
551543 self .current_offset = current_offset
552544
553- if (
554- opc .version_tuple >= (3 , 11 )
555- and not opc .is_pypy
556- and hasattr (co , "co_exceptiontable" )
557- ):
545+ if opc .version_tuple >= (3 , 11 ) and not opc .is_pypy and hasattr (co , "co_exceptiontable" ):
558546 self .exception_entries = parse_exception_table (co .co_exceptiontable )
559547 else :
560548 self .exception_entries = None
@@ -573,9 +561,7 @@ def from_traceback(cls, tb, opc=None):
573561 opc = get_opcode_module (sys .version_info , PYTHON_IMPLEMENTATION )
574562 while tb .tb_next :
575563 tb = tb .tb_next
576- return cls (
577- tb .tb_frame .f_code , opc = opc , first_line = None , current_offset = tb .tb_lasti
578- )
564+ return cls (tb .tb_frame .f_code , opc = opc , first_line = None , current_offset = tb .tb_lasti )
579565
580566 def info (self ) -> str :
581567 """Return formatted information about the code object."""
@@ -661,9 +647,7 @@ def show_source_text(line_number: Optional[int]) -> None:
661647 if show_source and filename and line_number :
662648 source_text = getline (filename , line_number ).lstrip ()
663649 if source_text .startswith ('"""' ):
664- source_text = get_docstring (
665- filename , line_number + 1 , source_text .rstrip ()
666- )
650+ source_text = get_docstring (filename , line_number + 1 , source_text .rstrip ())
667651 if source_text :
668652 file .write (" " * 13 + "# " + source_text )
669653
@@ -681,6 +665,7 @@ def show_source_text(line_number: Optional[int]) -> None:
681665
682666 if self .opc .python_implementation == PythonImplementation .Graal :
683667 from xdis .bytecode_graal import get_instructions_bytes_graal
668+
684669 get_instructions_fn = get_instructions_bytes_graal
685670 else :
686671 get_instructions_fn = get_instructions_bytes
@@ -758,18 +743,10 @@ def show_source_text(line_number: Optional[int]) -> None:
758743 extended_arg_jump_target_offset = None
759744
760745 instructions .append (instr )
761- new_source_line = show_lineno and (
762- extended_arg_starts_line
763- or instr .starts_line is not None
764- and instr .offset >= 0
765- )
746+ new_source_line = show_lineno and (extended_arg_starts_line or instr .starts_line is not None and instr .offset >= 0 )
766747 if new_source_line :
767748 file .write ("\n " )
768- show_source_text (
769- extended_arg_starts_line
770- if extended_arg_starts_line
771- else instr .starts_line
772- )
749+ show_source_text (extended_arg_starts_line if extended_arg_starts_line else instr .starts_line )
773750
774751 is_current_instr = instr .offset == lasti
775752
@@ -798,10 +775,7 @@ def show_source_text(line_number: Optional[int]) -> None:
798775 # currently we can't track names in this area, but instead use
799776 # locals and hope the two are the same.
800777 if instr .opname == "RESERVE_FAST" :
801- file .write (
802- "# Warning: subsequent LOAD_FAST and STORE_FAST after RESERVE_FAST "
803- "are inaccurate here in Python before 1.5\n "
804- )
778+ file .write ("# Warning: subsequent LOAD_FAST and STORE_FAST after RESERVE_FAST are inaccurate here in Python before 1.5\n " )
805779 pass
806780 return instructions
807781
@@ -820,9 +794,7 @@ def get_instructions(self, x):
820794 return get_instructions_bytes (co , self .opc )
821795
822796
823- def list2bytecode (
824- inst_list : Iterable , opc , varnames : str , consts : Tuple [None , int ]
825- ) -> bytes :
797+ def list2bytecode (inst_list : Iterable , opc , varnames : str , consts : Tuple [None , int ]) -> bytes :
826798 """Convert list/tuple of list/tuples to bytecode
827799 _names_ contains a list of name objects
828800 """
@@ -831,19 +803,15 @@ def list2bytecode(
831803 opname = opcodes [0 ]
832804 operands = opcodes [1 :]
833805 if opname not in opc .opname :
834- raise TypeError (
835- "error at item %d [%s, %s], opcode not valid" % (i , opname , operands )
836- )
806+ raise TypeError ("error at item %d [%s, %s], opcode not valid" % (i , opname , operands ))
837807 opcode = opc .opmap [opname ]
838808 bc .append (opcode )
839809 print (opname , operands )
840810 gen = (j for j in operands if operands )
841811 for j in gen :
842812 k = (consts if opcode in opc .CONST_OPS else varnames ).index (j )
843813 if k == - 1 :
844- raise TypeError (
845- f"operand { i } [{ opname } , { operands } ], not found in names"
846- )
814+ raise TypeError (f"operand { i } [{ opname } , { operands } ], not found in names" )
847815 else :
848816 bc += num2code (k )
849817 pass
0 commit comments