def calc_eval(node): """ Actually do the calculation. """ if isinstance(node, ast.Expr): # Top level expression return calc_eval(node.value) elif isinstance(node, ast.Load): # ignore return elif isinstance(node, ast.Name): # <constant> if node.id in constants: return constants[node.id] else: raise NotImplementedError(node.id) elif isinstance(node, ast.NameConstant): return node.value elif isinstance(node, ast.Num): # <number> return node.n elif (isinstance(node, ast.operator) or isinstance(node, ast.unaryop) or isinstance(node, ast.cmpop)): # <operator> if type(node) in operators: return operators[type(node)] else: raise KeyError(type(node).__name__) elif isinstance(node, ast.UnaryOp): # <operator> <operand> return calc_eval(node.op)(calc_eval(node.operand)) elif isinstance(node, ast.BinOp): # <left> <operator> <right> return calc_eval(node.op)(calc_eval(node.left), calc_eval(node.right)) elif isinstance(node, ast.Compare): # boolean comparisons are more tricky comparisons = zip(node.ops, pairwise([node.left] + node.comparators)) return all(calc_eval(op)(calc_eval(left), calc_eval(right)) for op, (left, right) in comparisons) else: raise TypeError(node)
def visit_Compare(self, node): comparisons = zip(node.ops, pairwise([node.left] + node.comparators)) try: return all(operators[op.__class__](self.visit(left), self.visit(right)) for op, (left, right) in comparisons) except KeyError: raise CalcError("invalid operator")
def calc_eval(node): """Actually do the calculation. """ # ast.Load is always preceded by something else assert not isinstance(node, ast.Load) if isinstance(node, ast.Expr): # Top level expression return calc_eval(node.value) elif isinstance(node, ast.Name): # <constant> if node.id in identifiers: return identifiers[node.id] else: raise NotImplementedError(node.id) elif isinstance(node, ast.Call): eval_args = [calc_eval(arg) for arg in node.args] try: return calc_eval(node.func)(*eval_args) except TypeError as ex: raise ValueError(str(ex)) elif isinstance(node, ast.NameConstant): return node.value elif isinstance(node, ast.Num): # <number> return node.n elif (isinstance(node, ast.operator) or isinstance(node, ast.unaryop) or isinstance(node, ast.cmpop)): # <operator> if type(node) in operators: return operators[type(node)] else: raise KeyError(type(node).__name__.lower()) elif isinstance(node, ast.UnaryOp): # <operator> <operand> return calc_eval(node.op)(calc_eval(node.operand)) elif isinstance(node, ast.BinOp): # <left> <operator> <right> return calc_eval(node.op)(calc_eval(node.left), calc_eval(node.right)) elif isinstance(node, ast.Compare): # boolean comparisons are more tricky comparisons = zip(node.ops, pairwise([node.left] + node.comparators)) return all(calc_eval(op)(calc_eval(left), calc_eval(right)) for op, (left, right) in comparisons) else: raise TypeError(node)