@@ -274,6 +274,36 @@ def safe_eval(self, expr):
274274 ast .USub : operator .neg
275275 }
276276
277+ constants = {
278+ "e" : math .e ,
279+ "pi" : math .pi ,
280+ "tau" : math .tau ,
281+ }
282+
283+ functions = {
284+ "log" : math .log ,
285+ "log10" : math .log10 ,
286+ "sqrt" : math .sqrt ,
287+ "factorial" : math .factorial ,
288+ "ceil" : math .ceil ,
289+ "floor" : math .floor ,
290+ "trunc" : math .trunc ,
291+ "sin" : math .sin ,
292+ "cos" : math .cos ,
293+ "tan" : math .tan ,
294+ "asin" : math .asin ,
295+ "acos" : math .acos
296+ "atan" : math .atan ,
297+ "degrees" : math .degrees ,
298+ "radians" : math .radians ,
299+ "sinh" : math .sinh ,
300+ "cosh" : math .cosh ",
301+ "tanh" : math .tanh ,
302+ "asinh" : math .asinh ,
303+ "acosh" : math .acosh ,
304+ "atanh" : math .atanh ,
305+ }
306+
277307 def eval_node (node ):
278308 if isinstance (node , ast .Constant ):
279309 if isinstance (node .value , (int , float )):
@@ -294,13 +324,14 @@ def eval_node(node):
294324 return operators [op ](eval_node (node .operand ))
295325 elif isinstance (node , ast .Call ):
296326 if isinstance (node .func , ast .Name ):
297- if node .func .id == "log" :
327+ if node .func .id in functions :
298328 args = [eval_node (a ) for a in node .args ]
299- return math .log (* args )
300- if node .func .id == "log10" :
301- return math .log10 (eval_node (node .args [0 ]))
302- if node .func .id == "sqrt" :
303- return math .sqrt (eval_node (node .args [0 ]))
329+ return functions [node .func .id ](* args )
330+
331+ elif isinstance (node , ast .Name ):
332+ if node .id in constants :
333+ return constants [node .id ]
334+ raise TypeError (f"Unknown identifier { node .id } " )
304335 raise TypeError ("Unsupported type" )
305336
306337 try :
0 commit comments