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),
            ],
        )
Example #2
0
    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),
            ],
        )
Example #6
0
    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",
        )
Example #7
0
    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)
Example #8
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, [])
Example #9
0
    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")
Example #10
0
    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))
Example #11
0
    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)
Example #12
0
    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))
Example #13
0
    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))
Example #14
0
    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, [])
Example #15
0
    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)
        )
Example #16
0
 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())
Example #17
0
    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)
Example #18
0
    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)
Example #19
0
    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)
Example #20
0
    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),
            ],
        )
Example #21
0
    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),
            ],
        )
Example #22
0
 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)
Example #23
0
    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"),
        )
Example #24
0
    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)
Example #25
0
 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)