From 6b0541bf03dc83713a02c9c3c454df5bf5ec3707 Mon Sep 17 00:00:00 2001 From: Sfan5 Date: Thu, 23 Jan 2014 21:42:27 +0100 Subject: [PATCH] [Calc] Use eval() because I do not want to write a python parser --- calc.py | 74 +++++++++++++-------------------------------------------- 1 file changed, 16 insertions(+), 58 deletions(-) diff --git a/calc.py b/calc.py index 014ebe5..5e9e936 100755 --- a/calc.py +++ b/calc.py @@ -10,67 +10,23 @@ import operator as op import math import random -# http://stackoverflow.com/questions/2371436/evaluating-a-mathematical-expression-in-a-string/9558001#9558001 -operators = { - ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul, ast.Pow: op.pow, - ast.Div: op.truediv, ast.BitXor: op.xor, ast.Mod: op.mod -} - -funcs = { +env = { "bin": bin, "abs": abs, "oct": oct, "int": int, "sum": sum, "tuple": tuple, "divmod": divmod, "hash": hash, "hex": hex, "len": len, "list": list, "long": long, "max": max, - "range": range, "round": round, "min": min, "map": map, - - # random functions - "betavariate": random.betavariate, "choice": random.choice, - "expovariate": random.expovariate, "gammavariate": random.gammavariate, - "gauss": random.gauss, "getrandbits": random.getrandbits, - "lognormvariate": random.lognormvariate, "normalvariate": random.normalvariate, - "paretovariate": random.paretovariate, "randint": random.randint, - "random": random.random, "randrange": random.randrange, - "sample": random.sample, "shuffle": random.shuffle, - "triangular": random.triangular, "uniform": random.uniform, - "vonmisesvariate": random.vonmisesvariate, "weibullvariate": random.weibullvariate + "range": range, "round": round, "min": min, "map": map } -for funcn in dir(math): - if funcn.startswith("_"): - continue - funcs[funcn] = getattr(math, funcn) +libs = [ + 'math', 'random' +] -def getfunc(fn): - if fn in funcs: - return funcs[fn] - else: - raise ValueError("Function not known: '" + str(fn) + "'") - -def get_kwargs(kwrds): - kwargs = {} - for kw in kwrds: - kwargs[kw.arg] = eval_astnode(kw.value) - return kwargs - -def eval_strexpr(expr): - return eval_astnode(ast.parse(expr).body[0].value) # Module(body=[Expr(value=...)]) - -def eval_astnode(node): - if isinstance(node, ast.Num): # - return node.n - elif isinstance(node, ast.operator): # - return operators[type(node)] - elif isinstance(node, ast.BinOp): # - return eval_astnode(node.op)(eval_astnode(node.left), eval_astnode(node.right)) - elif isinstance(node, ast.Call): # ( ) - return getfunc(node.func.id)(*(eval_astnode(e) for e in node.args), **get_kwargs(node.keywords)) - elif isinstance(node, ast.Tuple): # ( , , [...] ) - return tuple(eval_astnode(e) for e in node.elts) - elif isinstance(node, ast.List): # [ , , [...] ] - return list(eval_astnode(e) for e in node.elts) - elif isinstance(node, ast.Str): # ('|") ('|") - return node.s - else: - raise TypeError("AST node type not allowed: '" + type(node).__name__ + "'") +for lib in libs: + env[lib] = {} + for funcn in dir(globals()[lib]): + if funcn.startswith("_"): + continue + env[lib][funcn] = getattr(globals()[lib], funcn) def c(phenny, input): for x in phenny.bot.commands["high"].values(): @@ -79,12 +35,14 @@ def c(phenny, input): return # Abort function if not input.group(2): return phenny.reply("Nothing to calculate.") - q = input.group(2).encode('utf-8') + q = input.group(2).encode('ascii', 'ignore') + if '__' in q: + phenny.reply("Sorry, but no double underscores.") print("[LOG]: %s calculated '%s'" % (input.nick, q)) try: - phenny.say(repr(eval_strexpr(q))) + phenny.say(repr(eval(q, {'__builtins__': env}, {}))) except Exception as e: - phenny.say("Exception: " + str(e)) + phenny.say(type(e).__name__ + ": " + str(e)) c.commands = ['c'] c.example = '.c 5 + 3'