示例#1
0
    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),
            ],
        )
示例#2
0
    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'])
        code.extend([
            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)
        ])
示例#3
0
    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),
            ],
        )
示例#4
0
 def test_negative_size_unpack(self):
     with self.subTest():
         code = Bytecode()
         code.first_lineno = 1
         code.extend([Instr("UNPACK_SEQUENCE", 1)])
         with self.assertRaises(RuntimeError):
             code.compute_stacksize()
示例#5
0
    def test_copy(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"),
            ]
        )

        copy_code = code.copy()
        self.assertEqual(code, copy_code)
        for name in (
            "argcount",
            "posonlyargcount",
            "kwonlyargcount",
            "first_lineno",
            "name",
            "filename",
            "docstring",
            "cellvars",
            "freevars",
            "argnames",
        ):
            self.assertEqual(getattr(code, name, None), getattr(copy_code, name, None))
示例#6
0
    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),
            ],
        )
示例#7
0
    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')])
示例#8
0
    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')])
示例#9
0
 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",
             "first_lineno",
             "name",
             "filename",
             "docstring",
             "cellvars",
             "freevars",
             "argnames",
     ):
         Undefined = object()
         self.assertEqual(getattr(code, name, Undefined),
                          getattr(sliced_code, name, Undefined))
示例#10
0
 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()
示例#11
0
 def test_negative_size_build_const_map_with_disable_check_of_pre_and_post(
         self):
     code = Bytecode()
     code.first_lineno = 1
     code.extend(
         [Instr("LOAD_CONST", ("a", )),
          Instr("BUILD_CONST_KEY_MAP", 1)])
     co = code.to_code(check_pre_and_post=False)
     self.assertEqual(co.co_stacksize, 1)
示例#12
0
 def test_not_enough_rot_with_disable_check_of_pre_and_post(self):
     opnames = ["ROT_TWO", "ROT_THREE"]
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr("LOAD_CONST", 1), Instr(opname)])
             co = code.to_code(check_pre_and_post=False)
             self.assertEqual(co.co_stacksize, 1)
示例#13
0
 def test_not_enough_rot(self):
     opnames = ["ROT_TWO", "ROT_THREE"]
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr("LOAD_CONST", 1), Instr(opname)])
             with self.assertRaises(RuntimeError):
                 code.compute_stacksize()
示例#14
0
 def test_handling_of_extended_arg(self):
     code = Bytecode()
     code.first_lineno = 3
     code.extend([Instr("LOAD_CONST", 7),
                  Instr("STORE_NAME", 'x'),
                  Instr("EXTENDED_ARG", 1),
                  Instr("LOAD_CONST", 8),
                  Instr("STORE_NAME", 'y')])
     self.assertEqual(code.compute_stacksize(), 1)
示例#15
0
 def test_handling_of_set_lineno(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')])
     self.assertEqual(code.compute_stacksize(), 1)
示例#16
0
 def test_negative_size_build(self):
     opnames = (
         "BUILD_TUPLE",
         "BUILD_LIST",
         "BUILD_SET",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr(opname, 1)])
             with self.assertRaises(RuntimeError):
                 code.compute_stacksize()
示例#17
0
 def test_negative_size_unary_with_disable_check_of_pre_and_post(self):
     opnames = (
         "UNARY_POSITIVE",
         "UNARY_NEGATIVE",
         "UNARY_NOT",
         "UNARY_INVERT",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr(opname)])
             co = code.to_code(check_pre_and_post=False)
             self.assertEqual(co.co_stacksize, 0)
示例#18
0
 def test_negative_size_unary(self):
     opnames = (
         "UNARY_POSITIVE",
         "UNARY_NEGATIVE",
         "UNARY_NOT",
         "UNARY_INVERT",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr(opname)])
             with self.assertRaises(RuntimeError):
                 code.compute_stacksize()
示例#19
0
    def test_to_code(self):
        code = Bytecode()
        code.first_lineno = 50
        code.extend([Instr("LOAD_NAME", "print"),
                     Instr("LOAD_CONST", "%s"),
                     Instr("LOAD_GLOBAL", "a"),
                     Instr("BINARY_MODULO"),
                     Instr("CALL_FUNCTION", 1),
                     Instr("RETURN_VALUE")])
        co = code.to_code()
        # hopefully this is obvious from inspection? :-)
        self.assertEqual(co.co_stacksize, 3)

        co = code.to_code(stacksize=42)
        self.assertEqual(co.co_stacksize, 42)
示例#20
0
 def test_for_iter_stack_effect_computation(self):
     with self.subTest():
         code = Bytecode()
         code.first_lineno = 1
         lab1 = Label()
         lab2 = Label()
         code.extend([
             lab1,
             Instr("FOR_ITER", lab2),
             Instr("STORE_FAST", "i"),
             Instr("JUMP_ABSOLUTE", lab1),
             lab2,
         ])
         with self.assertRaises(RuntimeError):
             # Use compute_stacksize since the code is so broken that conversion
             # to from concrete is actually broken
             code.compute_stacksize(check_pre_and_post=False)
