def test_optimize_code_obj(self): # Test optimize() method with a code object # # x = 3 + 5 => x = 8 noopt = Bytecode([ Instr("LOAD_CONST", 3), Instr("LOAD_CONST", 5), Instr("BINARY_ADD"), Instr("STORE_NAME", "x"), Instr("LOAD_CONST", None), Instr("RETURN_VALUE"), ]) noopt = noopt.to_code() optimizer = peephole_opt.PeepholeOptimizer() optim = optimizer.optimize(noopt) code = Bytecode.from_code(optim) self.assertEqual( code, [ Instr("LOAD_CONST", 8, lineno=1), Instr("STORE_NAME", "x", lineno=1), Instr("LOAD_CONST", None, lineno=1), Instr("RETURN_VALUE", lineno=1), ], )
def test_legalize(self): code = Bytecode() code.first_lineno = 3 code.extend( [ Instr("LOAD_CONST", 7), Instr("STORE_NAME", "x"), Instr("LOAD_CONST", 8, lineno=4), Instr("STORE_NAME", "y"), SetLineno(5), Instr("LOAD_CONST", 9, lineno=6), Instr("STORE_NAME", "z"), ] ) blocks = ControlFlowGraph.from_bytecode(code) blocks.legalize() self.assertBlocksEqual( blocks, [ 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_slice(self): 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"), ]) sliced_code = code[:] self.assertEqual(code, sliced_code) for name in ( "argcount", "posonlyargcount", "kwonlyargcount", "first_lineno", "name", "filename", "docstring", "cellvars", "freevars", "argnames", ): self.assertEqual(getattr(code, name, None), getattr(sliced_code, name, None))
def test_extended_jump(self): NOP = bytes((opcode.opmap["NOP"], )) class BigInstr(ConcreteInstr): def __init__(self, size): super().__init__("NOP") self._size = size def copy(self): return self def assemble(self): return NOP * self._size # (invalid) code using jumps > 0xffff to test extended arg label = Label() nb_nop = 2**16 code = Bytecode([ Instr("JUMP_ABSOLUTE", label), BigInstr(nb_nop), label, Instr("LOAD_CONST", None), Instr("RETURN_VALUE"), ]) code_obj = code.to_code() if WORDCODE: expected = b"\x90\x01\x90\x00q\x06" + NOP * nb_nop + b"d\x00S\x00" else: expected = b"\x90\x01\x00q\x06\x00" + NOP * nb_nop + b"d\x00\x00S" self.assertEqual(code_obj.co_code, expected)
def test_general_constants(self): """Test if general object could be linked as constants. """ class CustomObject: pass class UnHashableCustomObject: __hash__ = None obj1 = [1, 2, 3] obj2 = {1, 2, 3} obj3 = CustomObject() obj4 = UnHashableCustomObject() code = Bytecode([ Instr("LOAD_CONST", obj1, lineno=1), Instr("LOAD_CONST", obj2, lineno=1), Instr("LOAD_CONST", obj3, lineno=1), Instr("LOAD_CONST", obj4, lineno=1), Instr("BUILD_TUPLE", 4, lineno=1), Instr("RETURN_VALUE", lineno=1), ]) self.assertEqual(code.to_code().co_consts, (obj1, obj2, obj3, obj4)) def f(): return # pragma: no cover f.__code__ = code.to_code() self.assertEqual(f(), (obj1, obj2, obj3, obj4))
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", 14 if WORDCODE else 21, lineno=1), ConcreteInstr("LOAD_CONST", 0, lineno=2), ConcreteInstr("STORE_NAME", 1, lineno=2), ConcreteInstr("JUMP_FORWARD", 4 if WORDCODE else 6, 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_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"), ] ) blocks = ControlFlowGraph.from_bytecode(code) self.assertBlocksEqual( blocks, [ 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"), ], )
def test_combined_unary_bin_ops(self): # x = 1 + 3 + 7 code = Bytecode([ Instr("LOAD_CONST", 1), Instr("LOAD_CONST", 3), Instr("BINARY_ADD"), Instr("LOAD_CONST", 7), Instr("BINARY_ADD"), Instr("STORE_NAME", "x"), ]) self.check(code, Instr("LOAD_CONST", 11), Instr("STORE_NAME", "x")) # x = ~(~(5)) code = Bytecode([ Instr("LOAD_CONST", 5), Instr("UNARY_INVERT"), Instr("UNARY_INVERT"), Instr("STORE_NAME", "x"), ]) self.check(code, Instr("LOAD_CONST", 5), Instr("STORE_NAME", "x")) # "events = [(0, 'call'), (1, 'line'), (-(3), 'call')]" code = Bytecode([ Instr("LOAD_CONST", 0), Instr("LOAD_CONST", "call"), Instr("BUILD_TUPLE", 2), Instr("LOAD_CONST", 1), Instr("LOAD_CONST", "line"), Instr("BUILD_TUPLE", 2), Instr("LOAD_CONST", 3), Instr("UNARY_NEGATIVE"), Instr("LOAD_CONST", "call"), Instr("BUILD_TUPLE", 2), Instr("BUILD_LIST", 3), Instr("STORE_NAME", "events"), ]) self.check( code, Instr("LOAD_CONST", (0, "call")), Instr("LOAD_CONST", (1, "line")), Instr("LOAD_CONST", (-3, "call")), Instr("BUILD_LIST", 3), Instr("STORE_NAME", "events"), ) # 'x = (1,) + (0,) * 8' code = Bytecode([ Instr("LOAD_CONST", 1), Instr("BUILD_TUPLE", 1), Instr("LOAD_CONST", 0), Instr("BUILD_TUPLE", 1), Instr("LOAD_CONST", 8), Instr("BINARY_MULTIPLY"), Instr("BINARY_ADD"), Instr("STORE_NAME", "x"), ]) zeros = (0, ) * 8 result = (1, ) + zeros self.check(code, Instr("LOAD_CONST", result), Instr("STORE_NAME", "x"))
def check(self, source, function=False): ref_code = get_code(source, function=function) code = ConcreteBytecode.from_code(ref_code).to_code() self.assertEqual(code, ref_code) code = Bytecode.from_code(ref_code).to_code() self.assertEqual(code, ref_code) bytecode = Bytecode.from_code(ref_code) blocks = ControlFlowGraph.from_bytecode(bytecode) code = blocks.to_bytecode().to_code() self.assertEqual(code, ref_code)
def test_build_list_unpack_seq(self): for build_list in ("BUILD_TUPLE", "BUILD_LIST"): # x, = [a] code = Bytecode([ Instr("LOAD_NAME", "a"), Instr(build_list, 1), Instr("UNPACK_SEQUENCE", 1), Instr("STORE_NAME", "x"), ]) self.check(code, Instr("LOAD_NAME", "a"), Instr("STORE_NAME", "x")) # x, y = [a, b] code = Bytecode([ Instr("LOAD_NAME", "a"), Instr("LOAD_NAME", "b"), Instr(build_list, 2), Instr("UNPACK_SEQUENCE", 2), Instr("STORE_NAME", "x"), Instr("STORE_NAME", "y"), ]) self.check( code, Instr("LOAD_NAME", "a"), Instr("LOAD_NAME", "b"), Instr("ROT_TWO"), Instr("STORE_NAME", "x"), Instr("STORE_NAME", "y"), ) # x, y, z = [a, b, c] code = Bytecode([ Instr("LOAD_NAME", "a"), Instr("LOAD_NAME", "b"), Instr("LOAD_NAME", "c"), Instr(build_list, 3), Instr("UNPACK_SEQUENCE", 3), Instr("STORE_NAME", "x"), Instr("STORE_NAME", "y"), Instr("STORE_NAME", "z"), ]) self.check( code, Instr("LOAD_NAME", "a"), Instr("LOAD_NAME", "b"), Instr("LOAD_NAME", "c"), Instr("ROT_THREE"), Instr("ROT_TWO"), Instr("STORE_NAME", "x"), Instr("STORE_NAME", "y"), Instr("STORE_NAME", "z"), )
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_stack_size_computation_nested_try_except_else_finally(self): def test(*args, **kwargs): try: v = args[1] except IndexError: try: w = kwargs["value"] except KeyError: return -1 else: return w finally: print("second finally") else: return v finally: print("first finally") # A direct comparison of the stack depth fails because CPython # generate dead code that is used in stack computation. cpython_stacksize = test.__code__.co_stacksize test.__code__ = Bytecode.from_code(test.__code__).to_code() self.assertLessEqual(test.__code__.co_stacksize, cpython_stacksize) with contextlib.redirect_stdout(io.StringIO()) as stdout: self.assertEqual(test(1, 4), 4) self.assertEqual(stdout.getvalue(), "first finally\n") with contextlib.redirect_stdout(io.StringIO()) as stdout: self.assertEqual(test([], value=3), 3) self.assertEqual(stdout.getvalue(), "second finally\nfirst finally\n") with contextlib.redirect_stdout(io.StringIO()) as stdout: self.assertEqual(test([], name=None), -1) self.assertEqual(stdout.getvalue(), "second finally\nfirst finally\n")
def test_not_jump_if_false(self): # Replace UNARY_NOT+POP_JUMP_IF_FALSE with POP_JUMP_IF_TRUE # # if not x: # y = 9 label = Label() code = Bytecode([ Instr("LOAD_NAME", "x"), Instr("UNARY_NOT"), Instr("POP_JUMP_IF_FALSE", label), Instr("LOAD_CONST", 9), Instr("STORE_NAME", "y"), label, ]) code = self.optimize_blocks(code) label = Label() self.check( code, Instr("LOAD_NAME", "x"), Instr("POP_JUMP_IF_TRUE", label), Instr("LOAD_CONST", 9), Instr("STORE_NAME", "y"), label, )
def test_unconditional_jumps(self): # def func(): # if x: # if y: # func() label_instr7 = Label() code = Bytecode([ Instr("LOAD_GLOBAL", "x", lineno=2), Instr("POP_JUMP_IF_FALSE", label_instr7, lineno=2), Instr("LOAD_GLOBAL", "y", lineno=3), Instr("POP_JUMP_IF_FALSE", label_instr7, lineno=3), Instr("LOAD_GLOBAL", "func", lineno=4), Instr("CALL_FUNCTION", 0, lineno=4), Instr("POP_TOP", lineno=4), label_instr7, Instr("LOAD_CONST", None, lineno=4), Instr("RETURN_VALUE", lineno=4), ]) label_return = Label() self.check( code, Instr("LOAD_GLOBAL", "x", lineno=2), Instr("POP_JUMP_IF_FALSE", label_return, lineno=2), Instr("LOAD_GLOBAL", "y", lineno=3), Instr("POP_JUMP_IF_FALSE", label_return, lineno=3), Instr("LOAD_GLOBAL", "func", lineno=4), Instr("CALL_FUNCTION", 0, lineno=4), Instr("POP_TOP", lineno=4), label_return, Instr("LOAD_CONST", None, lineno=4), Instr("RETURN_VALUE", lineno=4), )
def test_from_code_freevars(self): ns = {} exec( textwrap.dedent(""" def create_func(): x = 1 def func(): return x return func func = create_func() """), ns, ns, ) code = ns["func"].__code__ bytecode = Bytecode.from_code(code) self.assertEqual( bytecode, [ Instr("LOAD_DEREF", FreeVar("x"), lineno=5), Instr("RETURN_VALUE", lineno=5), ], )
def test_jump_to_return(self): # def func(condition): # return 'yes' if condition else 'no' label_instr4 = Label() label_instr6 = Label() code = Bytecode([ Instr("LOAD_FAST", "condition"), Instr("POP_JUMP_IF_FALSE", label_instr4), Instr("LOAD_CONST", "yes"), Instr("JUMP_FORWARD", label_instr6), label_instr4, Instr("LOAD_CONST", "no"), label_instr6, Instr("RETURN_VALUE"), ]) label = Label() self.check( code, Instr("LOAD_FAST", "condition"), Instr("POP_JUMP_IF_FALSE", label), Instr("LOAD_CONST", "yes"), Instr("RETURN_VALUE"), label, Instr("LOAD_CONST", "no"), Instr("RETURN_VALUE"), )
def test_from_code(self): code = get_code(""" if test: x = 1 else: x = 2 """) bytecode = Bytecode.from_code(code) label_else = Label() label_exit = Label() self.assertEqual( bytecode, [ Instr("LOAD_NAME", "test", lineno=1), Instr("POP_JUMP_IF_FALSE", label_else, lineno=1), Instr("LOAD_CONST", 1, lineno=2), Instr("STORE_NAME", "x", lineno=2), Instr("JUMP_FORWARD", label_exit, lineno=2), label_else, Instr("LOAD_CONST", 2, lineno=4), Instr("STORE_NAME", "x", lineno=4), label_exit, Instr("LOAD_CONST", None, lineno=4), Instr("RETURN_VALUE", lineno=4), ], )
def test_nop(self): code = Bytecode([ Instr("LOAD_NAME", "x"), Instr("NOP"), Instr("STORE_NAME", "test") ]) self.check(code, Instr("LOAD_NAME", "x"), Instr("STORE_NAME", "test"))
def check_unary_op(op, value, result): code = Bytecode([ Instr("LOAD_CONST", value), Instr(op), Instr("STORE_NAME", "x") ]) self.check(code, Instr("LOAD_CONST", result), Instr("STORE_NAME", "x"))
def test_legalize(self): code = Bytecode() code.first_lineno = 3 code.extend([ Instr("LOAD_CONST", 7), Instr("STORE_NAME", "x"), Instr("LOAD_CONST", 8, lineno=4), Instr("STORE_NAME", "y"), Label(), SetLineno(5), Instr("LOAD_CONST", 9, lineno=6), Instr("STORE_NAME", "z"), ]) code.legalize() self.assertListEqual( 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), Label(), Instr("LOAD_CONST", 9, lineno=5), Instr("STORE_NAME", "z", lineno=5), ], )
def optimize(self, code_obj): bytecode = Bytecode.from_code(code_obj) cfg = ControlFlowGraph.from_bytecode(bytecode) self.optimize_cfg(cfg) bytecode = cfg.to_bytecode() code = bytecode.to_code() return code
def test_label(self): code = Bytecode() label = Label() code.extend([ Instr("LOAD_CONST", "hello", lineno=1), Instr("JUMP_FORWARD", label, lineno=1), label, Instr("POP_TOP", lineno=1), ]) code = code.to_concrete_bytecode() expected = [ ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("JUMP_FORWARD", 0, lineno=1), ConcreteInstr("POP_TOP", lineno=1), ] self.assertListEqual(list(code), expected) self.assertListEqual(code.consts, ["hello"])
def check_bin_op(left, op, right, result): code = Bytecode([ Instr("LOAD_CONST", left), Instr("LOAD_CONST", right), Instr(op), Instr("STORE_NAME", "x"), ]) self.check(code, Instr("LOAD_CONST", result), Instr("STORE_NAME", "x"))
def test_bin_op_dont_optimize(self): # 1 / 0 code = Bytecode([ Instr("LOAD_CONST", 1), Instr("LOAD_CONST", 0), Instr("BINARY_TRUE_DIVIDE"), Instr("POP_TOP"), Instr("LOAD_CONST", None), Instr("RETURN_VALUE"), ]) self.check_dont_optimize(code) # 1 // 0 code = Bytecode([ Instr("LOAD_CONST", 1), Instr("LOAD_CONST", 0), Instr("BINARY_FLOOR_DIVIDE"), Instr("POP_TOP"), Instr("LOAD_CONST", None), Instr("RETURN_VALUE"), ]) self.check_dont_optimize(code) # 1 % 0 code = Bytecode([ Instr("LOAD_CONST", 1), Instr("LOAD_CONST", 0), Instr("BINARY_MODULO"), Instr("POP_TOP"), Instr("LOAD_CONST", None), Instr("RETURN_VALUE"), ]) self.check_dont_optimize(code) # 1 % 1j code = Bytecode([ Instr("LOAD_CONST", 1), Instr("LOAD_CONST", 1j), Instr("BINARY_MODULO"), Instr("POP_TOP"), Instr("LOAD_CONST", None), Instr("RETURN_VALUE"), ]) self.check_dont_optimize(code)
def test_cellvars(self): code = Bytecode() code.cellvars = ["x"] code.freevars = ["y"] code.extend([ Instr("LOAD_DEREF", CellVar("x"), lineno=1), Instr("LOAD_DEREF", FreeVar("y"), lineno=1), ]) concrete = code.to_concrete_bytecode() self.assertEqual(concrete.cellvars, ["x"]) self.assertEqual(concrete.freevars, ["y"]) code.extend([ ConcreteInstr("LOAD_DEREF", 0, lineno=1), ConcreteInstr("LOAD_DEREF", 1, lineno=1), ])
def test_negative_size_build_const_map(self): code = Bytecode() code.first_lineno = 1 code.extend( [Instr("LOAD_CONST", ("a", )), Instr("BUILD_CONST_KEY_MAP", 1)]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_unconditional_jump_to_return(self): # def func(): # if test: # if test2: # x = 10 # else: # x = 20 # else: # x = 30 label_instr11 = Label() label_instr14 = Label() label_instr7 = Label() code = Bytecode([ Instr("LOAD_GLOBAL", "test", lineno=2), Instr("POP_JUMP_IF_FALSE", label_instr11, lineno=2), Instr("LOAD_GLOBAL", "test2", lineno=3), Instr("POP_JUMP_IF_FALSE", label_instr7, lineno=3), Instr("LOAD_CONST", 10, lineno=4), Instr("STORE_FAST", "x", lineno=4), Instr("JUMP_ABSOLUTE", label_instr14, lineno=4), label_instr7, Instr("LOAD_CONST", 20, lineno=6), Instr("STORE_FAST", "x", lineno=6), Instr("JUMP_FORWARD", label_instr14, lineno=6), label_instr11, Instr("LOAD_CONST", 30, lineno=8), Instr("STORE_FAST", "x", lineno=8), label_instr14, Instr("LOAD_CONST", None, lineno=8), Instr("RETURN_VALUE", lineno=8), ]) label1 = Label() label3 = Label() label4 = Label() self.check( code, Instr("LOAD_GLOBAL", "test", lineno=2), Instr("POP_JUMP_IF_FALSE", label3, lineno=2), Instr("LOAD_GLOBAL", "test2", lineno=3), Instr("POP_JUMP_IF_FALSE", label1, lineno=3), Instr("LOAD_CONST", 10, lineno=4), Instr("STORE_FAST", "x", lineno=4), Instr("JUMP_ABSOLUTE", label4, lineno=4), label1, Instr("LOAD_CONST", 20, lineno=6), Instr("STORE_FAST", "x", lineno=6), Instr("JUMP_FORWARD", label4, lineno=6), label3, Instr("LOAD_CONST", 30, lineno=8), Instr("STORE_FAST", "x", lineno=8), label4, Instr("LOAD_CONST", None, lineno=8), Instr("RETURN_VALUE", lineno=8), )
def test_dont_merge_constants(self): # test two constants which are equal but have a different type code = Bytecode() code.extend([ Instr("LOAD_CONST", 5, lineno=1), Instr("LOAD_CONST", 5.0, lineno=1), Instr("LOAD_CONST", -0.0, lineno=1), Instr("LOAD_CONST", +0.0, lineno=1), ]) code = code.to_concrete_bytecode() expected = [ ConcreteInstr("LOAD_CONST", 0, lineno=1), ConcreteInstr("LOAD_CONST", 1, lineno=1), ConcreteInstr("LOAD_CONST", 2, lineno=1), ConcreteInstr("LOAD_CONST", 3, lineno=1), ] self.assertListEqual(list(code), expected) self.assertListEqual(code.consts, [5, 5.0, -0.0, +0.0])
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_invalid_types(self): code = Bytecode() code.append(123) with self.assertRaises(ValueError): list(code) with self.assertRaises(ValueError): code.legalize() with self.assertRaises(ValueError): Bytecode([123])