def test_recursion_decorator(trace): @trace def fib(n): if n <= 1: return n else: return fib(n - 1) + fib(n - 2) print(fib(3)) assert trace.events == [ InitialValue( lineno=7, target=Symbol("n"), value="3", repr="3", ), InitialValue( lineno=10, target=Symbol("fib"), value= '{"repr": "<function test_recursion_decorator.<locals>.fib>"}', repr="<function test_recursion_decorator.<locals>.fib>", ), Return( lineno=10, value="2", repr="2", sources={Symbol("fib"), Symbol("n")}, ), ]
def test_attribute(tracer, rpc_stub): class A: pass a1 = A() a2 = A() a2.y = 1 tracer.start() a1.x = a2 # STORE_ATTR a1.x.y = 2 # LOAD_ATTR, STORE_ATTR del a1.x # DELETE_ATTR tracer.stop() assert tracer.events == [ InitialValue( lineno=14, target=Symbol("a2"), value='{"y": 1}', repr="<test_attribute.test_attribute.<locals>.A object>", ), InitialValue( lineno=14, target=Symbol("a1"), value="{}", repr="<test_attribute.test_attribute.<locals>.A object>", ), Mutation( lineno=14, target=Symbol("a1"), sources={Symbol("a2"), Symbol("a1")}, value='{"x": {"y": 1}}', repr="<test_attribute.test_attribute.<locals>.A object>", ), Mutation( lineno=15, target=Symbol("a1"), sources={Symbol("a1")}, value='{"x": {"y": 2}}', repr="<test_attribute.test_attribute.<locals>.A object>", ), Mutation( lineno=16, target=Symbol("a1"), sources={Symbol("a1")}, value="{}", repr="<test_attribute.test_attribute.<locals>.A object>", ), ] from utils import assert_GetFrame assert_GetFrame(rpc_stub, "test_attribute")
def test_module(): assert tracer.events == [ InitialValue(target=Symbol("x"), value="1", lineno=-1), Deletion(target=Symbol("x"), lineno=8), InitialValue(target=Symbol("__annotations__"), value="{}", lineno=-1), Mutation( target=Symbol("__annotations__"), value='{"y":{"py/type":"builtins.int"}}', sources={Symbol("__annotations__") }, # `int` is a built-in so is excluded from sources. lineno=9, ), ]
def test_attribute(tracer, mocked_responses): class A: pass a1 = A() a2 = A() a2.y = 1 tracer.start() a1.x = a2 # STORE_ATTR a1.x.y = 2 # LOAD_ATTR, STORE_ATTR del a1.x # DELETE_ATTR tracer.stop() assert tracer.events == [ InitialValue( lineno=-1, target=Symbol("a2"), value='{"y":1}', repr="<test_attribute.test_attribute.<locals>.A object>", ), InitialValue( lineno=-1, target=Symbol("a1"), value="{}", repr="<test_attribute.test_attribute.<locals>.A object>", ), Mutation( lineno=14, target=Symbol("a1"), sources={Symbol("a2"), Symbol("a1")}, value='{"x":{"y":1}}', repr="<test_attribute.test_attribute.<locals>.A object>", ), Mutation( lineno=15, target=Symbol("a1"), sources={Symbol("a1")}, value='{"x":{"y":2}}', repr="<test_attribute.test_attribute.<locals>.A object>", ), Mutation( lineno=16, target=Symbol("a1"), sources={Symbol("a1")}, value="{}", repr="<test_attribute.test_attribute.<locals>.A object>", ), ]
def test_module(rpc_stub): assert tracer.events == [ InitialValue(target=Symbol("x"), value=1, lineno=10), Deletion(target=Symbol("x"), lineno=10), InitialValue(target=Symbol("__annotations__"), value={}, lineno=11), Mutation( target=Symbol("__annotations__"), value={"y": int}, sources={Symbol("__annotations__") }, # `int` is a built-in so is excluded from sources. lineno=11, ), ] assert_GetFrame(rpc_stub, "test_outside_func")
def test_decorator_multiple_times(trace, rpc_stub): @trace def func(b): a = b return a func(1) # Test that server wait does not block user code execution. trace._wait_for_termination() assert func(2) == 2 from cyberbrain import pprint pprint(trace.events) assert trace.events == [ InitialValue( lineno=21, target=Symbol("b"), value="1", ), Binding(lineno=21, target=Symbol("a"), value="1", sources={Symbol("b")}), Return(lineno=22, value="1", sources={Symbol("a")}), ] trace.server.stop()
def test_yield_from(trace, mocked_responses): def inner(): for i in range(2): yield i @trace def yield_from_function(): yield from inner() # CALL_FUNCTION, GET_YIELD_FROM_ITER, LOAD_CONST # The above line triggers two return events for sys.settrace for output in yield_from_function(): print(output) trace.stop() assert trace.events == [ InitialValue( lineno=75, target=Symbol("inner"), value='{"repr": "<function test_yield_from.<locals>.inner>"}', repr="<function test_yield_from.<locals>.inner>", ), Return( lineno=75, value="null", repr="None", sources=set(), ), ]
def test_unary_operations(tracer, mocked_responses): a = 1 tracer.start() b = +a # UNARY_POSITIVE b = -a # UNARY_NEGATIVE b = not a # UNARY_NOT b = ~a # UNARY_INVERT tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("a"), value="1", lineno=-1), Binding(target=Symbol("b"), value="1", sources={Symbol("a")}, lineno=9), Binding(target=Symbol("b"), value="-1", sources={Symbol("a")}, lineno=10), Binding(target=Symbol("b"), value="false", sources={Symbol("a")}, lineno=11), Binding(target=Symbol("b"), value="-2", sources={Symbol("a")}, lineno=12), ]
def test_unary_operations(tracer, rpc_stub): a = 1 tracer.start() b = +a # UNARY_POSITIVE b = -a # UNARY_NEGATIVE b = not a # UNARY_NOT b = ~a # UNARY_INVERT tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("a"), value=1, lineno=10), Binding(target=Symbol("b"), value=1, sources={Symbol("a")}, lineno=10), Binding(target=Symbol("b"), value=-1, sources={Symbol("a")}, lineno=11), Binding(target=Symbol("b"), value=False, sources={Symbol("a")}, lineno=12), Binding(target=Symbol("b"), value=-2, sources={Symbol("a")}, lineno=13), ] assert_GetFrame(rpc_stub, "test_unary_operations")
def test_mutation(tracer): text = "AAAA" tracer.start() lower_text = text.lower( ) # Test this line does not emit a mutation of `text`. tracer.stop() assert tracer.events == [ InitialValue( lineno=-1, target=Symbol("text"), value='"AAAA"', repr='"AAAA"', ), Binding( lineno=9, target=Symbol("lower_text"), value='"aaaa"', repr='"aaaa"', sources={Symbol("text")}, ), ]
def test_jump(tracer, rpc_stub): a = [] b = "b" c = "c" tracer.start() if a: # POP_JUMP_IF_FALSE pass # JUMP_FORWARD else: x = 1 if not a: # POP_JUMP_IF_TRUE x = 2 x = a != b != c # JUMP_IF_FALSE_OR_POP x = a == b or c # JUMP_IF_TRUE_OR_POP # TODO: Test JUMP_ABSOLUTE. This requires loop instructions to be Implemented. tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("a"), value=[], lineno=12), Binding(target=Symbol("x"), value=1, lineno=15), Binding(target=Symbol("x"), value=2, lineno=18), InitialValue(target=Symbol("b"), value="b", lineno=20), InitialValue(target=Symbol("c"), value="c", lineno=20), # This is a known defect. We have no way to know `x` comes from `a`, because # the result of `a != b` only determines whether to jump to execute `b != c` # I think it's fine though. Binding( target=Symbol("x"), value=True, sources={Symbol("b"), Symbol("c")}, lineno=20, ), # Same defect here. Binding(target=Symbol("x"), value="c", sources={Symbol("c")}, lineno=21), ] assert_GetFrame(rpc_stub, "test_jump")
def test_jump(tracer, mocked_responses): a = [] b = "b" c = "c" tracer.start() if a: # POP_JUMP_IF_FALSE pass # JUMP_FORWARD else: x = 1 if not a: # POP_JUMP_IF_TRUE x = 2 x = a != b != c # JUMP_IF_FALSE_OR_POP x = a == b or c # JUMP_IF_TRUE_OR_POP # TODO: Test JUMP_ABSOLUTE. This requires loop instructions to be Implemented. tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("a"), value="[]", lineno=-1), Binding(target=Symbol("x"), value="1", lineno=14), Binding(target=Symbol("x"), value="2", lineno=17), InitialValue(target=Symbol("b"), value='"b"', lineno=-1), InitialValue(target=Symbol("c"), value='"c"', lineno=-1), # This is a known defect. We have no way to know `x` comes from `a`, because # the result of `a != b` only determines whether to jump to execute `b != c` # I think it's fine though. Binding( target=Symbol("x"), value="true", sources={Symbol("b"), Symbol("c")}, lineno=19, ), # Same defect here. Binding(target=Symbol("x"), value='"c"', sources={Symbol("c")}, lineno=20), ]
def test_ref_outside(trace, mocked_responses): @trace def test_ref_outside_inner(): a = f() test_ref_outside_inner() assert trace.events == [ InitialValue(lineno=-1, target=Symbol("f"), value='{"repr": "<function f>"}'), Binding(lineno=11, target=Symbol("a"), value="1", sources={Symbol("f")}), Return(lineno=11, value="null", sources=set()), ]
def test_existing_variable_emit_initial_value(tracer, test_server): x = "foo" tracer.start() y = x tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("x"), value='"foo"', lineno=7), Binding(target=Symbol("y"), value='"foo"', sources={Symbol("x")}, lineno=7), ] test_server.assert_frame_sent("test_existing_variable_emit_initial_value")
def test_miscellaneous(tracer, test_server): a = "a" b = "b" c = "c" d = "d" e = [1, 2, 3] tracer.start() x = f"{a} {b:4} {c!r} {d!r:4}" # FORMAT_VALUE, BUILD_STRING x = a == b == c # ROT_THREE, _COMPARE_OP e[0] += e.pop() # DUP_TOP_TWO del e # DELETE_FAST global g x = g g = 1 # STORE_GLOBAL del g # DELETE_GLOBAL tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("a"), value='"a"', lineno=15), InitialValue(target=Symbol("b"), value='"b"', lineno=15), InitialValue(target=Symbol("c"), value='"c"', lineno=15), InitialValue(target=Symbol("d"), value='"d"', lineno=15), Binding( target=Symbol("x"), value="\"a b 'c' 'd' \"", sources={Symbol("a"), Symbol("b"), Symbol("d"), Symbol("c")}, lineno=15, ), Binding( target=Symbol("x"), value="false", sources={Symbol("a"), Symbol("b")}, lineno=16, ), InitialValue(target=Symbol("e"), value="[1, 2, 3]", lineno=17), Mutation(target=Symbol("e"), value="[1, 2]", sources={Symbol("e")}, lineno=17), Mutation(target=Symbol("e"), value="[4, 2]", sources={Symbol("e")}, lineno=17), Deletion(target=Symbol("e"), lineno=18), InitialValue(target=Symbol("g"), value="0", lineno=20), Binding(target=Symbol("x"), value="0", sources={Symbol("g")}, lineno=20), Binding(target=Symbol("g"), value="1", lineno=21), Deletion(target=Symbol("g"), lineno=22), ] test_server.assert_frame_sent("test_miscellaneous")
def test_existing_variable_emit_initial_value(tracer, mocked_responses): x = "foo" tracer.start() y = x tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("x"), value='"foo"', lineno=7), Binding(target=Symbol("y"), value='"foo"', sources={Symbol("x")}, lineno=7), ]
def test_ref_outside(trace, test_server): @trace def test_ref_outside_inner(): a = f() test_ref_outside_inner() assert trace.events == [ InitialValue(lineno=11, target=Symbol("f"), value='{"repr": "<function f>"}'), Binding(lineno=11, target=Symbol("a"), value="1", sources={Symbol("f")}), Return(lineno=11, value="null", sources=set()), ] test_server.assert_frame_sent("test_ref_outside_inner")
def test_miscellaneous(tracer, rpc_stub): a = "a" b = "b" c = "c" d = "d" e = [1, 2, 3] tracer.start() x = f"{a} {b:4} {c!r} {d!r:4}" # FORMAT_VALUE, BUILD_STRING x = a == b == c # ROT_THREE, _COMPARE_OP e[0] += e.pop() # DUP_TOP_TWO del e # DELETE_FAST global g x = g g = 1 # STORE_GLOBAL del g # DELETE_GLOBAL tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("a"), value="a", lineno=16), InitialValue(target=Symbol("b"), value="b", lineno=16), InitialValue(target=Symbol("c"), value="c", lineno=16), InitialValue(target=Symbol("d"), value="d", lineno=16), Binding( target=Symbol("x"), value="a b 'c' 'd' ", sources={Symbol("a"), Symbol("b"), Symbol("d"), Symbol("c")}, lineno=16, ), Binding( target=Symbol("x"), value=False, sources={Symbol("a"), Symbol("b")}, lineno=17, ), InitialValue(target=Symbol("e"), value=[1, 2, 3], lineno=18), Mutation(target=Symbol("e"), value=[1, 2], sources={Symbol("e")}, lineno=18), Mutation(target=Symbol("e"), value=[4, 2], sources={Symbol("e")}, lineno=18), Deletion(target=Symbol("e"), lineno=19), InitialValue(target=Symbol("g"), value=0, lineno=21), Binding(target=Symbol("x"), value=0, sources={Symbol("g")}, lineno=21), Binding(target=Symbol("g"), value=1, lineno=22), Deletion(target=Symbol("g"), lineno=23), ] assert_GetFrame(rpc_stub, "test_miscellaneous")
def test_existing_variable_emit_initial_value(tracer, rpc_stub): x = "foo" tracer.start() y = x tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("x"), value="foo", lineno=8), Binding(target=Symbol("y"), value="foo", sources={Symbol("x")}, lineno=8), ] assert_GetFrame(rpc_stub, "test_existing_variable_emit_initial_value")
def test_ref_outside(trace, rpc_stub): @trace def test_ref_outside_inner(): a = f() test_ref_outside_inner() assert trace.events == [ InitialValue(lineno=11, target=Symbol("f"), value=f), Binding(lineno=11, target=Symbol("a"), value=1, sources={Symbol("f")}), Return(lineno=11, value=None, sources=set()), ] from utils import assert_GetFrame assert_GetFrame(rpc_stub, "test_ref_outside_inner")
def test_while_jump_to_zero(trace): @trace def while_jump_to_zero(count): while count > 0: count -= 1 while_jump_to_zero(2) assert trace.events == [ InitialValue( lineno=103, target=Symbol("count"), value="2", repr="2", ), Binding( lineno=104, target=Symbol("count"), value="1", repr="1", sources={Symbol("count")}, ), JumpBackToLoopStart(lineno=104, jump_target=get_value({ "py37": 2, "default": 0 })), Binding( lineno=104, target=Symbol("count"), value="0", repr="0", sources={Symbol("count")}, ), JumpBackToLoopStart(lineno=104, jump_target=get_value({ "py37": 2, "default": 0 })), Return( lineno=104, value="null", repr="None", sources=set(), ), ]
def test_decorator_multiple_times(trace, mocked_responses): @trace def func(b): a = b return a func(1) assert func(2) == 2 assert trace.events == [ InitialValue( lineno=21, target=Symbol("b"), value="1", ), Binding(lineno=21, target=Symbol("a"), value="1", sources={Symbol("b")}), Return(lineno=22, value="1", sources={Symbol("a")}), ]
def test_recursion_tracer(tracer): def fib(n): return n if n <= 1 else fib(n - 1) + fib(n - 2) # tracer.stop can't be placed inside fib, because it will be called first by inner # calls. And tracer.start() has to be called in the same frame as tracer.stop(). tracer.start() print(fib(3)) tracer.stop() assert tracer.events == [ InitialValue( lineno=43, target=Symbol("fib"), value='{"repr": "<function test_recursion_tracer.<locals>.fib>"}', repr="<function test_recursion_tracer.<locals>.fib>", ) ]
def test_deref(tracer, mocked_responses): a = 1 def test_deref_func(): tracer.start() nonlocal a print(a) # LOAD_DEREF a = 2 # STORE_DEREF del a # DELETE_DEREF tracer.stop() test_deref_func() assert tracer.events == [ InitialValue(lineno=-1, target=Symbol("a"), value="1"), Binding(lineno=12, target=Symbol("a"), value="2", sources=set()), Deletion(lineno=13, target=Symbol("a")), ]
def test_deref(tracer, rpc_stub): a = 1 def test_deref_func(): tracer.start() nonlocal a print(a) # LOAD_DEREF a = 2 # STORE_DEREF del a # DELETE_DEREF tracer.stop() test_deref_func() assert tracer.events == [ InitialValue(lineno=12, target=Symbol("a"), value="1"), Binding(lineno=13, target=Symbol("a"), value="2", sources=set()), Deletion(lineno=14, target=Symbol("a")), ] assert_GetFrame(rpc_stub, "test_deref_func")
def test_call(tracer, mocked_responses): a = b = c = d = 1 counter = 0 tracer.start() def f(foo, bar, *args, **kwargs): nonlocal counter counter += 1 return counter x = f(a, b) # CALL_FUNCTION x = f(a, bar=b) # CALL_FUNCTION_KW x = f(a, b, *(c, d)) # BUILD_TUPLE_UNPACK_WITH_CALL, CALL_FUNCTION_EX(arg=0) x = f(a, *(b, c), **{"key": d}) # CALL_FUNCTION_EX(arg=1) # CALL_FUNCTION_EX, <3.9: BUILD_MAP_UNPACK_WITH_CALL, >=3.9: DICT_MERGE x = f(foo=a, **{"bar": b, "key": c}) tracer.stop() assert tracer.events == [ InitialValue(lineno=10, target=Symbol("counter"), value="0"), Binding( lineno=10, target=Symbol("f"), value='{"repr": "<function test_call.<locals>.f>"}', sources={Symbol("counter")}, ), InitialValue(lineno=15, target=Symbol("a"), value="1"), InitialValue(lineno=15, target=Symbol("b"), value="1"), Binding( lineno=15, target=Symbol("x"), value="1", sources={Symbol("a"), Symbol("b"), Symbol("f")}, ), Binding( lineno=16, target=Symbol("x"), value="2", sources={Symbol("a"), Symbol("b"), Symbol("f")}, ), InitialValue(lineno=17, target=Symbol("c"), value="1"), InitialValue(lineno=17, target=Symbol("d"), value="1"), Binding( lineno=17, target=Symbol("x"), value="3", sources={ Symbol("d"), Symbol("f"), Symbol("a"), Symbol("c"), Symbol("b") }, ), Binding( lineno=18, target=Symbol("x"), value="4", sources={ Symbol("d"), Symbol("f"), Symbol("a"), Symbol("c"), Symbol("b") }, ), Binding( lineno=21, target=Symbol("x"), value="5", sources={Symbol("a"), Symbol("c"), Symbol("b"), Symbol("f")}, ), ]
def test_call(tracer, rpc_stub): a = b = c = d = 1 counter = 0 tracer.start() def f(foo, bar, *args, **kwargs): nonlocal counter counter += 1 return counter x = f(a, b) # CALL_FUNCTION x = f(a, bar=b) # CALL_FUNCTION_KW x = f(a, b, *(c, d)) # BUILD_TUPLE_UNPACK_WITH_CALL, CALL_FUNCTION_EX(arg=0) x = f(a, *(b, c), **{"key": d}) # CALL_FUNCTION_EX(arg=1) x = f(foo=a, **{ "bar": b, "key": c }) # BUILD_MAP_UNPACK_WITH_CALL, CALL_FUNCTION_EX tracer.stop() assert tracer.events == [ InitialValue(lineno=10, target=Symbol("counter"), value="0"), Binding( lineno=10, target=Symbol("f"), value='{"repr": "<function test_call.<locals>.f>"}', sources={Symbol("counter")}, ), InitialValue(lineno=15, target=Symbol("a"), value="1"), InitialValue(lineno=15, target=Symbol("b"), value="1"), Binding( lineno=15, target=Symbol("x"), value="1", sources={Symbol("a"), Symbol("b"), Symbol("f")}, ), Binding( lineno=16, target=Symbol("x"), value="2", sources={Symbol("a"), Symbol("b"), Symbol("f")}, ), InitialValue(lineno=17, target=Symbol("c"), value="1"), InitialValue(lineno=17, target=Symbol("d"), value="1"), Binding( lineno=17, target=Symbol("x"), value="3", sources={ Symbol("d"), Symbol("f"), Symbol("a"), Symbol("c"), Symbol("b") }, ), Binding( lineno=18, target=Symbol("x"), value="4", sources={ Symbol("d"), Symbol("f"), Symbol("a"), Symbol("c"), Symbol("b") }, ), Binding( lineno=19, target=Symbol("x"), value="5", sources={Symbol("a"), Symbol("c"), Symbol("b"), Symbol("f")}, ), ] from utils import assert_GetFrame assert_GetFrame(rpc_stub, "test_call")
def test_inplace_operations(tracer, test_server): a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = a10 = a11 = a12 = 2 b = 2 tracer.start() a1 **= b # INPLACE_POWER a2 *= b # INPLACE_MULTIPLY a3 //= b # INPLACE_FLOOR_DIVIDE a4 /= b # INPLACE_TRUE_DIVIDE a5 %= b # INPLACE_MODULO a6 += b # INPLACE_ADD a7 -= b # INPLACE_SUBTRACT a8 <<= b # INPLACE_LSHIFT a9 >>= b # INPLACE_RSHIFT a10 &= b # INPLACE_AND a11 ^= b # INPLACE_XOR a12 |= b # INPLACE_OR tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("a1"), value="2", lineno=10), InitialValue(target=Symbol("b"), value="2", lineno=10), Binding( target=Symbol("a1"), value="4", sources={Symbol("a1"), Symbol("b")}, lineno=10, ), InitialValue(target=Symbol("a2"), value="2", lineno=11), Binding( target=Symbol("a2"), value="4", sources={Symbol("a2"), Symbol("b")}, lineno=11, ), InitialValue(target=Symbol("a3"), value="2", lineno=12), Binding( target=Symbol("a3"), value="1", sources={Symbol("a3"), Symbol("b")}, lineno=12, ), InitialValue(target=Symbol("a4"), value="2", lineno=13), Binding( target=Symbol("a4"), value="1.0", sources={Symbol("a4"), Symbol("b")}, lineno=13, ), InitialValue(target=Symbol("a5"), value="2", lineno=14), Binding( target=Symbol("a5"), value="0", sources={Symbol("a5"), Symbol("b")}, lineno=14, ), InitialValue(target=Symbol("a6"), value="2", lineno=15), Binding( target=Symbol("a6"), value="4", sources={Symbol("a6"), Symbol("b")}, lineno=15, ), InitialValue(target=Symbol("a7"), value="2", lineno=16), Binding( target=Symbol("a7"), value="0", sources={Symbol("a7"), Symbol("b")}, lineno=16, ), InitialValue(target=Symbol("a8"), value="2", lineno=17), Binding( target=Symbol("a8"), value="8", sources={Symbol("a8"), Symbol("b")}, lineno=17, ), InitialValue(target=Symbol("a9"), value="2", lineno=18), Binding( target=Symbol("a9"), value="0", sources={Symbol("a9"), Symbol("b")}, lineno=18, ), InitialValue(target=Symbol("a10"), value="2", lineno=19), Binding( target=Symbol("a10"), value="2", sources={Symbol("a10"), Symbol("b")}, lineno=19, ), InitialValue(target=Symbol("a11"), value="2", lineno=20), Binding( target=Symbol("a11"), value="0", sources={Symbol("a11"), Symbol("b")}, lineno=20, ), InitialValue(target=Symbol("a12"), value="2", lineno=21), Binding( target=Symbol("a12"), value="2", sources={Symbol("a12"), Symbol("b")}, lineno=21, ), ] test_server.assert_frame_sent("test_inplace_operations")
def test_container(tracer, test_server): a = b = 1 c = 2 e = 0 tracer.start() d = [a, b] # BUILD_LIST d = (a, b) # BUILD_TUPLE d = {a, b} # BUILD_SET d = {a: b} # BUILD_MAP d = {1: a, 2: b} # BUILD_CONST_KEY_MAP d[a] = c # STORE_SUBSCR del d[a] # DELETE_SUBSCR d = [a, b, c][e:c] # BUILD_SLICE,[1,1,2][0:2] d = [b, b, c][e:c:a] # BUILD_SLICE,[1,1,2][0:2:1] os.environ["foo"] = "bar" # STORE_SUBSCR without emitting any event. tracer.stop() assert tracer.events == [ InitialValue(target=Symbol("a"), value="1", lineno=13), InitialValue(target=Symbol("b"), value="1", lineno=13), Binding( target=Symbol("d"), value="[1,1]", sources={Symbol("a"), Symbol("b")}, lineno=13, ), Binding( target=Symbol("d"), value="[1,1]", sources={Symbol("a"), Symbol("b")}, lineno=14, ), Binding( target=Symbol("d"), value="[1]", sources={Symbol("a"), Symbol("b")}, lineno=15, ), Binding( target=Symbol("d"), value='{"1":1}', sources={Symbol("a"), Symbol("b")}, lineno=16, ), Binding( target=Symbol("d"), value='{"1":1,"2":1}', sources={Symbol("a"), Symbol("b")}, lineno=17, ), InitialValue(target=Symbol("c"), value="2", lineno=18), Mutation( target=Symbol("d"), value='{"1":2,"2":1}', sources={Symbol("d"), Symbol("a"), Symbol("c")}, lineno=18, ), Mutation( target=Symbol("d"), value='{"2":1}', sources={Symbol("d"), Symbol("a")}, lineno=19, ), InitialValue(target=Symbol("e"), value="0", lineno=20), Binding( target=Symbol("d"), value="[1,1]", sources={Symbol("a"), Symbol("b"), Symbol("c"), Symbol("e")}, lineno=20, ), Binding( target=Symbol("d"), value="[1,1]", sources={Symbol("a"), Symbol("b"), Symbol("c"), Symbol("e")}, lineno=21, ), ] test_server.assert_frame_sent("test_container")
def test_with(tracer, mocked_responses): class ContextManagerNoReturn: def __enter__(self): pass def __exit__(self, *unused): pass class ContextManagerWithReturn: def __enter__(self): return 2 def __exit__(self, *unused): pass tracer.start() with ContextManagerNoReturn( ): # SETUP_WITH,WITH_CLEANUP_START,WITH_CLEANUP_FINISH a = 1 with ContextManagerWithReturn() as b: pass with ContextManagerWithReturn() as c, ContextManagerNoReturn() as d: pass with ContextManagerWithReturn() as e: with ContextManagerWithReturn() as f: pass with ContextManagerNoReturn(): try: g = 1 raise RuntimeError except RuntimeError: pass for i in range(1): with ContextManagerNoReturn(): continue tracer.stop() expected_events = [ InitialValue( lineno=21, target=Symbol("ContextManagerNoReturn"), value= '{"py/type":"test_with.test_with.<locals>.ContextManagerNoReturn"}', ), Binding(lineno=22, target=Symbol("a"), value="1", sources=set()), InitialValue( lineno=24, target=Symbol("ContextManagerWithReturn"), value= '{"py/type":"test_with.test_with.<locals>.ContextManagerWithReturn"}', ), Binding( lineno=24, target=Symbol("b"), value="2", sources={Symbol("ContextManagerWithReturn")}, ), Binding( lineno=27, target=Symbol("c"), value="2", sources={Symbol("ContextManagerWithReturn")}, ), Binding( lineno=27, target=Symbol("d"), value="null", sources={Symbol("ContextManagerNoReturn")}, ), Binding( lineno=30, target=Symbol("e"), value="2", sources={Symbol("ContextManagerWithReturn")}, ), Binding( lineno=31, target=Symbol("f"), value="2", sources={Symbol("ContextManagerWithReturn")}, ), Binding(lineno=36, target=Symbol("g"), value="1", sources=set()), Binding(lineno=41, target=Symbol("i"), value="0", sources=set()), ] from utils import python_version, get_value if python_version >= "py38": expected_events.append( JumpBackToLoopStart(lineno=43, jump_target=get_value({ "py38": 208, "default": 352 }))) assert tracer.events == expected_events