Source code for viscid.pyeval
"""Deserialize a string using literal_eval
This is more than just literal_eval in that strings don't need quotes
and true/false are mapped to True/False
"""
from __future__ import print_function
import ast
[docs]class PyEvalError(Exception):
message = ""
def __init__(self, message=""):
self.message = message
super(PyEvalError, self).__init__(message)
class _Transformer(ast.NodeTransformer):
"""Turn a string into python objects (strings, numbers, as basic types)"""
def visit_Name(self, node):
if node.id.lower() in ["true", "false"]:
# turn 'true' / 'True' / 'TRUE' / etc. into True
val = True if node.id.lower() == "true" else False
try:
node = ast.copy_location(ast.NameConstant(val), node)
except AttributeError:
node = ast.copy_location(ast.Name(str(val), node.ctx), node)
elif node.id.lower() == "none":
val = None
try:
node = ast.copy_location(ast.NameConstant(val), node)
except AttributeError:
node = ast.copy_location(ast.Name(str(val), node.ctx), node)
else:
# turn other bare names into strings
node = ast.copy_location(ast.Str(s=node.id), node)
return self.generic_visit(node)
[docs]def parse(s):
try:
tree = ast.parse(s.strip(), mode='eval')
_Transformer().visit(tree)
return ast.literal_eval(tree)
except ValueError:
raise PyEvalError("ast parser vomited")
# def parse_option_list(s):
# tree = ast.parse(s.strip(), mode='eval')
# _Transformer().visit(tree)
# return ast.literal_eval(tree)
# if __name__ == "__main__":
# _s = """dict(opt1, opt2=12, opt3=text, opt4='some string')"""
# print(parse_option_list(_s))
##
## EOF
##