def calculate(
expr: str,
*,
replace_num_to_decimal: bool=True
):
node = ast.parse(expr, filename='<ast>', mode='exec')
local: Dict[str, Any] = {}
if replace_num_to_decimal:
Transformer().visit(node)
ast.fix_missing_locations(node)
en = ExtractNames()
en.visit(node)
names = en.names
if '__result__' in names:
raise SyntaxError('assign __result__ value is not allowed.')
Validator(names).visit(node)
last = node.body[-1]
expect_result = False
result = None
if isinstance(last, TYPE_EXPR):
expect_result = True
node.body[-1] = ast.Assign(
targets=[ast.Name(id='__result__', ctx=ast.Store())],
value=last.value
)
ast.fix_missing_locations(node)
exec(compile(node, filename='<ast>', mode='exec'), GLOBAL_CONTEXT, local)
if expect_result:
result = local['__result__']
del local['__result__']
if isinstance(result, Iterable) and \
not isinstance(result, BUILTIN_ITERABLE):
result = list(result)
return result, local
评论列表
文章目录