def process_body(self, body): """Finds desired varnames in body and instantiate operation""" oper = self.operation lines = self.lines if oper == "detect": self.result = DetectOperation() for stmt in body: if is_assign_to_name(stmt): if stmt.targets[0].id == self.varname and oper == "delete": self.remove_stmt(stmt) break elif stmt.targets[0].id > self.varname and oper == "insert": self.insert(stmt.first_line, False) break elif self.operation == "detect": self.result.work_list.append(( stmt.targets[0].id, stmt.value.args[0].args[1].s, pyposast.extract_code(lines, stmt), stmt.value.args[0].args[0].n, )) elif self.operation == "detect" and is_call_statement(stmt): self.result.citations.append(( pyposast.extract_code(lines, stmt.value.args[0].args[0]), pyposast.extract_code(lines, stmt.value.args[0].args[1]), pyposast.extract_code(lines, stmt.value), isinstance(stmt.value.args[0].args[1], ast.Name), )) if body and self.operation == "insert" and not self.result: self.insert(stmt.last_line, True)
def node_code(self, node): """Use PyPosAST positions to extract node text""" return extract_code(self.lcode, node, lstrip=" \t", ljoin="", strip="() \t")
def remove_keyword(self, keyword, remove_lines): """Instantiate an operation to remove a keyword""" if not remove_lines: warnings.warn( "PyPosAST bug" "Wrong positions for keywords. Won't delete attribute") self.result = DelOperation(keyword.value, remove_lines) self.old = keyword.arg + "=" + pyposast.extract_code( self.lines, keyword.value)
def process_body(self, body): """Find citation/import and applies the desired `.operation`""" if self.operation in ("find", "detect"): self.result = DetectOperation() last_line = 0 for stmt in body: if isinstance(stmt, ast.ImportFrom) and stmt.module is not None: year = int(getattr(re.search(r"work\.y(\d\d\d\d)", stmt.module), "group", lambda x: -1)(1)) if self.year == year and self.operation == "remove import": aliases = [a for a in stmt.names if a.name == self.varname] if aliases: if len(stmt.names) == 1: self.result = DelOperation(stmt, True) self.old = pyposast.extract_code(self.lines, stmt) elif aliases[0] == stmt.names[-1]: line = "".join(reversed(self.lines[aliases[0].last_line - 1])) pos = len(line) - aliases[0].first_col aliases[0].first_col = len(line) - next(re.compile("\w.*").finditer(line, pos=pos)).span()[0] self.result = DelOperation(aliases[0], False) self.old = pyposast.extract_code(self.lines, aliases[0]) else: line = self.lines[aliases[0].last_line - 1] pos = aliases[0].last_col aliases[0].last_col = next(re.compile("\w.*").finditer(line, pos=pos)).span()[0] self.result = DelOperation(aliases[0], False) self.old = pyposast.extract_code(self.lines, aliases[0]) break if self.operation == "insert import": last_line = stmt.first_line if self.year < year: self.result = InsertOperation(stmt.first_line, False, add_line=False) break if year != -1 and self.operation == "detect": self.result.imports += [a.name for a in stmt.names] if is_call_statement(stmt): if self.operation == "insert import": self.result = InsertOperation(last_line + 1, False, add_line=False) break target = pyposast.extract_code(self.lines, stmt.value.args[0].args[1]) source = pyposast.extract_code(self.lines, stmt.value.args[0].args[0]) if self.operation == "remove target" and target == self.varname: self.result = DelOperation(stmt, True) self.old = source + "<=>" + pyposast.extract_code(self.lines, stmt) break if self.operation == "remove source" and source == self.varname: self.result = DelOperation(stmt, True) self.old = target + "<=>" + pyposast.extract_code(self.lines, stmt) break if self.operation == "find" and self.varname in (source, target): self.result.citations.append(self.varname) if self.operation == "detect": self.result.citations.append((source, target)) if self.operation == "insert import" and not self.result: self.result = InsertOperation(last_line + 1, True, add_line=True)
def remove_stmt(self, stmt): """Instantiate an operation to remove the stmt""" self.result = DelOperation(stmt, True) self.old = pyposast.extract_code(self.lines, stmt)
def replace(self, node): """Instantiate a replace operation""" self.result = ReplaceOperation(node) self.old = pyposast.extract_code(self.lines, node)
def extract_code(self, node): """Use PyPosAST to extract node text without strips""" return extract_code(self.lcode, node)
def node_code(self, node): """Use PyPosAST positions to extract node text""" return extract_code( self.lcode, node, lstrip=" \t", ljoin="", strip="() \t" )