Use 'ast' instead of 'compiler' in utils.gen.safeEval.

This commit is contained in:
Valentin Lorentz 2012-08-04 17:24:08 +02:00
parent d3d93da602
commit b8fe420ef3

View File

@ -30,9 +30,9 @@
import os
import sys
import ast
import time
import types
import compiler
import textwrap
import traceback
import collections
@ -40,7 +40,6 @@ from itertools import imap
from str import format
from file import mktemp
from iter import all
import crypt
@ -150,32 +149,36 @@ def saltHash(password, salt=None, hash='sha'):
hasher = crypt.md5
return '|'.join([salt, hasher((salt + password).encode('utf8')).hexdigest()])
_astStr2 = ast.Str if sys.version_info[0] < 3 else ast.Bytes
def safeEval(s, namespace={'True': True, 'False': False, 'None': None}):
"""Evaluates s, safely. Useful for turning strings into tuples/lists/etc.
without unsafely using eval()."""
try:
node = compiler.parse(s)
node = ast.parse(s)
except SyntaxError, e:
raise ValueError, 'Invalid string: %s.' % e
nodes = compiler.parse(s).node.nodes
nodes = ast.parse(s).body
if not nodes:
if node.__class__ is compiler.ast.Module:
if node.__class__ is ast.Module:
return node.doc
else:
raise ValueError, format('Unsafe string: %q', s)
node = nodes[0]
if node.__class__ is not compiler.ast.Discard:
raise ValueError, format('Invalid expression: %q', s)
node = node.getChildNodes()[0]
def checkNode(node):
if node.__class__ is compiler.ast.Const:
if node.__class__ is ast.Expr:
node = node.value
if node.__class__ in (ast.Num,
ast.Str,
_astStr2):
return True
if node.__class__ in (compiler.ast.List,
compiler.ast.Tuple,
compiler.ast.Dict):
return all(checkNode, node.getChildNodes())
if node.__class__ is compiler.ast.Name:
if node.name in namespace:
elif node.__class__ in (ast.List,
ast.Tuple):
return all([checkNode(x) for x in node.elts])
elif node.__class__ is ast.Dict:
return all([checkNode(x) for x in node.values]) and \
all([checkNode(x) for x in node.values])
elif node.__class__ is ast.Name:
if node.id in namespace:
return True
else:
return False