示例#1
0
 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)])
示例#2
0
 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)])
示例#3
0
 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),
     ])
示例#4
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