@@ -389,6 +389,7 @@ def bug42562():
389389 POP_EXCEPT
390390 RERAISE 1
391391ExceptionTable:
392+ 4 rows
392393""" % (TRACEBACK_CODE .co_firstlineno ,
393394 TRACEBACK_CODE .co_firstlineno + 1 ,
394395 TRACEBACK_CODE .co_firstlineno + 2 ,
@@ -421,6 +422,133 @@ def _fstring(a, b, c, d):
421422 RETURN_VALUE
422423""" % (_fstring .__code__ .co_firstlineno , _fstring .__code__ .co_firstlineno + 1 )
423424
425+ def _with (c ):
426+ with c :
427+ x = 1
428+ y = 2
429+
430+ dis_with = """\
431+ %3d RESUME 0
432+
433+ %3d LOAD_FAST 0 (c)
434+ BEFORE_WITH
435+ POP_TOP
436+
437+ %3d LOAD_CONST 1 (1)
438+ STORE_FAST 1 (x)
439+
440+ %3d LOAD_CONST 0 (None)
441+ LOAD_CONST 0 (None)
442+ LOAD_CONST 0 (None)
443+ CALL 2
444+ POP_TOP
445+
446+ %3d LOAD_CONST 2 (2)
447+ STORE_FAST 2 (y)
448+ LOAD_CONST 0 (None)
449+ RETURN_VALUE
450+
451+ %3d >> PUSH_EXC_INFO
452+ WITH_EXCEPT_START
453+ POP_JUMP_FORWARD_IF_TRUE 1 (to 46)
454+ RERAISE 2
455+ >> POP_TOP
456+ POP_EXCEPT
457+ POP_TOP
458+ POP_TOP
459+
460+ %3d LOAD_CONST 2 (2)
461+ STORE_FAST 2 (y)
462+ LOAD_CONST 0 (None)
463+ RETURN_VALUE
464+ >> COPY 3
465+ POP_EXCEPT
466+ RERAISE 1
467+ ExceptionTable:
468+ 2 rows
469+ """ % (_with .__code__ .co_firstlineno ,
470+ _with .__code__ .co_firstlineno + 1 ,
471+ _with .__code__ .co_firstlineno + 2 ,
472+ _with .__code__ .co_firstlineno + 1 ,
473+ _with .__code__ .co_firstlineno + 3 ,
474+ _with .__code__ .co_firstlineno + 1 ,
475+ _with .__code__ .co_firstlineno + 3 ,
476+ )
477+
478+ async def _asyncwith (c ):
479+ async with c :
480+ x = 1
481+ y = 2
482+
483+ dis_asyncwith = """\
484+ %3d RETURN_GENERATOR
485+ POP_TOP
486+ RESUME 0
487+
488+ %3d LOAD_FAST 0 (c)
489+ BEFORE_ASYNC_WITH
490+ GET_AWAITABLE 1
491+ LOAD_CONST 0 (None)
492+ >> SEND 3 (to 22)
493+ YIELD_VALUE 3
494+ RESUME 3
495+ JUMP_BACKWARD_NO_INTERRUPT 4 (to 14)
496+ >> POP_TOP
497+
498+ %3d LOAD_CONST 1 (1)
499+ STORE_FAST 1 (x)
500+
501+ %3d LOAD_CONST 0 (None)
502+ LOAD_CONST 0 (None)
503+ LOAD_CONST 0 (None)
504+ CALL 2
505+ GET_AWAITABLE 2
506+ LOAD_CONST 0 (None)
507+ >> SEND 3 (to 56)
508+ YIELD_VALUE 2
509+ RESUME 3
510+ JUMP_BACKWARD_NO_INTERRUPT 4 (to 48)
511+ >> POP_TOP
512+
513+ %3d LOAD_CONST 2 (2)
514+ STORE_FAST 2 (y)
515+ LOAD_CONST 0 (None)
516+ RETURN_VALUE
517+
518+ %3d >> PUSH_EXC_INFO
519+ WITH_EXCEPT_START
520+ GET_AWAITABLE 2
521+ LOAD_CONST 0 (None)
522+ >> SEND 3 (to 82)
523+ YIELD_VALUE 6
524+ RESUME 3
525+ JUMP_BACKWARD_NO_INTERRUPT 4 (to 74)
526+ >> POP_JUMP_FORWARD_IF_TRUE 1 (to 86)
527+ RERAISE 2
528+ >> POP_TOP
529+ POP_EXCEPT
530+ POP_TOP
531+ POP_TOP
532+
533+ %3d LOAD_CONST 2 (2)
534+ STORE_FAST 2 (y)
535+ LOAD_CONST 0 (None)
536+ RETURN_VALUE
537+ >> COPY 3
538+ POP_EXCEPT
539+ RERAISE 1
540+ ExceptionTable:
541+ 2 rows
542+ """ % (_asyncwith .__code__ .co_firstlineno ,
543+ _asyncwith .__code__ .co_firstlineno + 1 ,
544+ _asyncwith .__code__ .co_firstlineno + 2 ,
545+ _asyncwith .__code__ .co_firstlineno + 1 ,
546+ _asyncwith .__code__ .co_firstlineno + 3 ,
547+ _asyncwith .__code__ .co_firstlineno + 1 ,
548+ _asyncwith .__code__ .co_firstlineno + 3 ,
549+ )
550+
551+
424552def _tryfinally (a , b ):
425553 try :
426554 return a
@@ -455,6 +583,7 @@ def _tryfinallyconst(b):
455583 POP_EXCEPT
456584 RERAISE 1
457585ExceptionTable:
586+ 2 rows
458587""" % (_tryfinally .__code__ .co_firstlineno ,
459588 _tryfinally .__code__ .co_firstlineno + 1 ,
460589 _tryfinally .__code__ .co_firstlineno + 2 ,
@@ -484,6 +613,7 @@ def _tryfinallyconst(b):
484613 POP_EXCEPT
485614 RERAISE 1
486615ExceptionTable:
616+ 1 row
487617""" % (_tryfinallyconst .__code__ .co_firstlineno ,
488618 _tryfinallyconst .__code__ .co_firstlineno + 1 ,
489619 _tryfinallyconst .__code__ .co_firstlineno + 2 ,
@@ -678,6 +808,18 @@ def assert_offsets_increasing(self, text, delta):
678808 self .assertGreaterEqual (offset , expected_offset , line )
679809 expected_offset = offset + delta
680810
811+ def assert_exception_table_increasing (self , lines ):
812+ prev_start , prev_end = - 1 , - 1
813+ count = 0
814+ for line in lines :
815+ m = re .match (r' (\d+) to (\d+) -> \d+ \[\d+\]' , line )
816+ start , end = [int (g ) for g in m .groups ()]
817+ self .assertGreaterEqual (end , start )
818+ self .assertGreater (start , prev_end )
819+ prev_start , prev_end = start , end
820+ count += 1
821+ return count
822+
681823 def strip_offsets (self , text ):
682824 lines = text .splitlines (True )
683825 start , end = self .find_offset_column (lines )
@@ -691,6 +833,9 @@ def strip_offsets(self, text):
691833 res .append (line )
692834 else :
693835 res .append (line [:start ] + line [end :])
836+ num_rows = self .assert_exception_table_increasing (lines )
837+ if num_rows :
838+ res .append (f"{ num_rows } row{ 's' if num_rows > 1 else '' } \n " )
694839 return "" .join (res )
695840
696841 def do_disassembly_compare (self , got , expected , with_offsets = False ):
@@ -883,6 +1028,12 @@ def test_disassemble_coroutine(self):
8831028 def test_disassemble_fstring (self ):
8841029 self .do_disassembly_test (_fstring , dis_fstring )
8851030
1031+ def test_disassemble_with (self ):
1032+ self .do_disassembly_test (_with , dis_with )
1033+
1034+ def test_disassemble_asyncwith (self ):
1035+ self .do_disassembly_test (_asyncwith , dis_asyncwith )
1036+
8861037 def test_disassemble_try_finally (self ):
8871038 self .do_disassembly_test (_tryfinally , dis_tryfinally )
8881039 self .do_disassembly_test (_tryfinallyconst , dis_tryfinallyconst )
@@ -1471,16 +1622,16 @@ def _prepare_test_cases():
14711622 Instruction (opname = 'RETURN_VALUE' , opcode = 83 , arg = None , argval = None , argrepr = '' , offset = 302 , starts_line = None , is_jump_target = False , positions = None ),
14721623 Instruction (opname = 'PUSH_EXC_INFO' , opcode = 35 , arg = None , argval = None , argrepr = '' , offset = 304 , starts_line = 25 , is_jump_target = False , positions = None ),
14731624 Instruction (opname = 'WITH_EXCEPT_START' , opcode = 49 , arg = None , argval = None , argrepr = '' , offset = 306 , starts_line = None , is_jump_target = False , positions = None ),
1474- Instruction (opname = 'POP_JUMP_FORWARD_IF_TRUE' , opcode = 115 , arg = 4 , argval = 318 , argrepr = 'to 318 ' , offset = 308 , starts_line = None , is_jump_target = False , positions = None ),
1625+ Instruction (opname = 'POP_JUMP_FORWARD_IF_TRUE' , opcode = 115 , arg = 1 , argval = 312 , argrepr = 'to 312 ' , offset = 308 , starts_line = None , is_jump_target = False , positions = None ),
14751626 Instruction (opname = 'RERAISE' , opcode = 119 , arg = 2 , argval = 2 , argrepr = '' , offset = 310 , starts_line = None , is_jump_target = False , positions = None ),
1476- Instruction (opname = 'COPY ' , opcode = 120 , arg = 3 , argval = 3 , argrepr = '' , offset = 312 , starts_line = None , is_jump_target = False , positions = None ),
1627+ Instruction (opname = 'POP_TOP ' , opcode = 1 , arg = None , argval = None , argrepr = '' , offset = 312 , starts_line = None , is_jump_target = True , positions = None ),
14771628 Instruction (opname = 'POP_EXCEPT' , opcode = 89 , arg = None , argval = None , argrepr = '' , offset = 314 , starts_line = None , is_jump_target = False , positions = None ),
1478- Instruction (opname = 'RERAISE ' , opcode = 119 , arg = 1 , argval = 1 , argrepr = '' , offset = 316 , starts_line = None , is_jump_target = False , positions = None ),
1479- Instruction (opname = 'POP_TOP' , opcode = 1 , arg = None , argval = None , argrepr = '' , offset = 318 , starts_line = None , is_jump_target = True , positions = None ),
1480- Instruction (opname = 'POP_EXCEPT ' , opcode = 89 , arg = None , argval = None , argrepr = '' , offset = 320 , starts_line = None , is_jump_target = False , positions = None ),
1481- Instruction (opname = 'POP_TOP ' , opcode = 1 , arg = None , argval = None , argrepr = '' , offset = 322 , starts_line = None , is_jump_target = False , positions = None ),
1482- Instruction (opname = 'POP_TOP ' , opcode = 1 , arg = None , argval = None , argrepr = '' , offset = 324 , starts_line = None , is_jump_target = False , positions = None ),
1483- Instruction (opname = 'JUMP_BACKWARD ' , opcode = 140 , arg = 27 , argval = 274 , argrepr = 'to 274 ' , offset = 326 , starts_line = None , is_jump_target = False , positions = None ),
1629+ Instruction (opname = 'POP_TOP ' , opcode = 1 , arg = None , argval = None , argrepr = '' , offset = 316 , starts_line = None , is_jump_target = False , positions = None ),
1630+ Instruction (opname = 'POP_TOP' , opcode = 1 , arg = None , argval = None , argrepr = '' , offset = 318 , starts_line = None , is_jump_target = False , positions = None ),
1631+ Instruction (opname = 'JUMP_BACKWARD ' , opcode = 140 , arg = 24 , argval = 274 , argrepr = 'to 274 ' , offset = 320 , starts_line = None , is_jump_target = False , positions = None ),
1632+ Instruction (opname = 'COPY ' , opcode = 120 , arg = 3 , argval = 3 , argrepr = '' , offset = 322 , starts_line = None , is_jump_target = False , positions = None ),
1633+ Instruction (opname = 'POP_EXCEPT ' , opcode = 89 , arg = None , argval = None , argrepr = '' , offset = 324 , starts_line = None , is_jump_target = False , positions = None ),
1634+ Instruction (opname = 'RERAISE ' , opcode = 119 , arg = 1 , argval = 1 , argrepr = '' , offset = 326 , starts_line = None , is_jump_target = False , positions = None ),
14841635 Instruction (opname = 'PUSH_EXC_INFO' , opcode = 35 , arg = None , argval = None , argrepr = '' , offset = 328 , starts_line = None , is_jump_target = False , positions = None ),
14851636 Instruction (opname = 'LOAD_GLOBAL' , opcode = 116 , arg = 4 , argval = 'ZeroDivisionError' , argrepr = 'ZeroDivisionError' , offset = 330 , starts_line = 22 , is_jump_target = False , positions = None ),
14861637 Instruction (opname = 'CHECK_EXC_MATCH' , opcode = 36 , arg = None , argval = None , argrepr = '' , offset = 342 , starts_line = None , is_jump_target = False , positions = None ),
0 commit comments