def test_setlineno(self): # x = 7 # y = 8 # z = 9 code = Bytecode() code.first_lineno = 3 code.extend([ Instr("LOAD_CONST", 7), Instr("STORE_NAME", "x"), SetLineno(4), Instr("LOAD_CONST", 8), Instr("STORE_NAME", "y"), SetLineno(5), Instr("LOAD_CONST", 9), Instr("STORE_NAME", "z"), ]) concrete = code.to_concrete_bytecode() self.assertEqual(concrete.consts, [7, 8, 9]) self.assertEqual(concrete.names, ["x", "y", "z"]) self.assertListEqual( list(concrete), [ ConcreteInstr("LOAD_CONST", 0, lineno=3), ConcreteInstr("STORE_NAME", 0, lineno=3), ConcreteInstr("LOAD_CONST", 1, lineno=4), ConcreteInstr("STORE_NAME", 1, lineno=4), ConcreteInstr("LOAD_CONST", 2, lineno=5), ConcreteInstr("STORE_NAME", 2, lineno=5), ], )
def test_get_jump_target(self): jump_abs = ConcreteInstr("JUMP_ABSOLUTE", 3) self.assertEqual(jump_abs.get_jump_target(100), 3) jump_forward = ConcreteInstr("JUMP_FORWARD", 5) self.assertEqual(jump_forward.get_jump_target(10), 16 if OFFSET_AS_INSTRUCTION else 17)
def test_get_jump_target(self): jump_abs = ConcreteInstr("JUMP_ABSOLUTE", 3) self.assertEqual(jump_abs.get_jump_target(100), 3) jump_forward = ConcreteInstr("JUMP_FORWARD", 5) self.assertEqual(jump_forward.get_jump_target(10), 17 if WORDCODE else 18)
def test_to_code_lnotab(self): # x = 7 # y = 8 # z = 9 concrete = ConcreteBytecode() concrete.consts = [7, 8, 9] concrete.names = ["x", "y", "z"] concrete.first_lineno = 3 concrete.extend([ ConcreteInstr("LOAD_CONST", 0), ConcreteInstr("STORE_NAME", 0), SetLineno(4), ConcreteInstr("LOAD_CONST", 1), ConcreteInstr("STORE_NAME", 1), SetLineno(5), ConcreteInstr("LOAD_CONST", 2), ConcreteInstr("STORE_NAME", 2), ]) code = concrete.to_code() if WORDCODE: expected = b"d\x00Z\x00d\x01Z\x01d\x02Z\x02" else: expected = (b"d\x00\x00" b"Z\x00\x00" b"d\x01\x00" b"Z\x01\x00" b"d\x02\x00" b"Z\x02\x00") self.assertEqual(code.co_code, expected) self.assertEqual(code.co_firstlineno, 3) self.assertEqual( code.co_lnotab, b"\x04\x01\x04\x01" if WORDCODE else b"\x06\x01\x06\x01")
def test_setlineno(self): # x = 7 # y = 8 # z = 9 concrete = ConcreteBytecode() concrete.consts = [7, 8, 9] concrete.names = ["x", "y", "z"] concrete.first_lineno = 3 concrete.extend([ ConcreteInstr("LOAD_CONST", 0), ConcreteInstr("STORE_NAME", 0), SetLineno(4), ConcreteInstr("LOAD_CONST", 1), ConcreteInstr("STORE_NAME", 1), SetLineno(5), ConcreteInstr("LOAD_CONST", 2), ConcreteInstr("STORE_NAME", 2), ]) code = concrete.to_bytecode() self.assertEqual( code, [ Instr("LOAD_CONST", 7, lineno=3), Instr("STORE_NAME", "x", lineno=3), Instr("LOAD_CONST", 8, lineno=4), Instr("STORE_NAME", "y", lineno=4), Instr("LOAD_CONST", 9, lineno=5), Instr("STORE_NAME", "z", lineno=5), ], )
def test_load_classderef(self): concrete = ConcreteBytecode() concrete.cellvars = ["__class__"] concrete.freevars = ["__class__"] concrete.extend([ ConcreteInstr("LOAD_CLASSDEREF", 1), ConcreteInstr("STORE_DEREF", 1) ]) bytecode = concrete.to_bytecode() self.assertEqual(bytecode.freevars, ["__class__"]) self.assertEqual(bytecode.cellvars, ["__class__"]) self.assertEqual( list(bytecode), [ Instr("LOAD_CLASSDEREF", FreeVar("__class__"), lineno=1), Instr("STORE_DEREF", FreeVar("__class__"), lineno=1), ], ) concrete = bytecode.to_concrete_bytecode() self.assertEqual(concrete.freevars, ["__class__"]) self.assertEqual(concrete.cellvars, ["__class__"]) self.assertEqual( list(concrete), [ ConcreteInstr("LOAD_CLASSDEREF", 1, lineno=1), ConcreteInstr("STORE_DEREF", 1, lineno=1), ], ) code = concrete.to_code() self.assertEqual(code.co_freevars, ("__class__", )) self.assertEqual(code.co_cellvars, ("__class__", )) self.assertEqual( code.co_code, b"\x94\x01\x89\x01", )
def test_async_gen_flags(self): # Test inference in the presence of pre-existing flags for is_async in (None, True): # Infer generator code = ConcreteBytecode() code.append(ConcreteInstr("YIELD_VALUE")) for f, expected in ( (CompilerFlags.COROUTINE, CompilerFlags.ASYNC_GENERATOR), (CompilerFlags.ASYNC_GENERATOR, CompilerFlags.ASYNC_GENERATOR), (CompilerFlags.ITERABLE_COROUTINE, CompilerFlags.ITERABLE_COROUTINE), ): code.flags = CompilerFlags(f) code.update_flags(is_async=is_async) self.assertTrue(bool(code.flags & expected)) # Infer coroutine code = ConcreteBytecode() code.append(ConcreteInstr("YIELD_FROM")) for f, expected in ( (CompilerFlags.COROUTINE, CompilerFlags.COROUTINE), (CompilerFlags.ASYNC_GENERATOR, CompilerFlags.COROUTINE), (CompilerFlags.ITERABLE_COROUTINE, CompilerFlags.ITERABLE_COROUTINE), ): code.flags = CompilerFlags(f) code.update_flags(is_async=is_async) self.assertTrue(bool(code.flags & expected)) # Crash on ITERABLE_COROUTINE with async bytecode code = ConcreteBytecode() code.append(ConcreteInstr("GET_AWAITABLE")) code.flags = CompilerFlags(CompilerFlags.ITERABLE_COROUTINE) with self.assertRaises(ValueError): code.update_flags(is_async=is_async)
def test_jumps(self): # if test: # x = 12 # else: # x = 37 code = Bytecode() label_else = Label() label_return = Label() code.extend([ Instr("LOAD_NAME", "test", lineno=1), Instr("POP_JUMP_IF_FALSE", label_else), Instr("LOAD_CONST", 12, lineno=2), Instr("STORE_NAME", "x"), Instr("JUMP_FORWARD", label_return), label_else, Instr("LOAD_CONST", 37, lineno=4), Instr("STORE_NAME", "x"), label_return, Instr("LOAD_CONST", None, lineno=4), Instr("RETURN_VALUE"), ]) code = code.to_concrete_bytecode() expected = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("POP_JUMP_IF_FALSE", 5 if OFFSET_AS_INSTRUCTION else 10, lineno=1), ConcreteInstr("LOAD_CONST", 0, lineno=2), ConcreteInstr("STORE_NAME", 1, lineno=2), ConcreteInstr("JUMP_FORWARD", 2 if OFFSET_AS_INSTRUCTION else 4, lineno=2), ConcreteInstr("LOAD_CONST", 1, lineno=4), ConcreteInstr("STORE_NAME", 1, lineno=4), ConcreteInstr("LOAD_CONST", 2, lineno=4), ConcreteInstr("RETURN_VALUE", lineno=4), ] self.assertListEqual(list(code), expected) self.assertListEqual(code.consts, [12, 37, None]) self.assertListEqual(code.names, ["test", "x"]) self.assertListEqual(code.varnames, [])
def test_extended_lnotab(self): # x = 7 # 200 blank lines # y = 8 concrete = ConcreteBytecode([ ConcreteInstr("LOAD_CONST", 0), SetLineno(1 + 128), ConcreteInstr("STORE_NAME", 0), # line number goes backward! SetLineno(1 + 129), ConcreteInstr("LOAD_CONST", 1), SetLineno(1), ConcreteInstr("STORE_NAME", 1), ]) concrete.consts = [7, 8] concrete.names = ["x", "y"] concrete.first_lineno = 1 code = concrete.to_code() expected = b"d\x00Z\x00d\x01Z\x01" self.assertEqual(code.co_code, expected) self.assertEqual(code.co_firstlineno, 1) self.assertEqual(code.co_lnotab, b"\x02\x7f\x00\x01\x02\x01\x02\x80\x00\xff")
def test_flag_inference(self): # Check no loss of non-infered flags code = ControlFlowGraph() code.flags |= ( CompilerFlags.NEWLOCALS | CompilerFlags.VARARGS | CompilerFlags.VARKEYWORDS | CompilerFlags.NESTED | CompilerFlags.FUTURE_GENERATOR_STOP ) code.update_flags() for f in ( CompilerFlags.NEWLOCALS, CompilerFlags.VARARGS, CompilerFlags.VARKEYWORDS, CompilerFlags.NESTED, CompilerFlags.NOFREE, CompilerFlags.OPTIMIZED, CompilerFlags.FUTURE_GENERATOR_STOP, ): self.assertTrue(bool(code.flags & f)) # Infer optimized and nofree code = Bytecode() flags = infer_flags(code) self.assertTrue(bool(flags & CompilerFlags.OPTIMIZED)) self.assertTrue(bool(flags & CompilerFlags.NOFREE)) code.append(ConcreteInstr("STORE_NAME", 1)) flags = infer_flags(code) self.assertFalse(bool(flags & CompilerFlags.OPTIMIZED)) self.assertTrue(bool(flags & CompilerFlags.NOFREE)) code.append(ConcreteInstr("STORE_DEREF", 2)) code.update_flags() self.assertFalse(bool(code.flags & CompilerFlags.OPTIMIZED)) self.assertFalse(bool(code.flags & CompilerFlags.NOFREE))
def test_extended_arg(self): # Create a code object from arbitrary bytecode co_code = b"\x90\x12\x904\x90\xabd\xcd" if WORDCODE else b"\x904\x12d\xcd\xab" code = get_code("x=1") args = ( (code.co_argcount,) if sys.version_info < (3, 8) else (code.co_argcount, code.co_posonlyargcount) ) args += ( code.co_kwonlyargcount, code.co_nlocals, code.co_stacksize, code.co_flags, co_code, code.co_consts, code.co_names, code.co_varnames, code.co_filename, code.co_name, code.co_firstlineno, code.co_lnotab, code.co_freevars, code.co_cellvars, ) code = types.CodeType(*args) # without EXTENDED_ARG opcode bytecode = ConcreteBytecode.from_code(code) self.assertListEqual( list(bytecode), [ConcreteInstr("LOAD_CONST", 0x1234ABCD, lineno=1)] ) # with EXTENDED_ARG opcode bytecode = ConcreteBytecode.from_code(code, extended_arg=True) if WORDCODE: expected = [ ConcreteInstr("EXTENDED_ARG", 0x12, lineno=1), ConcreteInstr("EXTENDED_ARG", 0x34, lineno=1), ConcreteInstr("EXTENDED_ARG", 0xAB, lineno=1), ConcreteInstr("LOAD_CONST", 0xCD, lineno=1), ] else: expected = [ ConcreteInstr("EXTENDED_ARG", 0x1234, lineno=1), ConcreteInstr("LOAD_CONST", 0xABCD, lineno=1), ] self.assertListEqual(list(bytecode), expected)
def test_async_gen_no_flag_is_async_True(self): # Test inference when we request an async function # Force coroutine code = ConcreteBytecode() code.update_flags(is_async=True) self.assertTrue(bool(code.flags & CompilerFlags.COROUTINE)) # Infer coroutine or async generator for i, expected in ( ("YIELD_VALUE", CompilerFlags.ASYNC_GENERATOR), ("YIELD_FROM", CompilerFlags.COROUTINE), ): code = ConcreteBytecode() code.append(ConcreteInstr(i)) code.update_flags(is_async=True) self.assertTrue(bool(code.flags & expected))
def test_disassemble(self): code = b"\t\x00d\x03" instr = ConcreteInstr.disassemble(1, code, 0) self.assertEqual(instr, ConcreteInstr("NOP", lineno=1)) instr = ConcreteInstr.disassemble(2, code, 1 if OFFSET_AS_INSTRUCTION else 2) self.assertEqual(instr, ConcreteInstr("LOAD_CONST", 3, lineno=2)) code = b"\x90\x12\x904\x90\xabd\xcd" instr = ConcreteInstr.disassemble(3, code, 0) self.assertEqual(instr, ConcreteInstr("EXTENDED_ARG", 0x12, lineno=3))
def test_label2(self): bytecode = Bytecode() label = Label() bytecode.extend([ Instr("LOAD_NAME", "test", lineno=1), Instr("POP_JUMP_IF_FALSE", label), Instr("LOAD_CONST", 5, lineno=2), Instr("STORE_NAME", "x"), Instr("JUMP_FORWARD", label), Instr("LOAD_CONST", 7, lineno=4), Instr("STORE_NAME", "x"), label, Instr("LOAD_CONST", None), Instr("RETURN_VALUE"), ]) concrete = bytecode.to_concrete_bytecode() expected = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("POP_JUMP_IF_FALSE", 7 if OFFSET_AS_INSTRUCTION else 14, lineno=1), ConcreteInstr("LOAD_CONST", 0, lineno=2), ConcreteInstr("STORE_NAME", 1, lineno=2), ConcreteInstr("JUMP_FORWARD", 2 if OFFSET_AS_INSTRUCTION else 4, lineno=2), ConcreteInstr("LOAD_CONST", 1, lineno=4), ConcreteInstr("STORE_NAME", 1, lineno=4), ConcreteInstr("LOAD_CONST", 2, lineno=4), ConcreteInstr("RETURN_VALUE", lineno=4), ] self.assertListEqual(list(concrete), expected) self.assertListEqual(concrete.consts, [5, 7, None]) self.assertListEqual(concrete.names, ["test", "x"]) self.assertListEqual(concrete.varnames, [])
def test_disassemble(self): code = b"\t\x00d\x03" if WORDCODE else b"\td\x03\x00" instr = ConcreteInstr.disassemble(1, code, 0) self.assertEqual(instr, ConcreteInstr("NOP", lineno=1)) instr = ConcreteInstr.disassemble(2, code, 2 if WORDCODE else 1) self.assertEqual(instr, ConcreteInstr("LOAD_CONST", 3, lineno=2)) code = b"\x90\x12\x904\x90\xabd\xcd" if WORDCODE else b"\x904\x12d\xcd\xab" instr = ConcreteInstr.disassemble(3, code, 0) self.assertEqual( instr, ConcreteInstr("EXTENDED_ARG", 0x12 if WORDCODE else 0x1234, lineno=3) )
def test_copy(self): concrete = ConcreteBytecode() concrete.first_lineno = 3 concrete.consts = [7, 8, 9] concrete.names = ["x", "y", "z"] concrete.extend([ ConcreteInstr("LOAD_CONST", 0), ConcreteInstr("STORE_NAME", 0), SetLineno(4), ConcreteInstr("LOAD_CONST", 1), ConcreteInstr("STORE_NAME", 1), SetLineno(5), ConcreteInstr("LOAD_CONST", 2), ConcreteInstr("STORE_NAME", 2), ]) self.assertEqual(concrete, concrete.copy())
def test_set_attr(self): instr = ConcreteInstr("LOAD_CONST", 5, lineno=12) # operator name instr.name = "LOAD_FAST" self.assertEqual(instr.name, "LOAD_FAST") self.assertEqual(instr.opcode, 124) self.assertRaises(TypeError, setattr, instr, "name", 3) self.assertRaises(ValueError, setattr, instr, "name", "xxx") # operator code instr.opcode = 100 self.assertEqual(instr.name, "LOAD_CONST") self.assertEqual(instr.opcode, 100) self.assertRaises(ValueError, setattr, instr, "opcode", -12) self.assertRaises(TypeError, setattr, instr, "opcode", "abc") # extended argument instr.arg = 0x1234ABCD self.assertEqual(instr.arg, 0x1234ABCD) self.assertEqual(instr.size, 8) # small argument instr.arg = 0 self.assertEqual(instr.arg, 0) self.assertEqual(instr.size, 2) # invalid argument self.assertRaises(ValueError, setattr, instr, "arg", -1) self.assertRaises(ValueError, setattr, instr, "arg", 2147483647 + 1) # size attribute is read-only self.assertRaises(AttributeError, setattr, instr, "size", 3) # lineno instr.lineno = 33 self.assertEqual(instr.lineno, 33) self.assertRaises(TypeError, setattr, instr, "lineno", 1.0) self.assertRaises(ValueError, setattr, instr, "lineno", -1)
def test_extended_lnotab2(self): # x = 7 # 200 blank lines # y = 8 base_code = compile("x = 7" + "\n" * 200 + "y = 8", "", "exec") concrete = ConcreteBytecode([ ConcreteInstr("LOAD_CONST", 0), ConcreteInstr("STORE_NAME", 0), SetLineno(201), ConcreteInstr("LOAD_CONST", 1), ConcreteInstr("STORE_NAME", 1), ConcreteInstr("LOAD_CONST", 2), ConcreteInstr("RETURN_VALUE"), ]) concrete.consts = [None, 7, 8] concrete.names = ["x", "y"] concrete.first_lineno = 1 code = concrete.to_code() self.assertEqual(code.co_code, base_code.co_code) self.assertEqual(code.co_firstlineno, base_code.co_firstlineno) self.assertEqual(code.co_lnotab, base_code.co_lnotab) if sys.version_info >= (3, 10): self.assertEqual(code.co_linetable, base_code.co_linetable)
def test_extended_arg_make_function(self): if (3, 9) <= sys.version_info < (3, 10): from _pydevd_frame_eval.vendored.bytecode.tests.util_annotation import get_code as get_code_future code_obj = get_code_future(""" def foo(x: int, y: int): pass """) else: code_obj = get_code(""" def foo(x: int, y: int): pass """) # without EXTENDED_ARG concrete = ConcreteBytecode.from_code(code_obj) if sys.version_info >= (3, 10): func_code = concrete.consts[2] names = ["int", "foo"] consts = ["x", "y", func_code, "foo", None] const_offset = 1 name_offset = 1 first_instrs = [ ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_CONST", 1, lineno=1), ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("BUILD_TUPLE", 4, lineno=1), ] elif (sys.version_info >= (3, 7) and concrete.flags & CompilerFlags.FUTURE_ANNOTATIONS): func_code = concrete.consts[2] names = ["foo"] consts = ["int", ("x", "y"), func_code, "foo", None] const_offset = 1 name_offset = 0 first_instrs = [ ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("LOAD_CONST", 0 + const_offset, lineno=1), ConcreteInstr("BUILD_CONST_KEY_MAP", 2, lineno=1), ] else: func_code = concrete.consts[1] names = ["int", "foo"] consts = [("x", "y"), func_code, "foo", None] const_offset = 0 name_offset = 1 first_instrs = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_CONST", 0 + const_offset, lineno=1), ConcreteInstr("BUILD_CONST_KEY_MAP", 2, lineno=1), ] self.assertEqual(concrete.names, names) self.assertEqual(concrete.consts, consts) expected = first_instrs + [ ConcreteInstr("LOAD_CONST", 1 + const_offset, lineno=1), ConcreteInstr("LOAD_CONST", 2 + const_offset, lineno=1), ConcreteInstr("MAKE_FUNCTION", 4, lineno=1), ConcreteInstr("STORE_NAME", name_offset, lineno=1), ConcreteInstr("LOAD_CONST", 3 + const_offset, lineno=1), ConcreteInstr("RETURN_VALUE", lineno=1), ] self.assertListEqual(list(concrete), expected) # with EXTENDED_ARG concrete = ConcreteBytecode.from_code(code_obj, extended_arg=True) # With future annotation the int annotation is stringified and # stored as constant this the default behavior under Python 3.10 if sys.version_info >= (3, 10): func_code = concrete.consts[2] names = ["int", "foo"] consts = ["x", "y", func_code, "foo", None] elif concrete.flags & CompilerFlags.FUTURE_ANNOTATIONS: func_code = concrete.consts[2] names = ["foo"] consts = ["int", ("x", "y"), func_code, "foo", None] else: func_code = concrete.consts[1] names = ["int", "foo"] consts = [("x", "y"), func_code, "foo", None] self.assertEqual(concrete.names, names) self.assertEqual(concrete.consts, consts) self.assertListEqual(list(concrete), expected)
def test_legalize(self): concrete = ConcreteBytecode() concrete.first_lineno = 3 concrete.consts = [7, 8, 9] concrete.names = ["x", "y", "z"] concrete.extend([ ConcreteInstr("LOAD_CONST", 0), ConcreteInstr("STORE_NAME", 0), ConcreteInstr("LOAD_CONST", 1, lineno=4), ConcreteInstr("STORE_NAME", 1), SetLineno(5), ConcreteInstr("LOAD_CONST", 2, lineno=6), ConcreteInstr("STORE_NAME", 2), ]) concrete.legalize() self.assertListEqual( list(concrete), [ ConcreteInstr("LOAD_CONST", 0, lineno=3), ConcreteInstr("STORE_NAME", 0, lineno=3), ConcreteInstr("LOAD_CONST", 1, lineno=4), ConcreteInstr("STORE_NAME", 1, lineno=4), ConcreteInstr("LOAD_CONST", 2, lineno=5), ConcreteInstr("STORE_NAME", 2, lineno=5), ], )
def test_to_bytecode_consts(self): # x = -0.0 # x = +0.0 # # code optimized by the CPython 3.6 peephole optimizer which emits # duplicated constants (0.0 is twice in consts). code = ConcreteBytecode() code.consts = [0.0, None, -0.0, 0.0] code.names = ["x", "y"] code.extend([ ConcreteInstr("LOAD_CONST", 2, lineno=1), ConcreteInstr("STORE_NAME", 0, lineno=1), ConcreteInstr("LOAD_CONST", 3, lineno=2), ConcreteInstr("STORE_NAME", 1, lineno=2), ConcreteInstr("LOAD_CONST", 1, lineno=2), ConcreteInstr("RETURN_VALUE", lineno=2), ]) code = code.to_bytecode().to_concrete_bytecode() # the conversion changes the constant order: the order comes from # the order of LOAD_CONST instructions self.assertEqual(code.consts, [-0.0, 0.0, None]) code.names = ["x", "y"] self.assertListEqual( list(code), [ ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("STORE_NAME", 0, lineno=1), ConcreteInstr("LOAD_CONST", 1, lineno=2), ConcreteInstr("STORE_NAME", 1, lineno=2), ConcreteInstr("LOAD_CONST", 2, lineno=2), ConcreteInstr("RETURN_VALUE", lineno=2), ], )
def test_size(self): self.assertEqual(ConcreteInstr("ROT_TWO").size, 2 if WORDCODE else 1) self.assertEqual( ConcreteInstr("LOAD_CONST", 3).size, 2 if WORDCODE else 3) self.assertEqual( ConcreteInstr("LOAD_CONST", 0x1234ABCD).size, 8 if WORDCODE else 6)
def test_assemble(self): instr = ConcreteInstr("NOP") self.assertEqual(instr.assemble(), b"\t\x00") instr = ConcreteInstr("LOAD_CONST", 3) self.assertEqual(instr.assemble(), b"d\x03") instr = ConcreteInstr("LOAD_CONST", 0x1234ABCD) self.assertEqual( instr.assemble(), (b"\x90\x12\x904\x90\xabd\xcd"), ) instr = ConcreteInstr("LOAD_CONST", 3, extended_args=1) self.assertEqual( instr.assemble(), (b"\x90\x00d\x03"), )
def test_extended_arg_make_function(self): code_obj = get_code(""" def foo(x: int, y: int): pass """) # without EXTENDED_ARG concrete = ConcreteBytecode.from_code(code_obj) func_code = concrete.consts[1] self.assertEqual(concrete.names, ["int", "foo"]) self.assertEqual(concrete.consts, [("x", "y"), func_code, "foo", None]) if WORDCODE: expected = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("BUILD_CONST_KEY_MAP", 2, lineno=1), ConcreteInstr("LOAD_CONST", 1, lineno=1), ConcreteInstr("LOAD_CONST", 2, lineno=1), ConcreteInstr("MAKE_FUNCTION", 4, lineno=1), ConcreteInstr("STORE_NAME", 1, lineno=1), ConcreteInstr("LOAD_CONST", 3, lineno=1), ConcreteInstr("RETURN_VALUE", lineno=1), ] else: expected = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("LOAD_CONST", 1, lineno=1), ConcreteInstr("LOAD_CONST", 2, lineno=1), ConcreteInstr("MAKE_FUNCTION", 3 << 16, lineno=1), ConcreteInstr("STORE_NAME", 1, lineno=1), ConcreteInstr("LOAD_CONST", 3, lineno=1), ConcreteInstr("RETURN_VALUE", lineno=1), ] self.assertListEqual(list(concrete), expected) # with EXTENDED_ARG concrete = ConcreteBytecode.from_code(code_obj, extended_arg=True) func_code = concrete.consts[1] self.assertEqual(concrete.names, ["int", "foo"]) self.assertEqual(concrete.consts, [("x", "y"), func_code, "foo", None]) if not WORDCODE: expected = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("LOAD_CONST", 1, lineno=1), ConcreteInstr("LOAD_CONST", 2, lineno=1), ConcreteInstr("EXTENDED_ARG", 3, lineno=1), ConcreteInstr("MAKE_FUNCTION", 0, lineno=1), ConcreteInstr("STORE_NAME", 1, lineno=1), ConcreteInstr("LOAD_CONST", 3, lineno=1), ConcreteInstr("RETURN_VALUE", lineno=1), ] self.assertListEqual(list(concrete), expected)
def test_size(self): self.assertEqual(ConcreteInstr("ROT_TWO").size, 2) self.assertEqual(ConcreteInstr("LOAD_CONST", 3).size, 2) self.assertEqual(ConcreteInstr("LOAD_CONST", 0x1234ABCD).size, 8)