我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用ast.If()。
def __init__(self, stmt, context): self.stmt = stmt self.context = context self.stmt_table = { ast.Expr: self.expr, ast.Pass: self.parse_pass, ast.AnnAssign: self.ann_assign, ast.Assign: self.assign, ast.If: self.parse_if, ast.Call: self.call, ast.Assert: self.parse_assert, ast.For: self.parse_for, ast.AugAssign: self.aug_assign, ast.Break: self.parse_break, ast.Return: self.parse_return, } stmt_type = self.stmt.__class__ if stmt_type in self.stmt_table: self.lll_node = self.stmt_table[stmt_type]() elif isinstance(stmt, ast.Name) and stmt.id == "throw": self.lll_node = LLLnode.from_list(['assert', 0], typ=None, pos=getpos(stmt)) else: raise StructureException("Unsupported statement type", stmt)
def load_module(self, name): # If there is an existing module object named 'fullname' in # sys.modules, the loader must use that existing module. (Otherwise, # the reload() builtin will not work correctly.) if name in sys.modules: return sys.modules[name] co, pyc = self.modules.pop(name) # I wish I could just call imp.load_compiled here, but __file__ has to # be set properly. In Python 3.2+, this all would be handled correctly # by load_compiled. mod = sys.modules[name] = imp.new_module(name) try: mod.__file__ = co.co_filename # Normally, this attribute is 3.2+. mod.__cached__ = pyc mod.__loader__ = self py.builtin.exec_(co, mod.__dict__) except: del sys.modules[name] raise return sys.modules[name]
def basicTypeSpecialFunction(cv): """If you're in a number or string (which has no metadata), move up to the AST to make the special functions work.""" if isinstance(cv, SwapVector) or isinstance(cv, MoveVector): return cv if (cv.path[0] in [('n', 'Number'), ('s', 'String'), ('id', 'Name'), ('arg', 'Argument'), ('value', 'Name Constant'), ('s', 'Bytes'), ('name', 'Alias')]): cvCopy = cv.deepcopy() cv.oldSubtree = deepcopy(cvCopy.traverseTree(cv.start)) if cv.path[0] == ('n', 'Number'): cv.newSubtree = ast.Num(cv.newSubtree) elif cv.path[0] == ('s', 'String'): cv.newSubtree = ast.Str(cv.newSubtree) elif cv.path[0] == ('id', 'Name'): cv.newSubtree = ast.Name(cv.newSubtree, cv.oldSubtree.ctx) elif cv.path[0] == ('arg', 'Argument'): cv.newSubtree = ast.arg(cv.newSubtree, cv.oldSubtree.annotation) elif cv.path[0] == ('value', 'Name Constant'): cv.newSubtree = ast.NameConstant(cv.newSubtree) elif cv.path[0] == ('s', 'Bytes'): cv.newSubtree = ast.Bytes(cv.newSubtree) elif cv.path[0] == ('name', 'Alias'): cv.newSubtree = ast.alias(cv.newSubtree, cv.oldSubtree.asname) cv.path = cv.path[1:] return cv
def combineConditionals(a): """When possible, combine conditional branches""" if not isinstance(a, ast.AST): return a elif type(a) == ast.If: for i in range(len(a.body)): a.body[i] = combineConditionals(a.body[i]) for i in range(len(a.orelse)): a.orelse[i] = combineConditionals(a.orelse[i]) # if a: if b: x can be - if a and b: x if (len(a.orelse) == 0) and (len(a.body) == 1) and \ (type(a.body[0]) == ast.If) and (len(a.body[0].orelse) == 0): a.test = ast.BoolOp(ast.And(combinedConditionalOp=True), [a.test, a.body[0].test], combinedConditional=True) a.body = a.body[0].body # if a: x elif b: x can be - if a or b: x elif (len(a.orelse) == 1) and \ (type(a.orelse[0]) == ast.If) and (len(a.orelse[0].orelse) == 0): if compareASTs(a.body, a.orelse[0].body, checkEquality=True) == 0: a.test = ast.BoolOp(ast.Or(combinedConditionalOp=True), [a.test, a.orelse[0].test], combinedConditional=True) a.orelse = [] return a else: return applyToChildren(a, combineConditionals)
def occursIn(sub, super): """Does the first AST occur as a subtree of the second?""" superStatementTypes = [ ast.Module, ast.Interactive, ast.Suite, ast.FunctionDef, ast.ClassDef, ast.For, ast.While, ast.If, ast.With, ast.Try, ast.ExceptHandler ] if (not isinstance(super, ast.AST)): return False if type(sub) == type(super) and compareASTs(sub, super, checkEquality=True) == 0: return True # we know that a statement can never occur in an expression # (or in a non-statement-holding statement), so cut the search off now to save time. if isStatement(sub) and type(super) not in superStatementTypes: return False for child in ast.iter_child_nodes(super): if occursIn(sub, child): return True return False
def _translate_if(self, test, orelse, body, location, base=True): test_node = self._testable(self._translate_node(test)) block = self._translate_node(body) #block [self._translate_node(child) for child in body] if orelse and len(orelse) == 1 and isinstance(orelse[0], ast.If): otherwise = self._translate_if(orelse[0].test, orelse[0].orelse, orelse[0].body, location, False) elif orelse: otherwise = { 'type': 'else_statement', 'block': self._translate_node(orelse), #block [self._translate_node(node) for node in orelse], 'pseudo_type': 'Void' } else: otherwise = None return { 'type': 'if_statement' if base else 'elseif_statement', 'test': test_node, 'block': block, 'pseudo_type': 'Void', 'otherwise': otherwise }
def remove_id_assignment(self, JOIN, cfg_node): lvars = list() if isinstance(cfg_node, BBorBInode): lvars.append(cfg_node.left_hand_side) else: try: for expr in cfg_node.ast_node.targets: vv = VarsVisitor() vv.visit(expr) lvars.extend(vv.result) except AttributeError: # If it is AugAssign vv = VarsVisitor() vv.visit(cfg_node.ast_node.target) lvars.extend(vv.result) for var in lvars: if var in self.lattice.get_elements(JOIN): # Remove var from JOIN JOIN = JOIN ^ self.lattice.el2bv[var] return JOIN
def add_vars_conditional(self, JOIN, cfg_node): varse = None if isinstance(cfg_node.ast_node, ast.While): vv = VarsVisitor() vv.visit(cfg_node.ast_node.test) varse = vv.result elif self.is_output(cfg_node): vv = VarsVisitor() vv.visit(cfg_node.ast_node) varse = vv.result elif isinstance(cfg_node.ast_node, ast.If): vv = VarsVisitor() vv.visit(cfg_node.ast_node.test) varse = vv.result for var in varse: JOIN = JOIN | self.lattice.el2bv[var] return JOIN
def get_con_configuration(): """ Returns a tuple containing the currently active connection configuration. The method uses the configuration name stored in the attribute 'current_server' to retrieve the configuration values from the dictionary 'server_configuration'. Returns ------- tup : tuple or None If there is a configuration for the currently selected server, the method returns the tuple (db_host, db_port, db_name, db_password). If no configuration is available, the method returns None. """ if cfg.current_server in cfg.server_configuration: d = cfg.server_configuration[cfg.current_server] if d["type"] == SQL_MYSQL: return (d["host"], d["port"], d["type"], d["user"], d["password"]) elif d["type"] == SQL_SQLITE: return (None, None, SQL_SQLITE, None, None) else: return None
def get_resource(name, connection=None): """ Return a tuple containing the Resource, Corpus, and Lexicon of the corpus module specified by 'name'. Arguments --------- name : str The name of the corpus module connection : str or None The name of the database connection. If None, the current connection is used. Returns ------- res : tuple A tuple consisting of the Resource class, Corpus class, and Lexicon class defined in the corpus module """ if not connection: connection = cfg.current_server Resource, Corpus, Lexicon, _ = get_available_resources(connection)[name] return Resource, Corpus, Lexicon
def _If(self, t): self.fill("if ") self.dispatch(t.test) self.enter() self.dispatch(t.body) self.leave() # collapse nested ifs into equivalent elifs. while (t.orelse and len(t.orelse) == 1 and isinstance(t.orelse[0], ast.If)): t = t.orelse[0] self.fill("elif ") self.dispatch(t.test) self.enter() self.dispatch(t.body) self.leave() # final else if t.orelse: self.fill("else") self.enter() self.dispatch(t.orelse) self.leave()
def _UnaryOp(self, t): self.write("(") self.write(self.unop[t.op.__class__.__name__]) self.write(" ") # If we're applying unary minus to a number, parenthesize the number. # This is necessary: -2147483648 is different from -(2147483648) on # a 32-bit machine (the first is an int, the second a long), and # -7j is different from -(7j). (The first has real part 0.0, the second # has real part -0.0.) if isinstance(t.op, ast.USub) and isinstance(t.operand, ast.Num): self.write("(") self.dispatch(t.operand) self.write(")") else: self.dispatch(t.operand) self.write(")")
def visit_If(self, node): new_node = self._visit_if_while(node) if new_node is not None: return new_node if node.orelse and is_empty_body(node.orelse): self.log_node_removal("Remove dead code (empty else block of if)", node.orelse) new_node = copy_node(node) del new_node.orelse[:] node = new_node if is_empty_body(node.body) and not is_empty_body(node.orelse): self.log_node_removal("Remove dead code (empty if block)", node.body) new_node = copy_node(node) not_test = ast.UnaryOp(op=ast.Not(), operand=node.test) copy_lineno(node.test, not_test) new_node = ast.If(test=not_test, body=new_node.orelse, orelse=[]) copy_lineno(node, new_node) return new_node return node
def _If(self, t): self.fill("if ") self.dispatch(t.test) self.enter() self.dispatch(t.body) self.leave() # collapse nested ifs into equivalent elifs. while (t.orelse and len(t.orelse) == 1 and (isinstance(t.orelse[0], ast.If) or isinstance(t.orelse[0], typed_ast.ast3.If))): t = t.orelse[0] self.fill("elif ") self.dispatch(t.test) self.enter() self.dispatch(t.body) self.leave() # final else if t.orelse: self.fill("else") self.enter() self.dispatch(t.orelse) self.leave()
def vars_defined_in_all_cases(self, node): if isinstance(node, ast.If): vars_defined = None for if_node in u.ifs_in_elif_block(node): cur_vars_defined = self.vars_defined_in_all_cases(if_node.body) if vars_defined is None: vars_defined = cur_vars_defined else: vars_defined = vars_defined & cur_vars_defined elif isinstance(node, list): vars_defined = set() for stmt_node in node: vars_defined = vars_defined | self.vars_defined_in_all_cases(stmt_node) elif isinstance(node, ast.AST): vars_defined = set() if u.is_set_to(node): vars_defined.add(node.value.func.value.id) return vars_defined
def visit_If(self, ifstmt, is_nested=False): if is_nested: s = "} else if (%s) {\n" % (self.visit(ifstmt.test)) else: s = "if (%s) {\n" % (self.visit(ifstmt.test)) s += self.visit_block(ifstmt.body) if len(ifstmt.orelse) == 0: s += "}\n" else: if len(ifstmt.orelse) == 1 and isinstance(ifstmt.orelse[0], ast.If): s += self.visit_If(ifstmt.orelse[0], is_nested=True) else: s += "} else {\n" s += self.visit_block(ifstmt.orelse) s += "}\n" return s
def get_compound_bodies(node): """Returns a list of bodies of a compound statement node. Args: node: AST node. Returns: A list of bodies of the node. If the given node does not represent a compound statement, an empty list is returned. """ if isinstance(node, (ast.Module, ast.FunctionDef, ast.ClassDef, ast.With)): return [node.body] elif isinstance(node, (ast.If, ast.While, ast.For)): return [node.body, node.orelse] elif PY2 and isinstance(node, ast.TryFinally): return [node.body, node.finalbody] elif PY2 and isinstance(node, ast.TryExcept): return [node.body, node.orelse] + [h.body for h in node.handlers] elif PY3 and isinstance(node, ast.Try): return ([node.body, node.orelse, node.finalbody] + [h.body for h in node.handlers]) end return []
def runTest(self): """Makes a simple test of the output""" body = ast.parse(self.candidate_code, self.file_name, 'exec') code = compile(self.candidate_code, self.file_name, 'exec', optimize=0) exec(code) if_statements = [ node for node in ast.walk(body) if isinstance(node, ast.If) ] self.assertGreater(len(if_statements), 0, "Should have at least on if statement") self.assertMultiLineEqual(self.correct_output, self.__mockstdout.getvalue(), "Output should be correct")
def get_coverable_nodes(cls): return { ast.Assert, ast.Assign, ast.AugAssign, ast.Break, ast.Continue, ast.Delete, ast.Expr, ast.Global, ast.Import, ast.ImportFrom, ast.Nonlocal, ast.Pass, ast.Raise, ast.Return, ast.FunctionDef, ast.ClassDef, ast.TryExcept, ast.TryFinally, ast.ExceptHandler, ast.If, ast.For, ast.While, }
def get_coverable_nodes(cls): return { ast.Assert, ast.Assign, ast.AugAssign, ast.Break, ast.Continue, ast.Delete, ast.Expr, ast.Global, ast.Import, ast.ImportFrom, ast.Nonlocal, ast.Pass, ast.Raise, ast.Return, ast.ClassDef, ast.FunctionDef, ast.Try, ast.ExceptHandler, ast.If, ast.For, ast.While, }
def visit_If(self, node, start=True): if start: self.startline('if (') else: self.write('if (') self.visit(node.test) self.write(') {\n') self.visit_body(node.body) self.startline() self.endline('}') # Treat the else or else if clauses if node.orelse: if len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If): self.startline('else ') self.visit_If(node.orelse[0], False) else: self.startline('else {\n') self.visit_body(node.orelse) self.startline() self.endline('}') # # Expressions #
def _build_node_cfg(node): handlers = { ast.If: _build_if_cfg, ast.For: _build_loop_cfg, ast.While: _build_loop_cfg, ast.With: _build_with_cfg, ast.Break: _build_break_cfg, ast.Continue: _build_continue_cfg, ast.Return: _build_return_cfg, ast.Try: _build_try_cfg, } if type(node) in handlers: handler = handlers[type(node)] else: handler = _build_statement_cfg return handler(node)
def test_block_autofix(): # This transformer removes If nodes from statement blocks, # but it has no way to check whether the resulting body still has some nodes or not. # That's why the walker adds a Pass node automatically if after all the transformations # a statement block turns out to be empty. @ast_transformer def delete_ifs(node, **kwds): if isinstance(node, ast.If): return None else: return node node = get_ast(dummy_if) new_node = delete_ifs(node) assert_ast_equal(new_node, get_ast( """ def dummy_if(): pass """))
def translate(self, ctx): translation = [] scrutinee = ast.Name(id="__typy_with_scrutinee__") translation.extend( self.body_block.translate_assign( ctx, scrutinee)) pat = self.pat ctx_update = pat.ctx_update condition, binding_translations = ctx.translate_pat(pat, scrutinee) if astx.cond_vacuously_true(condition): for (id, trans) in binding_translations.iteritems(): translation.append(ast.Assign( targets=[ast.Name(id=ctx_update[id][0])], value=trans)) else: translation.append(ast.If( test=condition, body=list(_yield_binding_translation_assignments( binding_translations, ctx_update)), orelse=astx.expr_Raise_Exception_string("Match failure."))) return translation
def make_if(kwd, test, then, *rest): # (This'd be simpler with a different form of the grammar.) test = test(ast.Load()) if not rest: else_ = [] elif len(rest) == 1: else_ = rest[0] else: else_ = [make_if(*rest)] return ast.If(test, then, else_, lineno=kwd.start[0], col_offset=kwd.start[1])
def visit_Assert(self, t): return ast.If(t.test, [], [ast.Raise(Call(ast.Name('AssertionError', load), [] if t.msg is None else [t.msg]), None)])
def visit_ListComp(self, t): result_append = ast.Attribute(ast.Name('.0', load), 'append', load) body = ast.Expr(Call(result_append, [t.elt])) for loop in reversed(t.generators): for test in reversed(loop.ifs): body = ast.If(test, [body], []) body = ast.For(loop.target, loop.iter, [body], []) fn = [body, ast.Return(ast.Name('.0', load))] args = ast.arguments([ast.arg('.0', None)], None, [], None, [], []) return Call(Function('<listcomp>', args, fn), [ast.List([], load)])
def visit_Assert(self, t): t = self.generic_visit(t) result = ast.If(t.test, [], [ast.Raise(Call(ast.Name('AssertionError', load), [] if t.msg is None else [t.msg]), None)]) return ast.copy_location(result, t)
def visit_ListComp(self, t): t = self.generic_visit(t) add_element = ast.Attribute(ast.Name('.elements', load), 'append', load) body = ast.Expr(Call(add_element, [t.elt])) for loop in reversed(t.generators): for test in reversed(loop.ifs): body = ast.If(test, [body], []) body = ast.For(loop.target, loop.iter, [body], []) fn = [body, ast.Return(ast.Name('.elements', load))] args = ast.arguments([ast.arg('.elements', None)], None, [], None, [], []) result = Call(Function('<listcomp>', args, fn), [ast.List([], load)]) return ast.copy_location(result, t)
def _translate_body(self, body, types, allow_loose_in_edges=False, allow_loose_out_edges=False): cfg_factory = CFGFactory(self._id_gen) for child in body: if isinstance(child, (ast.AnnAssign, ast.Expr)): cfg_factory.add_stmts(self.visit(child, types)) elif isinstance(child, ast.If): cfg_factory.complete_basic_block() if_cfg = self.visit(child, types) cfg_factory.append_cfg(if_cfg) elif isinstance(child, ast.While): cfg_factory.complete_basic_block() while_cfg = self.visit(child, types) cfg_factory.append_cfg(while_cfg) elif isinstance(child, ast.Break): cfg_factory.complete_basic_block() break_cfg = self.visit(child, types) cfg_factory.append_cfg(break_cfg) elif isinstance(child, ast.Continue): cfg_factory.complete_basic_block() cont_cfg = self.visit(child, types) cfg_factory.append_cfg(cont_cfg) elif isinstance(child, ast.Pass): if cfg_factory.incomplete_block(): pass else: cfg_factory.append_cfg(_dummy_cfg(self._id_gen)) else: raise NotImplementedError(f"The statement {str(type(child))} is not yet translatable to CFG!") cfg_factory.complete_basic_block() if not allow_loose_in_edges and cfg_factory.cfg and cfg_factory.cfg.loose_in_edges: cfg_factory.prepend_cfg(_dummy_cfg(self._id_gen)) if not allow_loose_out_edges and cfg_factory.cfg and cfg_factory.cfg.loose_out_edges: cfg_factory.append_cfg(_dummy_cfg(self._id_gen)) return cfg_factory.cfg
def handle_or_else(self, orelse, test): """Handle the orelse part of an if node. Returns: The last nodes of the orelse branch """ if isinstance(orelse[0], ast.If): control_flow_node = self.visit(orelse[0]) self.add_elif_label(control_flow_node.test) test.connect(control_flow_node.test) return control_flow_node.last_nodes else: else_connect_statements = self.stmt_star_handler(orelse) test.connect(else_connect_statements.first_statement) return else_connect_statements.last_statements
def visit_BoolOp(self, boolop): res_var = self.variable() expl_list = self.assign(ast.List([], ast.Load())) app = ast.Attribute(expl_list, "append", ast.Load()) is_or = int(isinstance(boolop.op, ast.Or)) body = save = self.statements fail_save = self.on_failure levels = len(boolop.values) - 1 self.push_format_context() # Process each operand, short-circuting if needed. for i, v in enumerate(boolop.values): if i: fail_inner = [] # cond is set in a prior loop iteration below self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa self.on_failure = fail_inner self.push_format_context() res, expl = self.visit(v) body.append(ast.Assign([ast.Name(res_var, ast.Store())], res)) expl_format = self.pop_format_context(ast.Str(expl)) call = ast_Call(app, [expl_format], []) self.on_failure.append(ast.Expr(call)) if i < levels: cond = res if is_or: cond = ast.UnaryOp(ast.Not(), cond) inner = [] self.statements.append(ast.If(cond, inner, [])) self.statements = body = inner self.statements = save self.on_failure = fail_save expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or)) expl = self.pop_format_context(expl_template) return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
def visit_If(self, node): node = self.generic_visit(node) if (node.orelse and len(node.orelse) == 1 and isinstance(node.orelse[0], ast.Pass) ): node.orelse = [] if (len(node.body) == 1 and isinstance(node.body[0], ast.Pass) ): if node.orelse: node_test = ast.UnaryOp(op=ast.Not(), operand=node.test) if (len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If) ): node_test = ast.BoolOp\ ( op = ast.And() , values = [node_test, node.orelse[0].test] ) node.test = ast.copy_location(node_test, node.orelse[0].test) node.body = node.orelse[0].body node.orelse = node.orelse[0].orelse else: node.test = ast.copy_location(node_test, node.test) node.body = node.orelse node.orelse = [] else: node = None return node
def noneSpecialFunction(cv): """If the old type is 'None' (which won't show up in the original), move up in the AST to get the metadata""" if (not isinstance(cv, AddVector)) and cv.oldSubtree == None: cvCopy = cv.deepcopy() if cv.path[0] == ('value', 'Return'): cv.oldSubtree = deepcopy(cvCopy.traverseTree(cv.start)) cv.newSubtree = ast.Return(cv.newSubtree) cv.path = cv.path[1:] elif cv.path[0] == ('value', 'Name Constant'): cv.oldSubtree = deepcopy(cvCopy.traverseTree(cv.start)) cv.newSubtree = ast.NameConstant(cv.newSubtree) cv.path = cv.path[1:] elif cv.path[0] in [('lower', 'Slice'), ('upper', 'Slice'), ('step', 'Slice')]: tmpNew = cv.newSubtree cvCopy = cv.deepcopy() cv.oldSubtree = deepcopy(cvCopy.traverseTree(cv.start)) cv.newSubtree = deepcopy(cv.oldSubtree) # use the same slice if cv.path[0][0] == 'lower': cv.newSubtree.lower = tmpNew elif cv.path[0][0] == 'upper': cv.newSubtree.upper = tmpNew else: cv.newSubtree.step = tmpNew cv.path = cv.path[1:] # get rid of None and the val else: log("Individualize\tmapEdit\tMissing option in None special case 1: " + str(cv.path[0]), "bug") elif cv.oldSubtree == "None": cv.path = cv.path[1:] # get rid of None and the id cvCopy = cv.deepcopy() cv.oldSubtree = deepcopy(cvCopy.traverseTree(cv.start)) if cv.path[0] == ('value', 'Return'): cv.newSubtree = ast.Return(ast.Name(cv.newSubtree, ast.Load())) else: log("Individualize\tmapEdit\tMissing option in None special case 2: " + str(cv.path[0]), "bug") cv.path = cv.path[1:] return cv
def movedLineAfterSpecialFunction(cv, startingTree, startingPath, orig): """Sometimes, with Move Vectors, items that got combined are no longer combined. Fix this by moving up the tree.""" if isinstance(cv, MoveVector): cvCopy = cv.deepcopy() origSpot = deepcopy(cvCopy.traverseTree(cv.start)) if len(origSpot) <= cv.oldSubtree or len(origSpot) <= cv.newSubtree: cvCopy.path = startingPath[1:] parentSpot = deepcopy(cvCopy.traverseTree(startingTree)) if type(parentSpot) == ast.BoolOp: # Change this to a ChangeVector at the parent's level newSpot = deepcopy(parentSpot) newSpot.values.insert(cv.newSubtree, newSpot.values[cv.oldSubtree]) newSpot.values.pop(cv.oldSubtree + (0 if cv.oldSubtree < cv.newSubtree else 1)) # adjust for length change cv = ChangeVector(cv.path[2:], parentSpot, newSpot, cv.start) cv.wasMoveVector = True return cv elif cv.path[1][0] == 'body': # If we're in a set of statements lineToMove = parentSpot.body[cv.oldSubtree] # First, just delete this line if hasattr(lineToMove, "global_id"): path = generatePathToId(orig, lineToMove.global_id) else: log("Individualize\tmovedLineAfterSpecialFunction\tWhere is the global id? " + printFunction(lineToMove), "bug") firstEdit = DeleteVector(path, lineToMove, None, start=orig) # Then, add the line back in, but in the correct position newPath = [cv.newSubtree] + cv.path[1:] secondEdit = AddVector(newPath, None, lineToMove, start=cv.start) return [firstEdit, secondEdit] else: log("Individualize\tmapEdit\tMissing option in Move Vector special case: " + str(type(parentSpot)), "bug") return cv
def anonymizeNames(a, namesToKeep, imports): """Anonymize all of variables/names that occur in the given AST""" """If we run this on an anonymized AST, it will fix the names again to get rid of any gaps!""" if type(a) != ast.Module: return a globalMap = { } for var in namesToKeep: globalMap[var] = var anonymizeStatementNames(a, globalMap, "", imports, goBackwards=True) return a
def cleanupEquals(a): """Gets rid of silly blah == True statements that students make""" if not isinstance(a, ast.AST): return a if type(a) == ast.Call: a.func = cleanupEquals(a.func) for i in range(len(a.args)): # But test expressions don't carry through to function arguments a.args[i] = cleanupEquals(a.args[i]) return a elif type(a) == ast.Compare and type(a.ops[0]) in [ast.Eq, ast.NotEq]: l = a.left = cleanupEquals(a.left) r = cleanupEquals(a.comparators[0]) a.comparators = [r] if type(l) == ast.NameConstant and l.value in [True, False]: (l,r) = (r,l) # If we have (boolean expression) == True if type(r) == ast.NameConstant and r.value in [True, False] and (eventualType(l) == bool): # Matching types if (type(a.ops[0]) == ast.Eq and r.value == True) or \ (type(a.ops[0]) == ast.NotEq and r.value == False): transferMetaData(a, l) # make sure to keep the original location return l else: tmp = ast.UnaryOp(ast.Not(addedNotOp=True), l) transferMetaData(a, tmp) return tmp else: return a else: return applyToChildren(a, cleanupEquals)
def cleanupBoolOps(a): """When possible, combine adjacent boolean expressions""" """Note- we are assuming that all ops are the first op (as is done in the simplify function)""" if not isinstance(a, ast.AST): return a if type(a) == ast.BoolOp: allTypesWork = True for i in range(len(a.values)): a.values[i] = cleanupBoolOps(a.values[i]) if eventualType(a.values[i]) != bool or hasattr(a.values[i], "multiComp"): allTypesWork = False # We can't reduce if the types aren't all booleans if not allTypesWork: return a i = 0 while i < len(a.values) - 1: current = a.values[i] next = a.values[i+1] # (a and b and c and d) or (a and e and d) == a and ((b and c) or e) and d if type(current) == type(next) == ast.BoolOp: if type(current.op) == type(next.op): minlength = min(len(current.values), len(next.values)) # shortest length # First, check for all identical values from the front j = 0 while j < minlength: if compareASTs(current.values[j], next.values[j], checkEquality=True) != 0: break j += 1 # Same values in both, so get rid of the latter line if j == len(current.values) == len(next.values): a.values.pop(i+1) continue i += 1 ### If reduced to one item, just return that item return a.values[0] if (len(a.values) == 1) else a return applyToChildren(a, cleanupBoolOps)
def cleanupTypes(a): """Remove any unneccessary type mappings""" if not isinstance(a, ast.AST): return a # No need to cast something if it'll be changed anyway by a binary operation if type(a) == ast.BinOp: a.left = cleanupTypes(a.left) a.right = cleanupTypes(a.right) # Ints become floats naturally if eventualType(a.left) == eventualType(a.right) == float: if type(a.right) == ast.Call and type(a.right.func) == ast.Name and \ a.right.func.id == "float" and len(a.right.args) == 1 and len(a.right.keywords) == 0 and \ eventualType(a.right.args[0]) in [int, float]: a.right = a.right.args[0] elif type(a.left) == ast.Call and type(a.left.func) == ast.Name and \ a.left.func.id == "float" and len(a.left.args) == 1 and len(a.left.keywords) == 0 and \ eventualType(a.left.args[0]) in [int, float]: a.left = a.left.args[0] return a elif type(a) == ast.Call and type(a.func) == ast.Name and len(a.args) == 1 and len(a.keywords) == 0: a.func = cleanupTypes(a.func) a.args = [cleanupTypes(a.args[0])] # If the type already matches, no need to cast it funName = a.func.id argType = eventualType(a.args[0]) if type(a.func) == ast.Name: if (funName == "float" and argType == float) or \ (funName == "int" and argType == int) or \ (funName == "bool" and argType == bool) or \ (funName == "str" and argType == str): return a.args[0] return applyToChildren(a, cleanupTypes)
def getIfBranches(a): """Gets all the branches of an if statement. Will only work if each else has a single line""" if type(a) != ast.If: return None if len(a.orelse) == 0: return [a] elif len(a.orelse) == 1: tmp = getIfBranches(a.orelse[0]) if tmp == None: return None return [a] + tmp else: return None
def isStatement(a): """Determine whether the given node is a statement (vs an expression)""" return type(a) in [ ast.Module, ast.Interactive, ast.Expression, ast.Suite, ast.FunctionDef, ast.ClassDef, ast.Return, ast.Delete, ast.Assign, ast.AugAssign, ast.For, ast.While, ast.If, ast.With, ast.Raise, ast.Try, ast.Assert, ast.Import, ast.ImportFrom, ast.Global, ast.Expr, ast.Pass, ast.Break, ast.Continue ]
def handle_or_else(self, orelse, test): """Handle the orelse part of an if or try node. Returns: The last nodes of the orelse branch. """ if isinstance(orelse[0], ast.If): control_flow_node = self.visit(orelse[0]) self.add_elif_label(control_flow_node.test) test.connect(control_flow_node.test) return control_flow_node.last_nodes else: else_connect_statements = self.stmt_star_handler(orelse, prev_node_to_avoid=self.nodes[-1]) test.connect(else_connect_statements.first_statement) return else_connect_statements.last_statements
def is_condition(self, cfg_node): if isinstance(cfg_node.ast_node, (ast.If, ast.While)): return True elif self.is_output(cfg_node): return True return False