11import dis
2- import sys
32import textwrap
43import types
54import unittest
1413 Instr ,
1514 Label ,
1615)
16+ from bytecode .utils import PY312
1717
1818
1919def _format_instr_list (block , labels , lineno ):
@@ -132,9 +132,9 @@ def get_code(source, *, filename="<string>", function=False):
132132 sub_code = [
133133 const for const in code .co_consts if isinstance (const , types .CodeType )
134134 ]
135- if len (sub_code ) != 1 :
135+ if len (sub_code ) == 0 :
136136 raise ValueError ("unable to find function code" )
137- code = sub_code [0 ]
137+ code = sub_code [- 1 ]
138138 return code
139139
140140
@@ -146,8 +146,7 @@ def disassemble(source, *, filename="<string>", function=False):
146146class TestCase (unittest .TestCase ):
147147 def assertInstructionListEqual (self , l1 , l2 ):
148148 # DO not check location information
149- self .assertEqual (len (l1 ), len (l2 ))
150- for i1 , i2 in zip (l1 , l2 ):
149+ for i1 , i2 in zip (l1 , l2 , strict = True ):
151150 if isinstance (i1 , Instr ):
152151 self .assertEqual (i1 .name , i2 .name )
153152 if not isinstance (i1 .arg , Label ):
@@ -164,74 +163,34 @@ def assertCodeObjectEqual(self, code1: types.CodeType, code2: types.CodeType):
164163 self .assertSequenceEqual (code1 .co_cellvars , code2 .co_cellvars )
165164 self .assertSequenceEqual (code1 .co_freevars , code2 .co_freevars )
166165 self .assertSetEqual (set (code1 .co_varnames ), set (code2 .co_varnames ))
167- if sys .version_info >= (3 , 11 ):
168- self .assertSequenceEqual (code1 .co_exceptiontable , code2 .co_exceptiontable )
169- # We do not compare linetables because CPython does not always optimize
170- # the packing of the table
171- self .assertSequenceEqual (
172- list (code1 .co_positions ()), list (code2 .co_positions ())
173- )
174- self .assertEqual (code1 .co_qualname , code2 .co_qualname )
175- elif sys .version_info >= (3 , 10 ):
176- self .assertSequenceEqual (list (code1 .co_lines ()), list (code2 .co_lines ()))
177- else :
178- # This is safer than directly comparing co_lnotab that sometimes contains
179- # cruft
180- self .assertSequenceEqual (
181- list (dis .findlinestarts (code1 )), list (dis .findlinestarts (code2 ))
182- )
166+ self .assertSequenceEqual (code1 .co_exceptiontable , code2 .co_exceptiontable )
167+ # We do not compare linetables because CPython does not always optimize
168+ # the packing of the table
169+ self .assertSequenceEqual (list (code1 .co_positions ()), list (code2 .co_positions ()))
170+ self .assertEqual (code1 .co_qualname , code2 .co_qualname )
183171
184172 # If names or consts have been re-ordered compared the output of dis.instructions
185- if sys . version_info >= ( 3 , 12 ) and (
173+ if PY312 and (
186174 code1 .co_consts != code2 .co_consts
187175 or code1 .co_names != code2 .co_names
188176 or code1 .co_varnames != code2 .co_varnames
189177 ):
190178 instrs1 = list (dis .get_instructions (code1 ))
191179 instrs2 = list (dis .get_instructions (code2 ))
192180 self .assertEqual (len (instrs1 ), len (instrs2 ))
193- for i1 , i2 in zip (instrs1 , instrs2 ):
181+ for i1 , i2 in zip (instrs1 , instrs2 , strict = False ):
194182 self .assertEqual (i1 .opcode , i2 .opcode )
195183 if isinstance (i1 .argval , types .CodeType ):
196184 pass
197185 else :
198186 self .assertEqual (i1 .argval , i2 .argval )
199- elif sys .version_info >= (3 , 9 ):
200- self .assertSequenceEqual (code1 .co_code , code2 .co_code )
201- # On Python 3.8 it happens that fast storage index vary in a roundtrip
202187 else :
203- import opcode
204-
205- fast_storage = opcode .opmap ["LOAD_FAST" ], opcode .opmap ["STORE_FAST" ]
206- load_const = opcode .opmap ["LOAD_CONST" ]
207- load_by_name = (
208- opcode .opmap ["LOAD_GLOBAL" ],
209- opcode .opmap ["LOAD_NAME" ],
210- opcode .opmap ["LOAD_METHOD" ],
211- )
212- if code1 .co_code != code2 .co_code :
213- for b1 , a1 , b2 , a2 in zip (
214- code1 .co_code [::2 ],
215- code1 .co_code [1 ::2 ],
216- code2 .co_code [::2 ],
217- code2 .co_code [1 ::2 ],
218- ):
219- if b1 != b2 :
220- self .assertSequenceEqual (code1 .co_code , code2 .co_code )
221- # Do not check the argument of fast storage manipulation opcode
222- elif b1 in fast_storage :
223- pass
224- elif b1 == load_const :
225- self .assertEqual (code1 .co_consts [a1 ], code2 .co_consts [a2 ])
226- elif b1 in load_by_name :
227- self .assertEqual (code1 .co_names [a1 ], code2 .co_names [a2 ])
228- elif a1 != a2 :
229- self .assertSequenceEqual (code1 .co_code , code2 .co_code )
188+ self .assertSequenceEqual (code1 .co_code , code2 .co_code )
230189
231190 self .assertEqual (code1 .co_flags , code2 .co_flags )
232191
233192 def assertBlocksEqual (self , code , * expected_blocks ):
234193 self .assertEqual (len (code ), len (expected_blocks ))
235194
236- for block1 , block2 in zip (code , expected_blocks ):
195+ for block1 , block2 in zip (code , expected_blocks , strict = False ):
237196 self .assertInstructionListEqual (list (block1 ), block2 )
0 commit comments