3
3
from __future__ import absolute_import , division , print_function , unicode_literals
4
4
from .. import source , lexer , diagnostic , ast , coverage
5
5
from ..coverage import parser
6
- import unittest , sys , re
6
+ import unittest , sys , re , ast as pyast
7
7
8
8
if sys .version_info >= (3 ,):
9
9
def unicode (x ): return x
@@ -51,6 +51,21 @@ def flatten_ast(self, node):
51
51
flat_node [unicode (field )] = value
52
52
return flat_node
53
53
54
+ def flatten_python_ast (self , node ):
55
+ flat_node = { 'ty' : unicode (type (node ).__name__ ) }
56
+ for field in node ._fields :
57
+ if field == 'ctx' :
58
+ flat_node ['ctx' ] = None
59
+ continue
60
+
61
+ value = getattr (node , field )
62
+ if isinstance (value , ast .AST ):
63
+ value = self .flatten_python_ast (value )
64
+ if isinstance (value , list ) and len (value ) > 0 and isinstance (value [0 ], ast .AST ):
65
+ value = list (map (self .flatten_python_ast , value ))
66
+ flat_node [unicode (field )] = value
67
+ return flat_node
68
+
54
69
_loc_re = re .compile (r"\s*([~^]*)<?\s+([a-z_0-9.]+)" )
55
70
_path_re = re .compile (r"(([a-z_]+)|([0-9]+))(\.)?" )
56
71
@@ -92,26 +107,35 @@ def match_loc(self, ast, matcher, root=lambda x: x):
92
107
matcher_pos = matcher_match .end (0 )
93
108
94
109
def _assertParsesGen (self , expected_flat_ast , code ,
95
- loc_matcher = "" , ast_slicer = lambda x : (0 , x )):
110
+ loc_matcher = "" , ast_slicer = lambda x : (0 , x ),
111
+ validate_if = lambda : True ):
96
112
ast = self .parser_for (code + "\n " ).file_input ()
97
113
flat_ast = self .flatten_ast (ast )
114
+ python_ast = pyast .parse (code .replace ("·" , "\n " ) + "\n " )
115
+ flat_python_ast = self .flatten_python_ast (python_ast )
98
116
self .assertEqual ({'ty' : 'Module' , 'body' : expected_flat_ast },
99
117
flat_ast )
118
+ if validate_if ():
119
+ self .assertEqual ({'ty' : 'Module' , 'body' : expected_flat_ast },
120
+ flat_python_ast )
100
121
self .match_loc (ast , loc_matcher , ast_slicer )
101
122
102
- def assertParsesSuite (self , expected_flat_ast , code , loc_matcher = "" ):
123
+ def assertParsesSuite (self , expected_flat_ast , code , loc_matcher = "" , ** kwargs ):
103
124
self ._assertParsesGen (expected_flat_ast , code ,
104
- loc_matcher , lambda x : (0 , x .body ))
125
+ loc_matcher , lambda x : (0 , x .body ),
126
+ ** kwargs )
105
127
106
- def assertParsesExpr (self , expected_flat_ast , code , loc_matcher = "" ):
128
+ def assertParsesExpr (self , expected_flat_ast , code , loc_matcher = "" , ** kwargs ):
107
129
self ._assertParsesGen ([{'ty' : 'Expr' , 'value' : expected_flat_ast }], code ,
108
- loc_matcher , lambda x : (0 , x .body [0 ].value ))
130
+ loc_matcher , lambda x : (0 , x .body [0 ].value ),
131
+ ** kwargs )
109
132
110
- def assertParsesArgs (self , expected_flat_ast , code , loc_matcher = "" ):
133
+ def assertParsesArgs (self , expected_flat_ast , code , loc_matcher = "" , ** kwargs ):
111
134
self ._assertParsesGen ([{'ty' : 'Expr' , 'value' : {'ty' : 'Lambda' , 'body' : self .ast_1 ,
112
135
'args' : expected_flat_ast }}],
113
136
"lambda %s: 1" % code ,
114
- loc_matcher , lambda x : (7 , x .body [0 ].value .args ))
137
+ loc_matcher , lambda x : (7 , x .body [0 ].value .args ),
138
+ ** kwargs )
115
139
116
140
def assertParsesToplevel (self , expected_flat_ast , code ,
117
141
mode = "file_input" , interactive = False ):
@@ -200,8 +224,8 @@ def test_unary(self):
200
224
"~ op.loc" )
201
225
202
226
self .assertParsesExpr (
203
- {'ty' : 'UnaryOp' , 'op' : {'ty' : 'USub' }, 'operand' : self .ast_1 },
204
- "-1 " ,
227
+ {'ty' : 'UnaryOp' , 'op' : {'ty' : 'USub' }, 'operand' : self .ast_x },
228
+ "-x " ,
205
229
"~~ loc"
206
230
"~ op.loc" )
207
231
@@ -669,10 +693,9 @@ def test_subscript(self):
669
693
670
694
self .assertParsesExpr (
671
695
{'ty' : 'Subscript' , 'value' : self .ast_x , 'ctx' : None ,
672
- 'slice' : {'ty' : 'ExtSlice' , 'dims' : [
673
- {'ty' : 'Index' , 'value' : self .ast_1 },
674
- {'ty' : 'Index' , 'value' : self .ast_2 },
675
- ]}},
696
+ 'slice' : {'ty' : 'Index' , 'value' : {'ty' : 'Tuple' , 'ctx' : None , 'elts' : [
697
+ self .ast_1 , self .ast_2
698
+ ]}}},
676
699
"x[1, 2]" ,
677
700
" ~~~~ slice.loc"
678
701
"~~~~~~~ loc" )
@@ -701,14 +724,26 @@ def test_subscript(self):
701
724
" ~~~ slice.loc"
702
725
"~~~~~~ loc" )
703
726
727
+ self .assertParsesExpr (
728
+ {'ty' : 'Subscript' , 'value' : self .ast_x , 'ctx' : None ,
729
+ 'slice' : {'ty' : 'ExtSlice' , 'dims' : [
730
+ {'ty' : 'Slice' , 'lower' : self .ast_1 , 'upper' : self .ast_2 , 'step' : None },
731
+ {'ty' : 'Index' , 'value' : self .ast_2 },
732
+ ]}},
733
+ "x[1:2, 2]" ,
734
+ " ~~~~~~ slice.loc"
735
+ "~~~~~~~~~ loc" )
736
+
704
737
self .assertParsesExpr (
705
738
{'ty' : 'Subscript' , 'value' : self .ast_x , 'ctx' : None ,
706
739
'slice' : {'ty' : 'Slice' , 'lower' : self .ast_1 , 'upper' : self .ast_2 , 'step' : None }},
707
740
"x[1:2:]" ,
708
741
" ^ slice.bound_colon_loc"
709
742
" ^ slice.step_colon_loc"
710
743
" ~~~~ slice.loc"
711
- "~~~~~~~ loc" )
744
+ "~~~~~~~ loc" ,
745
+ # A Python bug places ast.Name(id='None') instead of None in step on <3.0
746
+ validate_if = lambda : sys .version_info [0 ] > 2 )
712
747
713
748
self .assertParsesExpr (
714
749
{'ty' : 'Subscript' , 'value' : self .ast_x , 'ctx' : None ,
@@ -839,31 +874,37 @@ def test_augassign(self):
839
874
840
875
def test_print (self ):
841
876
self .assertParsesSuite (
842
- [{'ty' : 'Print' , 'dest' : None , 'values' : [self .ast_1 ], 'nl' : False }],
877
+ [{'ty' : 'Print' , 'dest' : None , 'values' : [self .ast_1 ], 'nl' : True }],
843
878
"print 1" ,
844
879
"~~~~~ 0.keyword_loc"
845
880
"~~~~~~~ 0.loc" )
846
881
847
882
self .assertParsesSuite (
848
- [{'ty' : 'Print' , 'dest' : None , 'values' : [self .ast_1 ], 'nl' : True }],
883
+ [{'ty' : 'Print' , 'dest' : None , 'values' : [self .ast_1 ], 'nl' : False }],
849
884
"print 1," ,
850
885
"~~~~~ 0.keyword_loc"
851
886
"~~~~~~~~ 0.loc" )
852
887
853
888
self .assertParsesSuite (
854
- [{'ty' : 'Print' , 'dest' : self .ast_2 , 'values' : [self .ast_1 ], 'nl' : False }],
889
+ [{'ty' : 'Print' , 'dest' : self .ast_2 , 'values' : [self .ast_1 ], 'nl' : True }],
855
890
"print >>2, 1" ,
856
891
"~~~~~ 0.keyword_loc"
857
892
" ~~ 0.dest_loc"
858
893
"~~~~~~~~~~~~ 0.loc" )
859
894
860
895
def test_del (self ):
861
896
self .assertParsesSuite (
862
- [{'ty' : 'Delete' , 'targets' : self .ast_x }],
897
+ [{'ty' : 'Delete' , 'targets' : [ self .ast_x ] }],
863
898
"del x" ,
864
899
"~~~ 0.keyword_loc"
865
900
"~~~~~ 0.loc" )
866
901
902
+ self .assertParsesSuite (
903
+ [{'ty' : 'Delete' , 'targets' : [self .ast_x , self .ast_y ]}],
904
+ "del x, y" ,
905
+ "~~~ 0.keyword_loc"
906
+ "~~~~~~~~ 0.loc" )
907
+
867
908
def test_pass (self ):
868
909
self .assertParsesSuite (
869
910
[{'ty' : 'Pass' }],
@@ -1039,20 +1080,20 @@ def test_global(self):
1039
1080
1040
1081
def test_exec (self ):
1041
1082
self .assertParsesSuite (
1042
- [{'ty' : 'Exec' , 'body' : self .ast_1 , 'locals ' : None , 'globals ' : None }],
1083
+ [{'ty' : 'Exec' , 'body' : self .ast_1 , 'globals ' : None , 'locals ' : None }],
1043
1084
"exec 1" ,
1044
1085
"~~~~ 0.keyword_loc"
1045
1086
"~~~~~~ 0.loc" )
1046
1087
1047
1088
self .assertParsesSuite (
1048
- [{'ty' : 'Exec' , 'body' : self .ast_1 , 'locals ' : self .ast_2 , 'globals ' : None }],
1089
+ [{'ty' : 'Exec' , 'body' : self .ast_1 , 'globals ' : self .ast_2 , 'locals ' : None }],
1049
1090
"exec 1 in 2" ,
1050
1091
"~~~~ 0.keyword_loc"
1051
1092
" ~~ 0.in_loc"
1052
1093
"~~~~~~~~~~~ 0.loc" )
1053
1094
1054
1095
self .assertParsesSuite (
1055
- [{'ty' : 'Exec' , 'body' : self .ast_1 , 'locals ' : self .ast_2 , 'globals ' : self .ast_3 }],
1096
+ [{'ty' : 'Exec' , 'body' : self .ast_1 , 'globals ' : self .ast_2 , 'locals ' : self .ast_3 }],
1056
1097
"exec 1 in 2, 3" ,
1057
1098
"~~~~ 0.keyword_loc"
1058
1099
" ~~ 0.in_loc"
@@ -1146,7 +1187,7 @@ def test_for(self):
1146
1187
1147
1188
def test_try (self ):
1148
1189
self .assertParsesSuite (
1149
- [{'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : None ,
1190
+ [{'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : [] ,
1150
1191
'handlers' : [
1151
1192
{'ty' : 'ExceptHandler' , 'type' : None , 'name' : None ,
1152
1193
'body' : [self .ast_expr_2 ]}
@@ -1160,15 +1201,15 @@ def test_try(self):
1160
1201
"~~~~~~~~~~~~~~~~~~~~ 0.loc" )
1161
1202
1162
1203
self .assertParsesSuite (
1163
- [{'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : None ,
1204
+ [{'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : [] ,
1164
1205
'handlers' : [
1165
1206
{'ty' : 'ExceptHandler' , 'type' : self .ast_y , 'name' : None ,
1166
1207
'body' : [self .ast_expr_2 ]}
1167
1208
]}],
1168
1209
"try:· 1·except y:· 2" )
1169
1210
1170
1211
self .assertParsesSuite (
1171
- [{'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : None ,
1212
+ [{'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : [] ,
1172
1213
'handlers' : [
1173
1214
{'ty' : 'ExceptHandler' , 'type' : self .ast_y , 'name' : self .ast_t ,
1174
1215
'body' : [self .ast_expr_2 ]}
@@ -1177,7 +1218,7 @@ def test_try(self):
1177
1218
" ~~ 0.handlers.0.as_loc" )
1178
1219
1179
1220
self .assertParsesSuite (
1180
- [{'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : None ,
1221
+ [{'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : [] ,
1181
1222
'handlers' : [
1182
1223
{'ty' : 'ExceptHandler' , 'type' : self .ast_y , 'name' : self .ast_t ,
1183
1224
'body' : [self .ast_expr_2 ]}
@@ -1208,7 +1249,7 @@ def test_finally(self):
1208
1249
1209
1250
self .assertParsesSuite (
1210
1251
[{'ty' : 'TryFinally' , 'finalbody' : [self .ast_expr_3 ], 'body' : [
1211
- {'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : None , 'handlers' : [
1252
+ {'ty' : 'TryExcept' , 'body' : [self .ast_expr_1 ], 'orelse' : [] , 'handlers' : [
1212
1253
{'ty' : 'ExceptHandler' , 'type' : None , 'name' : None ,
1213
1254
'body' : [self .ast_expr_2 ]}
1214
1255
]}
0 commit comments