@@ -389,6 +389,7 @@ def bug42562():
389389 POP_EXCEPT
390390 RERAISE 1
391391ExceptionTable:
392+ 4 rows
392393""" % (TRACEBACK_CODE .co_firstlineno ,
393394TRACEBACK_CODE .co_firstlineno + 1 ,
394395TRACEBACK_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 ):
425553try :
426554return 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):
678808self .assertGreaterEqual (offset ,expected_offset ,line )
679809expected_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+
681823def strip_offsets (self ,text ):
682824lines = text .splitlines (True )
683825start ,end = self .find_offset_column (lines )
@@ -691,6 +833,9 @@ def strip_offsets(self, text):
691833res .append (line )
692834else :
693835res .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 " )
694839return "" .join (res )
695840
696841def do_disassembly_compare (self ,got ,expected ,with_offsets = False ):
@@ -883,6 +1028,12 @@ def test_disassemble_coroutine(self):
8831028def test_disassemble_fstring (self ):
8841029self .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+
8861037def test_disassemble_try_finally (self ):
8871038self .do_disassembly_test (_tryfinally ,dis_tryfinally )
8881039self .do_disassembly_test (_tryfinallyconst ,dis_tryfinallyconst )
@@ -1471,16 +1622,16 @@ def _prepare_test_cases():
14711622Instruction (opname = 'RETURN_VALUE' ,opcode = 83 ,arg = None ,argval = None ,argrepr = '' ,offset = 302 ,starts_line = None ,is_jump_target = False ,positions = None ),
14721623Instruction (opname = 'PUSH_EXC_INFO' ,opcode = 35 ,arg = None ,argval = None ,argrepr = '' ,offset = 304 ,starts_line = 25 ,is_jump_target = False ,positions = None ),
14731624Instruction (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 = 'to318 ' ,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 = 'to312 ' ,offset = 308 ,starts_line = None ,is_jump_target = False ,positions = None ),
14751626Instruction (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 ),
14771628Instruction (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 ),
14841635Instruction (opname = 'PUSH_EXC_INFO' ,opcode = 35 ,arg = None ,argval = None ,argrepr = '' ,offset = 328 ,starts_line = None ,is_jump_target = False ,positions = None ),
14851636Instruction (opname = 'LOAD_GLOBAL' ,opcode = 116 ,arg = 4 ,argval = 'ZeroDivisionError' ,argrepr = 'ZeroDivisionError' ,offset = 330 ,starts_line = 22 ,is_jump_target = False ,positions = None ),
14861637Instruction (opname = 'CHECK_EXC_MATCH' ,opcode = 36 ,arg = None ,argval = None ,argrepr = '' ,offset = 342 ,starts_line = None ,is_jump_target = False ,positions = None ),