def test_continue_in_finally_with_exception(tracer, test_server): """Tests POP_FINALLY when tos is an exception.""" tracer.start() # If the finally clause executes a return, break or continue statement, the saved # exception is discarded. for x in range(2): try: raise IndexError finally: continue # BREAK_LOOP (3.7) POP_FINALLY (3.8) tracer.stop() assert tracer.events == [ Binding(target=Symbol("x"), value="0", lineno=58), JumpBackToLoopStart(lineno=62, jump_target=16), Binding(target=Symbol("x"), value="1", lineno=58), JumpBackToLoopStart(lineno=62, jump_target=16), ] assert tracer.loops == [ Loop( start_offset=16, end_offset=get_value({"py38": 36, "default": 40}), start_lineno=58, ) ] test_server.assert_frame_sent("test_continue_in_finally_with_exception")
def test_continue_in_finally_with_exception(tracer, rpc_stub): """Tests POP_FINALLY when tos is an exception.""" tracer.start() # If the finally clause executes a return, break or continue statement, the saved # exception is discarded. for x in range(2): try: raise IndexError finally: continue # BREAK_LOOP (3.7) POP_FINALLY (3.8) tracer.stop() assert tracer.events == [ Binding(target=Symbol("x"), value=0, lineno=52), JumpBackToLoopStart(lineno=56, jump_target=16), Binding(target=Symbol("x"), value=1, lineno=52), JumpBackToLoopStart(lineno=56, jump_target=16), ] assert tracer.loops == [ Loop(start_offset=16, end_offset=36, start_lineno=52) ] assert_GetFrame(rpc_stub, "test_continue_in_finally_with_exception")
def test_continue_in_finally(tracer, test_server): tracer.start() for x in range(2): try: pass finally: continue # 3.8: POP_FINALLY, >= 3.9: POP_EXCEPT, RERAISE tracer.stop() assert tracer.events == [ Binding(target=Symbol("x"), value="0", lineno=22), JumpBackToLoopStart(lineno=26, jump_target=16), Binding(target=Symbol("x"), value="1", lineno=22), JumpBackToLoopStart(lineno=26, jump_target=16), ] assert tracer.loops == [ Loop( start_offset=16, end_offset=get_value({"py38": 32, "default": 24}), start_lineno=22, ) ] test_server.assert_frame_sent("test_continue_in_finally")
def test_nested_loop(tracer, check_golden_file): tracer.start() for i in range(2): for j in range(2): a = i + j tracer.stop() assert tracer.loops == [ Loop( start_offset=get_value({"default": 28, "py37": 32}), end_offset=get_value({"default": 40, "py37": 44}), start_lineno=9, end_lineno=10, ), Loop( start_offset=get_value({"default": 16, "py37": 18}), end_offset=get_value({"default": 42, "py37": 48}), start_lineno=8, end_lineno=10, ), ]
def test_continue_in_finally(tracer, rpc_stub): tracer.start() for x in range(2): try: pass finally: continue # BREAK_LOOP (3.7) POP_FINALLY (3.8) tracer.stop() assert tracer.events == [ Binding(target=Symbol("x"), value=0, lineno=22), JumpBackToLoopStart(lineno=26, jump_target=16), Binding(target=Symbol("x"), value=1, lineno=22), JumpBackToLoopStart(lineno=26, jump_target=16), ] assert tracer.loops == [ Loop(start_offset=16, end_offset=32, start_lineno=22) ] assert_GetFrame(rpc_stub, "test_continue_in_finally")
def test_continue_in_finally(tracer, check_golden_file): tracer.start() for x in range(2): try: pass finally: continue # 3.8: POP_FINALLY, >= 3.9: POP_EXCEPT, RERAISE tracer.stop() assert tracer.loops == [ Loop( start_offset=16, end_offset=get_value({ "py38": 32, "default": 24 }), start_lineno=21, end_lineno=25, ) ]
def test_for_loop(tracer, rpc_stub): tracer.start() for i in range(2): # SETUP_LOOP (3.7), GET_ITER, FOR_ITER a = i # POP_BLOCK (3.7) for i in range(2): break # BREAK_LOOP (3.7), JUMP_ABSOLUTE (>=3.8) a = 1 for i in range(1): continue # CONTINUE_LOOP (3.7), JUMP_ABSOLUTE (>=3.8) a = 1 for i in range(2): if i == 0: # This jumps directly to FOR_ITER continue for i in range(2): if i == 1: break for i in range(1): break else: a = 1 for i in range(1): # One iteration loop. pass else: a = 1 tracer.stop() from cyberbrain import pprint pprint(tracer.events) expected_events = [ Binding(target=Symbol("i"), value="0", lineno=8), Binding(target=Symbol("a"), value="0", lineno=9, sources={Symbol("i")}), JumpBackToLoopStart(jump_target=get_value({ "py38": 16, "py37": 18 }), lineno=9), Binding(target=Symbol("i"), value="1", lineno=8), Binding(target=Symbol("a"), value="1", lineno=9, sources={Symbol("i")}), JumpBackToLoopStart(jump_target=get_value({ "py38": 16, "py37": 18 }), lineno=9), Binding(target=Symbol("i"), value="0", lineno=11), Binding(target=Symbol("i"), value="0", lineno=15), JumpBackToLoopStart(jump_target=get_value({ "py38": 56, "py37": 64 }), lineno=16), Binding(target=Symbol("i"), value="0", lineno=19), JumpBackToLoopStart(jump_target=get_value({ "py38": 76, "py37": 88 }), lineno=21), Binding(target=Symbol("i"), value="1", lineno=19), JumpBackToLoopStart(jump_target=get_value({ "py38": 76, "py37": 88 }), lineno=20), Binding(target=Symbol("i"), value="0", lineno=23), JumpBackToLoopStart(jump_target=get_value({ "py38": 100, "py37": 116 }), lineno=24), Binding(target=Symbol("i"), value="1", lineno=23), Binding(target=Symbol("i"), value="0", lineno=27), Binding(target=Symbol("i"), value="0", lineno=32), JumpBackToLoopStart(jump_target=get_value({ "py38": 148, "py37": 168 }), lineno=33), Binding(target=Symbol("a"), value="1", lineno=35), ] for index, event in enumerate(tracer.events): assert event == expected_events[ index], f"{event} {expected_events[index]}" print(tracer.loops) assert tracer.loops == [ Loop( start_offset=get_value({ "py38": 16, "py37": 18 }), end_offset=get_value({ "py38": 24, "py37": 26 }), start_lineno=8, ), Loop( start_offset=get_value({ "py38": 56, "py37": 64 }), end_offset=get_value({ "py38": 60, "py37": 68 }), start_lineno=15, ), Loop( start_offset=get_value({ "py38": 76, "py37": 88 }), end_offset=get_value({ "py38": 88, "py37": 100 }), start_lineno=19, ), Loop( start_offset=get_value({ "py38": 100, "py37": 116 }), end_offset=get_value({ "py38": 110, "py37": 126 }), start_lineno=23, ), Loop( start_offset=get_value({ "py38": 148, "py37": 168 }), end_offset=get_value({ "py38": 152, "py37": 172 }), start_lineno=32, ), ] assert_GetFrame(rpc_stub, "test_for_loop")
def test_while_loop(tracer, test_server): tracer.start() i = 0 while i < 2: a = i i += 1 i = 0 while i < 2: break # BREAK_LOOP (3.7), JUMP_ABSOLUTE (>=3.8) i = 0 while i < 1: i += 1 continue # CONTINUE_LOOP (3.7), JUMP_ABSOLUTE (>=3.8) i = 0 while i < 2: i += 1 if i == 1: # This jumps to the end of the iteration, not out of loop. continue i = 0 while i < 2: i += 1 if i == 1: break while True: break else: a = 1 while False: pass else: a = 1 tracer.stop() assert tracer.events == [ Binding(lineno=8, target=Symbol("i"), value="0"), Binding(lineno=10, target=Symbol("a"), value="0", sources={Symbol("i")}), Binding(lineno=11, target=Symbol("i"), value="1", sources={Symbol("i")}), JumpBackToLoopStart(lineno=11, jump_target=get_value({ "default": 12, "py37": 14 })), Binding(lineno=10, target=Symbol("a"), value="1", sources={Symbol("i")}), Binding(lineno=11, target=Symbol("i"), value="2", sources={Symbol("i")}), JumpBackToLoopStart(lineno=11, jump_target=get_value({ "default": 12, "py37": 14 })), ## Binding(lineno=13, target=Symbol("i"), value="0"), Binding(lineno=17, target=Symbol("i"), value="0"), Binding(lineno=19, target=Symbol("i"), value="1", sources={Symbol("i")}), JumpBackToLoopStart(lineno=20, jump_target=get_value({ "default": 54, "py37": 64 })), ## Binding(lineno=22, target=Symbol("i"), value="0"), Binding(lineno=24, target=Symbol("i"), value="1", sources={Symbol("i")}), JumpBackToLoopStart(lineno=26, jump_target=get_value({ "default": 78, "py37": 92 })), Binding(lineno=24, target=Symbol("i"), value="2", sources={Symbol("i")}), JumpBackToLoopStart(lineno=25, jump_target=get_value({ "default": 78, "py37": 92 })), ## Binding(lineno=28, target=Symbol("i"), value="0"), Binding(lineno=30, target=Symbol("i"), value="1", sources={Symbol("i")}), Binding(lineno=42, target=Symbol("a"), value="1"), ] assert tracer.loops == [ Loop( start_offset=get_value({ "default": 12, "py37": 14 }), end_offset=get_value({ "default": 32, "py37": 34 }), start_lineno=9, ), Loop( start_offset=get_value({ "default": 54, "py37": 64 }), end_offset=get_value({ "default": 70, "py37": 80 }), start_lineno=18, ), Loop( start_offset=get_value({ "default": 78, "py37": 92 }), end_offset=get_value({ "default": 102, "py37": 116 }), start_lineno=23, ), ] test_server.assert_frame_sent("test_while_loop")
def test_nested_loop(tracer, test_server): tracer.start() for i in range(2): for j in range(2): a = i + j tracer.stop() assert tracer.events == [ Binding(lineno=8, target=Symbol("i"), value="0"), Binding(lineno=9, target=Symbol("j"), value="0"), Binding(lineno=10, target=Symbol("a"), value="0", sources={Symbol("i"), Symbol("j")}), JumpBackToLoopStart(lineno=10, jump_target=get_value({ "default": 28, "py37": 32 })), Binding(lineno=9, target=Symbol("j"), value="1"), Binding(lineno=10, target=Symbol("a"), value="1", sources={Symbol("i"), Symbol("j")}), JumpBackToLoopStart(lineno=10, jump_target=get_value({ "default": 28, "py37": 32 })), JumpBackToLoopStart(lineno=10, jump_target=get_value({ "default": 16, "py37": 18 })), Binding(lineno=8, target=Symbol("i"), value="1"), Binding(lineno=9, target=Symbol("j"), value="0"), Binding(lineno=10, target=Symbol("a"), value="1", sources={Symbol("i"), Symbol("j")}), JumpBackToLoopStart(lineno=10, jump_target=get_value({ "default": 28, "py37": 32 })), Binding(lineno=9, target=Symbol("j"), value="1"), Binding(lineno=10, target=Symbol("a"), value="2", sources={Symbol("i"), Symbol("j")}), JumpBackToLoopStart(lineno=10, jump_target=get_value({ "default": 28, "py37": 32 })), JumpBackToLoopStart(lineno=10, jump_target=get_value({ "default": 16, "py37": 18 })), ] assert tracer.loops == [ Loop( start_offset=get_value({ "default": 28, "py37": 32 }), end_offset=get_value({ "default": 40, "py37": 44 }), start_lineno=9, ), Loop( start_offset=get_value({ "default": 16, "py37": 18 }), end_offset=get_value({ "default": 42, "py37": 48 }), start_lineno=8, ), ] test_server.assert_frame_sent("test_nested_loop")
def test_for_loop(tracer, check_golden_file): tracer.start() for i in range(2): # SETUP_LOOP (3.7), GET_ITER, FOR_ITER a = i # POP_BLOCK (3.7) for i in range(2): break # BREAK_LOOP (3.7), JUMP_ABSOLUTE (>=3.8) a = 1 for i in range(1): continue # CONTINUE_LOOP (3.7), JUMP_ABSOLUTE (>=3.8) a = 1 for i in range(2): if i == 0: # This jumps directly to FOR_ITER continue for i in range(2): if i == 1: break for i in range(1): break else: a = 1 for i in range(1): # One iteration loop. pass else: a = 1 tracer.stop() assert tracer.loops == [ Loop( start_offset=get_value({"default": 16, "py37": 18}), end_offset=get_value({"default": 24, "py37": 26}), start_lineno=8, end_lineno=9, ), Loop( start_offset=get_value({"default": 56, "py37": 64, "py310": 48}), end_offset=get_value({"default": 60, "py37": 68, "py310": 52}), start_lineno=15, end_lineno=16, ), Loop( start_offset=get_value({"default": 76, "py37": 88, "py310": 62}), end_offset=get_value({"default": 88, "py37": 100, "py310": 76}), start_lineno=19, end_lineno=21, ), Loop( start_offset=get_value({"default": 100, "py37": 116, "py310": 86}), end_offset=get_value({"default": 110, "py37": 126, "py310": 102}), start_lineno=23, # TODO: Correct lineno is 25, see if we can fix this for older versions. end_lineno=get_value({"default": 25, "py37": 24, "py38": 24, "py39": 24}), ), Loop( start_offset=get_value({"default": 148, "py37": 168, "py310": 132}), end_offset=get_value({"default": 152, "py37": 172, "py310": 136}), start_lineno=32, end_lineno=33, ), ]
def test_while_loop(tracer, check_golden_file): tracer.start() i = 0 while i < 2: a = i i += 1 i = 0 while i < 2: break # BREAK_LOOP (3.7), JUMP_ABSOLUTE (>=3.8) i = 0 while i < 1: i += 1 continue # CONTINUE_LOOP (3.7), JUMP_ABSOLUTE (>=3.8) i = 0 while i < 2: i += 1 if i == 1: # This jumps to the end of the iteration, not out of loop. continue i = 0 while i < 2: i += 1 if i == 1: break while True: break else: a = 1 while False: pass else: a = 1 tracer.stop() assert tracer.loops == [ Loop( start_offset=get_value({ "default": 12, "py37": 14, "py310": 20 }), end_offset=get_value({ "default": 32, "py37": 34, "py310": 38 }), start_lineno=get_value({ "default": 9, "py310": 10 }), end_lineno=11, ), Loop( start_offset=get_value({ "default": 54, "py37": 64, "py310": 58 }), end_offset=get_value({ "default": 70, "py37": 80, "py310": 74 }), start_lineno=18, end_lineno=20, ), Loop( start_offset=get_value({ "default": 78, "py37": 92, "py310": 80 }), end_offset=get_value({ "default": 102, "py37": 116, "py310": 104 }), start_lineno=23, end_lineno=26, ), ]