1+ import dis
2+ import io
3+ import textwrap
14import types
25
36from test .support .bytecode_helper import AssemblerTestCase
@@ -22,11 +25,13 @@ def complete_metadata(self, metadata, filename="myfile.py"):
2225 metadata .setdefault ('filename' , filename )
2326 return metadata
2427
25- def assemble_test (self , insts , metadata , expected ):
28+ def insts_to_code_object (self , insts , metadata ):
2629 metadata = self .complete_metadata (metadata )
2730 insts = self .complete_insts_info (insts )
31+ return self .get_code_object (metadata ['filename' ], insts , metadata )
2832
29- co = self .get_code_object (metadata ['filename' ], insts , metadata )
33+ def assemble_test (self , insts , metadata , expected ):
34+ co = self .insts_to_code_object (insts , metadata )
3035 self .assertIsInstance (co , types .CodeType )
3136
3237 expected_metadata = {}
@@ -108,3 +113,35 @@ def inner():
108113
109114 expected = {(0 ,): 0 , (1 ,): 1 , (2 ,): 0 , (120 ,): 0 , (121 ,): 1 }
110115 self .assemble_test (instructions , metadata , expected )
116+
117+
118+ def test_exception_table (self ):
119+ metadata = {
120+ 'filename' : 'exc.py' ,
121+ 'name' : 'exc' ,
122+ 'consts' : {2 : 0 },
123+ }
124+
125+ # code for "try: pass\n except: pass"
126+ insts = [
127+ ('RESUME' , 0 ),
128+ ('SETUP_FINALLY' , 3 ),
129+ ('RETURN_CONST' , 0 ),
130+ ('SETUP_CLEANUP' , 8 ),
131+ ('PUSH_EXC_INFO' , 0 ),
132+ ('POP_TOP' , 0 ),
133+ ('POP_EXCEPT' , 0 ),
134+ ('RETURN_CONST' , 0 ),
135+ ('COPY' , 3 ),
136+ ('POP_EXCEPT' , 0 ),
137+ ('RERAISE' , 1 ),
138+ ]
139+ co = self .insts_to_code_object (insts , metadata )
140+ output = io .StringIO ()
141+ dis .dis (co , file = output )
142+ exc_table = textwrap .dedent ("""
143+ ExceptionTable:
144+ L1 to L2 -> L2 [0]
145+ L2 to L3 -> L3 [1] lasti
146+ """ )
147+ self .assertTrue (output .getvalue ().endswith (exc_table ))
0 commit comments