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