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_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 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