5
5
6
6
"""
7
7
8
- from ast import *
8
+ import ast
9
9
from six import string_types
10
+ from six .moves import builtins
10
11
11
12
from bpython import line as line_properties
12
13
@@ -23,6 +24,7 @@ def safe_eval(expr, namespace):
23
24
# raise
24
25
raise EvaluationError
25
26
27
+ # taken from Python 2 stdlib ast.literal_eval
26
28
def simple_eval (node_or_string , namespace = None ):
27
29
"""
28
30
Safely evaluate an expression node or a string containing a Python
@@ -37,43 +39,44 @@ def simple_eval(node_or_string, namespace=None):
37
39
38
40
The optional namespace dict-like ought not to cause side effects on lookup
39
41
"""
42
+ # Based heavily on stdlib ast.literal_eval
40
43
if namespace is None :
41
44
namespace = {}
42
45
if isinstance (node_or_string , string_types ):
43
- node_or_string = parse (node_or_string , mode = 'eval' )
44
- if isinstance (node_or_string , Expression ):
46
+ node_or_string = ast . parse (node_or_string , mode = 'eval' )
47
+ if isinstance (node_or_string , ast . Expression ):
45
48
node_or_string = node_or_string .body
46
49
def _convert (node ):
47
- if isinstance (node , Str ):
50
+ if isinstance (node , ast . Str ):
48
51
return node .s
49
- elif isinstance (node , Num ):
52
+ elif isinstance (node , ast . Num ):
50
53
return node .n
51
- elif isinstance (node , Tuple ):
54
+ elif isinstance (node , ast . Tuple ):
52
55
return tuple (map (_convert , node .elts ))
53
- elif isinstance (node , List ):
56
+ elif isinstance (node , ast . List ):
54
57
return list (map (_convert , node .elts ))
55
- elif isinstance (node , Dict ):
58
+ elif isinstance (node , ast . Dict ):
56
59
return dict ((_convert (k ), _convert (v )) for k , v
57
60
in zip (node .keys , node .values ))
58
- elif isinstance (node , Name ):
61
+ elif isinstance (node , ast . Name ):
59
62
try :
60
63
return namespace [node .id ]
61
64
except KeyError :
62
- return __builtins__ [ node .id ]
63
- elif isinstance (node , BinOp ) and \
64
- isinstance (node .op , (Add , Sub )) and \
65
- isinstance (node .right , Num ) and \
65
+ return getattr ( builtins , node .id )
66
+ elif isinstance (node , ast . BinOp ) and \
67
+ isinstance (node .op , (ast . Add , ast . Sub )) and \
68
+ isinstance (node .right , ast . Num ) and \
66
69
isinstance (node .right .n , complex ) and \
67
- isinstance (node .left , Num ) and \
70
+ isinstance (node .left , ast . Num ) and \
68
71
isinstance (node .left .n , (int , long , float )):
69
72
left = node .left .n
70
73
right = node .right .n
71
- if isinstance (node .op , Add ):
74
+ if isinstance (node .op , ast . Add ):
72
75
return left + right
73
76
else :
74
77
return left - right
75
- elif isinstance (node , Subscript ) and \
76
- isinstance (node .slice , Index ):
78
+ elif isinstance (node , ast . Subscript ) and \
79
+ isinstance (node .slice , ast . Index ):
77
80
obj = _convert (node .value )
78
81
index = _convert (node .slice .value )
79
82
return safe_getitem (obj , index )
@@ -90,16 +93,16 @@ def safe_getitem(obj, index):
90
93
91
94
def find_attribute_with_name (node , name ):
92
95
"""Based on ast.NodeVisitor"""
93
- if isinstance (node , Attribute ) and node .attr == name :
96
+ if isinstance (node , ast . Attribute ) and node .attr == name :
94
97
return node
95
- for field , value in iter_fields (node ):
98
+ for field , value in ast . iter_fields (node ):
96
99
if isinstance (value , list ):
97
100
for item in value :
98
- if isinstance (item , AST ):
101
+ if isinstance (item , ast . AST ):
99
102
r = find_attribute_with_name (item , name )
100
103
if r :
101
104
return r
102
- elif isinstance (value , AST ):
105
+ elif isinstance (value , ast . AST ):
103
106
r = find_attribute_with_name (value , name )
104
107
if r :
105
108
return r
@@ -126,8 +129,8 @@ def evaluate_current_expression(cursor_offset, line, namespace={}):
126
129
def parse_trees (cursor_offset , line ):
127
130
for i in range (cursor_offset - 1 , - 1 , - 1 ):
128
131
try :
129
- ast = parse (line [i :cursor_offset ])
130
- yield ast
132
+ tree = ast . parse (line [i :cursor_offset ])
133
+ yield tree
131
134
except SyntaxError :
132
135
continue
133
136
@@ -141,5 +144,5 @@ def parse_trees(cursor_offset, line):
141
144
raise EvaluationError ("Corresponding ASTs to right of cursor are invalid" )
142
145
try :
143
146
return simple_eval (largest_ast , namespace )
144
- except (ValueError , KeyError , IndexError ):
147
+ except (ValueError , KeyError , IndexError , AttributeError ):
145
148
raise EvaluationError ("Could not safely evaluate" )
0 commit comments