示例#21
0
    def test_to_code(self):
        code = Bytecode()
        code.first_lineno = 50
        code.extend([
            Instr("LOAD_NAME", "print"),
            Instr("LOAD_CONST", "%s"),
            Instr("LOAD_GLOBAL", "a"),
            Instr("BINARY_MODULO"),
            Instr("CALL_FUNCTION", 1),
            Instr("RETURN_VALUE"),
        ])
        co = code.to_code()
        # hopefully this is obvious from inspection? :-)
        self.assertEqual(co.co_stacksize, 3)

        co = code.to_code(stacksize=42)
        self.assertEqual(co.co_stacksize, 42)
示例#22
0
 def test_negative_size_binary_with_disable_check_of_pre_and_post(self):
     opnames = (
         "BINARY_POWER",
         "BINARY_MULTIPLY",
         "BINARY_FLOOR_DIVIDE",
         "BINARY_TRUE_DIVIDE",
         "BINARY_MODULO",
         "BINARY_ADD",
         "BINARY_SUBTRACT",
         "BINARY_SUBSCR",
         "BINARY_LSHIFT",
         "BINARY_RSHIFT",
         "BINARY_AND",
         "BINARY_XOR",
         "BINARY_OR",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr("LOAD_CONST", 1), Instr(opname)])
             co = code.to_code(check_pre_and_post=False)
             self.assertEqual(co.co_stacksize, 1)
示例#23
0
 def test_negative_size_binary(self):
     opnames = (
         "BINARY_POWER",
         "BINARY_MULTIPLY",
         "BINARY_FLOOR_DIVIDE",
         "BINARY_TRUE_DIVIDE",
         "BINARY_MODULO",
         "BINARY_ADD",
         "BINARY_SUBTRACT",
         "BINARY_SUBSCR",
         "BINARY_LSHIFT",
         "BINARY_RSHIFT",
         "BINARY_AND",
         "BINARY_XOR",
         "BINARY_OR",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr("LOAD_CONST", 1), Instr(opname)])
             with self.assertRaises(RuntimeError):
                 code.compute_stacksize()
示例#24
0
    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'])
        code.extend([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)])
示例#25
0
    def modify(self, code, *, inner=False):
        initial_bytecode = Bytecode.from_code(code)

        modified_bytecode = Bytecode()
        modified_bytecode.first_lineno = initial_bytecode.first_lineno
        modified_bytecode.argcount = code.co_argcount
        modified_bytecode.argnames = initial_bytecode.argnames
        modified_bytecode.name = initial_bytecode.name
        modified_bytecode.freevars = code.co_freevars
        modified_bytecode.cellvars = code.co_cellvars

        first_line_no = initial_bytecode.first_lineno

        if inner:
            modified_bytecode.extend([
                Instr('LOAD_NAME', arg=self._command, lineno=first_line_no),
                Instr('LOAD_CONST',
                      arg=DebugCommand.STEP_OVER,
                      lineno=first_line_no),
                Instr('COMPARE_OP', arg=Compare.EQ, lineno=first_line_no),
                Instr('STORE_NAME', arg='is_over', lineno=first_line_no),
            ])

        # добавляем инструкции отладки перед первой строкой модуля
        if not inner:
            modified_bytecode.extend(
                self._get_trace_func_call_instructions(first_line_no))

        previous_line_no = first_line_no
        for instr in initial_bytecode:
            if not isinstance(instr, Instr):
                modified_bytecode.append(instr)
                continue

            if isinstance(instr.arg, types.CodeType):
                old_instr_name = instr.name
                new_co = self.modify(instr.arg, inner=True)
                instr.set(old_instr_name, new_co)

            skip = Label()
            if instr.lineno != previous_line_no:
                if inner:
                    modified_bytecode.extend([
                        Instr('LOAD_NAME', arg='is_over', lineno=instr.lineno),
                        Instr('POP_JUMP_IF_TRUE',
                              arg=skip,
                              lineno=instr.lineno)
                    ])
                    modified_bytecode.extend([
                        Instr('LOAD_NAME',
                              arg=self._command,
                              lineno=instr.lineno),
                        Instr('LOAD_CONST',
                              arg=DebugCommand.STEP_OUT,
                              lineno=instr.lineno),
                        Instr('COMPARE_OP',
                              arg=Compare.EQ,
                              lineno=instr.lineno),
                        Instr('POP_JUMP_IF_TRUE',
                              arg=skip,
                              lineno=instr.lineno)
                    ])

                modified_bytecode.extend(
                    self._get_trace_func_call_instructions(instr.lineno))

                if inner:
                    modified_bytecode.append(skip)
                previous_line_no = instr.lineno

            modified_bytecode.append(instr)

        code = modified_bytecode.to_code()

        return code
示例#26
0
 def test_not_enough_dup(self):
     code = Bytecode()
     code.first_lineno = 1
     code.extend([Instr("LOAD_CONST", 1), Instr("DUP_TOP_TWO")])
     with self.assertRaises(RuntimeError):
         code.compute_stacksize()
示例#27
0
 def test_empty_dup(self):
     code = Bytecode()
     code.first_lineno = 1
     code.extend([Instr("DUP_TOP")])
     with self.assertRaises(RuntimeError):
         code.compute_stacksize()
示例#28
0
 def test_negative_size_call(self):
     code = Bytecode()
     code.first_lineno = 1
     code.extend([Instr("CALL_FUNCTION", 0)])
     with self.assertRaises(RuntimeError):
         code.compute_stacksize()