我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用ast.BinOp()。
def __init__(self, expr, context): self.expr = expr self.context = context self.expr_table = { LLLnode: self.get_expr, ast.Num: self.number, ast.Str: self.string, ast.NameConstant: self.constants, ast.Name: self.variables, ast.Attribute: self.attribute, ast.Subscript: self.subscript, ast.BinOp: self.arithmetic, ast.Compare: self.compare, ast.BoolOp: self.boolean_operations, ast.UnaryOp: self.unary_operations, ast.Call: self.call, ast.List: self.list_literals, ast.Dict: self.struct_literals, ast.Tuple: self.tuple_literals, } expr_type = self.expr.__class__ if expr_type in self.expr_table: self.lll_node = self.expr_table[expr_type]() else: raise Exception("Unsupported operator: %r" % ast.dump(self.expr))
def pop_format_context(self, expl_expr): """Format the %-formatted string with current format context. The expl_expr should be an ast.Str instance constructed from the %-placeholders created by .explanation_param(). This will add the required code to format said string to .on_failure and return the ast.Name instance of the formatted string. """ current = self.stack.pop() if self.stack: self.explanation_specifiers = self.stack[-1] keys = [ast.Str(key) for key in current.keys()] format_dict = ast.Dict(keys, list(current.values())) form = ast.BinOp(expl_expr, ast.Mod(), format_dict) name = "@py_format" + str(next(self.variable_counter)) self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form)) return ast.Name(name, ast.Load())
def visit_BinOp(self, node: ast.BinOp) -> ast.BinOp: node = self.generic_visit(node) if self._is_numeric_mult(node): if isinstance(node.right, ast.Num): if node.right.n == 0: node = ast.copy_location(ast.Num(n = 0), node) elif node.right.n == 1: node = node.left elif node.right.n == 2: node.op = ast.copy_location(ast.Add(), node.op) node.right = copy(node.left) elif isinstance(node.left , ast.Num): if node.left.n == 0: node = ast.copy_location(ast.Num(n = 0), node) elif node.left.n == 1: node = node.right elif node.left.n == 2: node.op = ast.copy_location(ast.Add(), node.op) node.left = copy(node.right) return node
def _is_numeric_pow(self, node: ast.BinOp) -> bool: if isinstance(node.op, ast.Pow): left, right = node.left, node.right if isinstance(left, (ast.Name, ast.Num)): if isinstance(right, ast.Num): degree = right.n elif isinstance(right, ast.UnaryOp)\ and isinstance(right.op, (ast.USub, ast.UAdd))\ and isinstance(right.operand, ast.Num): degree = right.operand.n else: return False if isinstance(degree, float): degree = int(degree) if degree.is_integer() else degree return isinstance(degree, int) return False
def eval_expr(expr): """ Eval and expression inside a #define using a suppart of python grammar """ def _eval(node): if isinstance(node, ast.Num): return node.n elif isinstance(node, ast.BinOp): return OPERATORS[type(node.op)](_eval(node.left), _eval(node.right)) elif isinstance(node, ast.UnaryOp): return OPERATORS[type(node.op)](_eval(node.operand)) elif isinstance(node, ast.BoolOp): values = [_eval(x) for x in node.values] return OPERATORS[type(node.op)](**values) else: raise TypeError(node) return _eval(ast.parse(expr, mode='eval').body)
def test_increment_lineno(self): src = ast.parse('1 + 1', mode='eval') self.assertEqual(ast.increment_lineno(src, n=3), src) self.assertEqual(ast.dump(src, include_attributes=True), 'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), ' 'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, ' 'col_offset=0))' ) # issue10869: do not increment lineno of root twice src = ast.parse('1 + 1', mode='eval') self.assertEqual(ast.increment_lineno(src.body, n=3), src.body) self.assertEqual(ast.dump(src, include_attributes=True), 'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), ' 'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, ' 'col_offset=0))' )
def get_type(self, node): if isinstance(node, ast.Num): return Type.NUMBER elif isinstance(node, ast.Str): return Type.STRING elif isinstance(node, ast.Name): if self.variables[node.id] is not None: return self.variables[node.id].var_type else: return Type.VOID elif isinstance(node, ast.BinOp): if self.get_type(node.left).is_number and self.get_type(node.right).is_number: return Type.NUMBER elif self.get_type(node.left).is_string or self.get_type(node.right).is_string: return Type.STRING elif isinstance(node, ast.Call): return self.functions[node.func.id].return_type else: return Type.VOID
def _solve(self): import_aliases = (self.context._context['import_aliases'] if self.context else None) cursor_node = self.tainted_node.parent while cursor_node != self.target_node: test_node = cursor_node cursor_node = cursor_node.parent if isinstance(test_node, ast.BinOp): continue elif isinstance(test_node, ast.Call): if isinstance(test_node.func, ast.Attribute) and isinstance(test_node.func.value, ast.Str) and test_node.func.attr == 'format': return True function = s_utils.get_call_function(test_node, import_aliases=import_aliases) if function in ('os.path.abspath', 'os.path.join', 'str'): continue elif function == 'os.path.relpath' and s_utils.node_is_child_of_parent(test_node.args[0], self.tainted_node): continue elif isinstance(test_node, ast.Subscript): continue return False return True
def _evaluate_ast(node): wrapper = None statement = '' if isinstance(node.parent, ast.BinOp): out = utils.concat_string(node, node.parent) wrapper = out[0].parent statement = out[1] elif (isinstance(node.parent, ast.Attribute) and node.parent.attr == 'format'): statement = node.s # Hierarchy for "".format() is Wrapper -> Call -> Attribute -> Str wrapper = node.parent.parent.parent if isinstance(wrapper, ast.Call): # wrapped in "execute" call? names = ['execute', 'executemany'] name = utils.get_called_name(wrapper) return (name in names, statement) else: return (False, statement)
def check_call_visitor(self, visitor): tree = ast.parse("1+1") with self.assertRaises(Exception) as cm: visitor.visit(tree) binop = tree.body[0].value what = ast.dump(binop) self.assertEqual(str(cm.exception), 'error at <string>:1 on visiting %s: bug' % what) # Test truncature of the AST dump with mock.patch('fatoptimizer.tools.COMPACT_DUMP_MAXLEN', 5): with self.assertRaises(Exception) as cm: visitor.visit(tree) what = 'BinOp(...)' self.assertEqual(str(cm.exception), 'error at <string>:1 on visiting %s: bug' % what)
def visit_Compare(self, node, **kwargs): ops = node.ops comps = node.comparators # base case: we have something like a CMP b if len(comps) == 1: op = self.translate_In(ops[0]) binop = ast.BinOp(op=op, left=node.left, right=comps[0]) return self.visit(binop) # recursive case: we have a chained comparison, a CMP b CMP c, etc. left = node.left values = [] for op, comp in zip(ops, comps): new_node = self.visit(ast.Compare(comparators=[comp], left=left, ops=[self.translate_In(op)])) left = comp values.append(new_node) return self.visit(ast.BoolOp(op=ast.And(), values=values))
def eval_numeric_constexpr(node: ast.AST) -> int: if isinstance(node, ast.Num): return node.n if isinstance(node, ast.UnaryOp): if isinstance(node.op, ast.UAdd): return +eval_numeric_constexpr(node.operand) elif isinstance(node.op, ast.USub): return -eval_numeric_constexpr(node.operand) else: return None if isinstance(node, ast.BinOp): if isinstance(node.op, ast.Add): return eval_numeric_constexpr(node.left) + eval_numeric_constexpr(node.right) if isinstance(node.op, ast.Sub): return eval_numeric_constexpr(node.left) - eval_numeric_constexpr(node.right) if isinstance(node.op, ast.Mult): return eval_numeric_constexpr(node.left) * eval_numeric_constexpr(node.right) if isinstance(node.op, ast.Div): return eval_numeric_constexpr(node.left) / eval_numeric_constexpr(node.right) return None
def visit_ExceptHandler(self, node): node_name = None if isinstance(node.name, ast.Name): # Python 2 node_name = node.name.id elif isinstance(node.name, str): # Python 3 node_name = node.name if node_name in builtin_exception_types: yield self.tag(node, 'except-shadows-builtin', node_name) if node.type is None: ex_types = [] elif isinstance(node.type, ast.Tuple): ex_types = list(node.type.elts) else: ex_types = [node.type] for ex_type in ex_types: while isinstance(ex_type, ast.BinOp): ex_type = ex_type.left if isinstance(ex_type, ast.Str): yield self.tag(node, 'string-exception') break for t in self.generic_visit(node): yield t
def eval_expr(expr): import ast import operator as op op = { ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul, ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor, ast.USub: op.neg, } def eval_(node): if isinstance(node, ast.Num): return fractions.Fraction(node.n) elif isinstance(node, ast.BinOp): return op[type(node.op)](eval_(node.left), eval_(node.right)) elif isinstance(node, ast.UnaryOp): return op[type(node.op)](eval_(node.operand)) raise TypeError(node) return eval_(ast.parse(str(expr), mode='eval').body)
def _process_function_signature(stmt, arg_names, static_env): return_type = Ellipsis if isinstance(stmt, ast.Expr): value = stmt.value if isinstance(value, ast.BinOp): left, op, right = value.left, value.op, value.right if isinstance(op, ast.RShift): arg_types = fn._process_argument_signature(left, arg_names, static_env) return_type = static_env.eval_expr_ast(right) else: return None elif isinstance(value, ast.Dict) or isinstance(value, ast.Set): arg_types = fn._process_argument_signature(value, arg_names, static_env) else: return None else: return None if arg_types is None: return None return (arg_types, return_type)
def parse_unit(item): if isinstance(item, ast.Name): if item.id not in valid_units: raise InvalidTypeException("Invalid base unit", item) return {item.id: 1} elif isinstance(item, ast.Num) and item.n == 1: return {} elif not isinstance(item, ast.BinOp): raise InvalidTypeException("Invalid unit expression", item) elif isinstance(item.op, ast.Mult): left, right = parse_unit(item.left), parse_unit(item.right) return combine_units(left, right) elif isinstance(item.op, ast.Div): left, right = parse_unit(item.left), parse_unit(item.right) return combine_units(left, right, div=True) elif isinstance(item.op, ast.Pow): if not isinstance(item.left, ast.Name): raise InvalidTypeException("Can only raise a base type to an exponent", item) if not isinstance(item.right, ast.Num) or not isinstance(item.right.n, int) or item.right.n <= 0: raise InvalidTypeException("Exponent must be positive integer", item) return {item.left.id: item.right.n} else: raise InvalidTypeException("Invalid unit expression", item) # Parses an expression representing a type. Annotation refers to whether # the type is to be located in memory or storage
def aug_assign(self): target = self.get_target(self.stmt.target) sub = Expr.parse_value_expr(self.stmt.value, self.context) if not isinstance(self.stmt.op, (ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod)): raise Exception("Unsupported operator for augassign") if not isinstance(target.typ, BaseType): raise TypeMismatchException("Can only use aug-assign operators with simple types!", self.stmt.target) if target.location == 'storage': o = Expr.parse_value_expr(ast.BinOp(left=LLLnode.from_list(['sload', '_stloc'], typ=target.typ, pos=target.pos), right=sub, op=self.stmt.op, lineno=self.stmt.lineno, col_offset=self.stmt.col_offset), self.context) return LLLnode.from_list(['with', '_stloc', target, ['sstore', '_stloc', base_type_conversion(o, o.typ, target.typ)]], typ=None, pos=getpos(self.stmt)) elif target.location == 'memory': o = Expr.parse_value_expr(ast.BinOp(left=LLLnode.from_list(['mload', '_mloc'], typ=target.typ, pos=target.pos), right=sub, op=self.stmt.op, lineno=self.stmt.lineno, col_offset=self.stmt.col_offset), self.context) return LLLnode.from_list(['with', '_mloc', target, ['mstore', '_mloc', base_type_conversion(o, o.typ, target.typ)]], typ=None, pos=getpos(self.stmt))
def visit_BinOp(self, binop): symbol = binop_map[binop.op.__class__] left_expr, left_expl = self.visit(binop.left) right_expr, right_expl = self.visit(binop.right) explanation = "(%s %s %s)" % (left_expl, symbol, right_expl) res = self.assign(ast.BinOp(left_expr, binop.op, right_expr)) return res, explanation
def _is_numeric_mult(self, node: ast.BinOp) -> bool: if isinstance(node.op, ast.Mult): if isinstance(node.left , (ast.Name, ast.Num)) \ and isinstance(node.right, ast.Num): return True if isinstance(node.right, (ast.Name, ast.Num)) \ and isinstance(node.left , ast.Num): return True return False
def visit_BinOp(self, node: ast.BinOp): node = self.generic_visit(node) if self._is_numeric_pow(node): left, right = node.left, node.right degree = ( right.n if isinstance(right, ast.Num) else -right.operand.n if isinstance(right.op, ast.USub) else right.operand.n ) degree = int(degree) if abs(degree) == 0: node = ast.copy_location(ast.Num(n = 1), node) elif abs(degree) == 1: node = node.left elif 2 <= abs(degree) <= self.MAX_DEGREE: for _ in range(1, abs(degree)): new_node = ast.BinOp\ ( left = left , op = ast.Mult() , right = copy(node.left) ) left = new_node = ast.copy_location(new_node, node) node = new_node else: return node if degree < 0: new_node = ast.BinOp\ ( left = ast.Num(n = 1) , op = ast.Div() , right = node ) node = ast.copy_location(new_node, node) return node
def listNotEmpty(a): """Determines that the iterable is NOT empty, if we can know that""" """Used for For objects""" if not isinstance(a, ast.AST): return False if type(a) == ast.Call: if type(a.func) == ast.Name and a.func.id in ["range"]: if len(a.args) == 1: # range(x) return type(a.args[0]) == ast.Num and type(a.args[0].n) != complex and a.args[0].n > 0 elif len(a.args) == 2: # range(start, x) if type(a.args[0]) == ast.Num and type(a.args[1]) == ast.Num and \ type(a.args[0].n) != complex and type(a.args[1].n) != complex and \ a.args[0].n < a.args[1].n: return True elif type(a.args[1]) == ast.BinOp and type(a.args[1].op) == ast.Add: if type(a.args[1].right) == ast.Num and type(a.args[1].right) != complex and a.args[1].right.n > 0 and \ compareASTs(a.args[0], a.args[1].left, checkEquality=True) == 0: return True elif type(a.args[1].left) == ast.Num and type(a.args[1].left) != complex and a.args[1].left.n > 0 and \ compareASTs(a.args[0], a.args[1].right, checkEquality=True) == 0: return True elif type(a) in [ast.List, ast.Tuple]: return len(a.elts) > 0 elif type(a) == ast.Str: return len(a.s) > 0 return False
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 _translate_augassign(self, target, op, value, location): return self._translate_assign([target], ast.BinOp(target, op, value), location)
def _binop(self, other, *, _opnode=opnode, _sym=sym): othername, other, constants = _normalize_arg( other, self._constants, ) return __class__( '%s %s %s' % (self._pname, _sym, othername), ast.BinOp( left=self._tree, op=_opnode(), right=other, ), merge(constants, getattr(other, '_constants', {})), )
def visit_AugAssign(self, node): if node.op.__class__ != ast.FloorDiv: return node dummy_op = ast.BinOp(left=node.target, op=ast.Div(), right=node.value) dummy_int = ast.Name(id="int", ctx=ast.Load()) dummy_call = ast.Call(func=dummy_int, args=[dummy_op], keywords=[], starargs=None, kwargs=None) return ast.Assign(targets=[node.target], value=dummy_call)
def visit_BinOp(self, node): if node.op.__class__ != ast.FloorDiv: return node dummy_op = ast.BinOp(left=node.left, op=ast.Div(), right=node.right) dummy_int = ast.Name(id="int", ctx=ast.Load()) return ast.Call(func=dummy_int, args=[dummy_op], keywords=[], starargs=None, kwargs=None)
def test_copy_location(self): src = ast.parse('1 + 1', mode='eval') src.body.right = ast.copy_location(ast.Num(2), src.body.right) self.assertEqual(ast.dump(src, include_attributes=True), 'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), ' 'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, ' 'col_offset=0))' )
def get_type(self, node): if isinstance(node, ast.BinOp): left_type = self.get_type(node.left) right_type = self.get_type(node.right) if isinstance(node.op, ast.Add): if left_type.is_number and right_type.is_number: return Type.NUMBER else: return Type.STRING elif left_type.is_number and right_type.is_number: return Type.NUMBER else: raise CompileError("Can not '%s' operator with string." % node.op.__class__.__name__) elif isinstance(node, ast.UnaryOp): if isinstance(operand, ast.Num): return Type.NUMBER else: raise SyntaxNotSupportError("Not support unary operator except number.") elif isinstance(node, ast.Num): return Type.NUMBER elif isinstance(node, ast.Str): return Type.STRING elif isinstance(node, ast.List): return Type.LIST elif isinstance(node, ast.Call): args_type = [self.get_type(arg) for arg in node.args] return self.get_function_return_type(node.func.id, args_type) elif isinstance(node, ast.Name): return self.variables[node.id].var_type
def eval_(node): """Calculate a mathematical expression.""" if isinstance(node, ast.Num): # <number> return node.n elif isinstance(node, ast.BinOp): # <left> <operator> <right> return operators[type(node.op)](eval_(node.left), eval_(node.right)) elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1 return operators[type(node.op)](eval_(node.operand)) else: raise TypeError(node)
def _is_range_op(self, node): return isinstance(node, ast.BinOp) and isinstance(node.op, self.range_op)
def concat_string(node, stop=None): '''Builds a string from a ast.BinOp chain. This will build a string from a series of ast.Str nodes wrapped in ast.BinOp nodes. Something like "a" + "b" + "c" or "a %s" % val etc. The provided node can be any participant in the BinOp chain. :param node: (ast.Str or ast.BinOp) The node to process :param stop: (ast.Str or ast.BinOp) Optional base node to stop at :returns: (Tuple) the root node of the expression, the string value ''' def _get(node, bits, stop=None): if node != stop: bits.append( _get(node.left, bits, stop) if isinstance(node.left, ast.BinOp) else node.left) bits.append( _get(node.right, bits, stop) if isinstance(node.right, ast.BinOp) else node.right) bits = [node] while isinstance(node.parent, ast.BinOp): node = node.parent if isinstance(node, ast.BinOp): _get(node, bits, stop) return (node, " ".join([x.s for x in bits if isinstance(x, ast.Str)]))
def raw_str_sql_expressions(context): str_node = context.node if isinstance(str_node.parent, ast.BinOp): # avoid duplicates findings with B9101 return return _check_string_for_sql(context.node, confidence=bandit.LOW)
def test_shift_error(self): self.check_dont_optimize_func("1 << -3", ast.BinOp(left=ast.Num(n=1), op=ast.LShift(), right=ast.Num(-3))) self.check_dont_optimize_func("1 >> -3", ast.BinOp(left=ast.Num(n=1), op=ast.RShift(), right=ast.Num(-3)))
def test_pow(self): self.check_optimize_func("2 ** 3", "8") self.check_optimize_func("2.0 ** 3.0", "8.0") # complex self.check_dont_optimize_func("2.0j ** 3.0") self.check_dont_optimize_func("2.0 ** 3.0j") # 0 ** -1 self.check_dont_optimize_func("0 ** -1", ast.BinOp(left=ast.Num(n=0), op=ast.Pow(), right=ast.Num(-1))) self.check_dont_optimize_func("0.0 ** -1", ast.BinOp(left=ast.Num(n=0.0), op=ast.Pow(), right=ast.Num(-1)))