]>
Commit | Line | Data |
---|---|---|
53e6db90 DC |
1 | # Copyright 2015 Google Inc. All Rights Reserved. |
2 | # | |
3 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | # you may not use this file except in compliance with the License. | |
5 | # You may obtain a copy of the License at | |
6 | # | |
7 | # http://www.apache.org/licenses/LICENSE-2.0 | |
8 | # | |
9 | # Unless required by applicable law or agreed to in writing, software | |
10 | # distributed under the License is distributed on an "AS IS" BASIS, | |
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | # See the License for the specific language governing permissions and | |
13 | # limitations under the License. | |
14 | """Tests for yapf.pytree_unwrapper.""" | |
15 | ||
16 | import textwrap | |
17 | import unittest | |
18 | ||
19 | from yapf.pytree import pytree_utils | |
20 | ||
21 | from yapftests import yapf_test_helper | |
22 | ||
23 | ||
24 | class PytreeUnwrapperTest(yapf_test_helper.YAPFTest): | |
25 | ||
26 | def _CheckLogicalLines(self, llines, list_of_expected): | |
27 | """Check that the given LogicalLines match expectations. | |
28 | ||
29 | Args: | |
30 | llines: list of LogicalLine | |
31 | list_of_expected: list of (depth, values) pairs. Non-semantic tokens are | |
32 | filtered out from the expected values. | |
33 | """ | |
34 | actual = [] | |
35 | for lline in llines: | |
36 | filtered_values = [ | |
37 | ft.value | |
38 | for ft in lline.tokens | |
39 | if ft.name not in pytree_utils.NONSEMANTIC_TOKENS | |
40 | ] | |
41 | actual.append((lline.depth, filtered_values)) | |
42 | ||
43 | self.assertEqual(list_of_expected, actual) | |
44 | ||
45 | def testSimpleFileScope(self): | |
46 | code = textwrap.dedent("""\ | |
47 | x = 1 | |
48 | # a comment | |
49 | y = 2 | |
50 | """) | |
51 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
52 | self._CheckLogicalLines(llines, [ | |
53 | (0, ['x', '=', '1']), | |
54 | (0, ['# a comment']), | |
55 | (0, ['y', '=', '2']), | |
56 | ]) | |
57 | ||
58 | def testSimpleMultilineStatement(self): | |
59 | code = textwrap.dedent("""\ | |
60 | y = (1 + | |
61 | x) | |
62 | """) | |
63 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
64 | self._CheckLogicalLines(llines, [ | |
65 | (0, ['y', '=', '(', '1', '+', 'x', ')']), | |
66 | ]) | |
67 | ||
68 | def testFileScopeWithInlineComment(self): | |
69 | code = textwrap.dedent("""\ | |
70 | x = 1 # a comment | |
71 | y = 2 | |
72 | """) | |
73 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
74 | self._CheckLogicalLines(llines, [ | |
75 | (0, ['x', '=', '1', '# a comment']), | |
76 | (0, ['y', '=', '2']), | |
77 | ]) | |
78 | ||
79 | def testSimpleIf(self): | |
80 | code = textwrap.dedent("""\ | |
81 | if foo: | |
82 | x = 1 | |
83 | y = 2 | |
84 | """) | |
85 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
86 | self._CheckLogicalLines(llines, [ | |
87 | (0, ['if', 'foo', ':']), | |
88 | (1, ['x', '=', '1']), | |
89 | (1, ['y', '=', '2']), | |
90 | ]) | |
91 | ||
92 | def testSimpleIfWithComments(self): | |
93 | code = textwrap.dedent("""\ | |
94 | # c1 | |
95 | if foo: # c2 | |
96 | x = 1 | |
97 | y = 2 | |
98 | """) | |
99 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
100 | self._CheckLogicalLines(llines, [ | |
101 | (0, ['# c1']), | |
102 | (0, ['if', 'foo', ':', '# c2']), | |
103 | (1, ['x', '=', '1']), | |
104 | (1, ['y', '=', '2']), | |
105 | ]) | |
106 | ||
107 | def testIfWithCommentsInside(self): | |
108 | code = textwrap.dedent("""\ | |
109 | if foo: | |
110 | # c1 | |
111 | x = 1 # c2 | |
112 | # c3 | |
113 | y = 2 | |
114 | """) | |
115 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
116 | self._CheckLogicalLines(llines, [ | |
117 | (0, ['if', 'foo', ':']), | |
118 | (1, ['# c1']), | |
119 | (1, ['x', '=', '1', '# c2']), | |
120 | (1, ['# c3']), | |
121 | (1, ['y', '=', '2']), | |
122 | ]) | |
123 | ||
124 | def testIfElifElse(self): | |
125 | code = textwrap.dedent("""\ | |
126 | if x: | |
127 | x = 1 # c1 | |
128 | elif y: # c2 | |
129 | y = 1 | |
130 | else: | |
131 | # c3 | |
132 | z = 1 | |
133 | """) | |
134 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
135 | self._CheckLogicalLines(llines, [ | |
136 | (0, ['if', 'x', ':']), | |
137 | (1, ['x', '=', '1', '# c1']), | |
138 | (0, ['elif', 'y', ':', '# c2']), | |
139 | (1, ['y', '=', '1']), | |
140 | (0, ['else', ':']), | |
141 | (1, ['# c3']), | |
142 | (1, ['z', '=', '1']), | |
143 | ]) | |
144 | ||
145 | def testNestedCompoundTwoLevel(self): | |
146 | code = textwrap.dedent("""\ | |
147 | if x: | |
148 | x = 1 # c1 | |
149 | while t: | |
150 | # c2 | |
151 | j = 1 | |
152 | k = 1 | |
153 | """) | |
154 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
155 | self._CheckLogicalLines(llines, [ | |
156 | (0, ['if', 'x', ':']), | |
157 | (1, ['x', '=', '1', '# c1']), | |
158 | (1, ['while', 't', ':']), | |
159 | (2, ['# c2']), | |
160 | (2, ['j', '=', '1']), | |
161 | (1, ['k', '=', '1']), | |
162 | ]) | |
163 | ||
164 | def testSimpleWhile(self): | |
165 | code = textwrap.dedent("""\ | |
166 | while x > 1: # c1 | |
167 | # c2 | |
168 | x = 1 | |
169 | """) | |
170 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
171 | self._CheckLogicalLines(llines, [ | |
172 | (0, ['while', 'x', '>', '1', ':', '# c1']), | |
173 | (1, ['# c2']), | |
174 | (1, ['x', '=', '1']), | |
175 | ]) | |
176 | ||
177 | def testSimpleTry(self): | |
178 | code = textwrap.dedent("""\ | |
179 | try: | |
180 | pass | |
181 | except: | |
182 | pass | |
183 | except: | |
184 | pass | |
185 | else: | |
186 | pass | |
187 | finally: | |
188 | pass | |
189 | """) | |
190 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
191 | self._CheckLogicalLines(llines, [ | |
192 | (0, ['try', ':']), | |
193 | (1, ['pass']), | |
194 | (0, ['except', ':']), | |
195 | (1, ['pass']), | |
196 | (0, ['except', ':']), | |
197 | (1, ['pass']), | |
198 | (0, ['else', ':']), | |
199 | (1, ['pass']), | |
200 | (0, ['finally', ':']), | |
201 | (1, ['pass']), | |
202 | ]) | |
203 | ||
204 | def testSimpleFuncdef(self): | |
205 | code = textwrap.dedent("""\ | |
206 | def foo(x): # c1 | |
207 | # c2 | |
208 | return x | |
209 | """) | |
210 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
211 | self._CheckLogicalLines(llines, [ | |
212 | (0, ['def', 'foo', '(', 'x', ')', ':', '# c1']), | |
213 | (1, ['# c2']), | |
214 | (1, ['return', 'x']), | |
215 | ]) | |
216 | ||
217 | def testTwoFuncDefs(self): | |
218 | code = textwrap.dedent("""\ | |
219 | def foo(x): # c1 | |
220 | # c2 | |
221 | return x | |
222 | ||
223 | def bar(): # c3 | |
224 | # c4 | |
225 | return x | |
226 | """) | |
227 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
228 | self._CheckLogicalLines(llines, [ | |
229 | (0, ['def', 'foo', '(', 'x', ')', ':', '# c1']), | |
230 | (1, ['# c2']), | |
231 | (1, ['return', 'x']), | |
232 | (0, ['def', 'bar', '(', ')', ':', '# c3']), | |
233 | (1, ['# c4']), | |
234 | (1, ['return', 'x']), | |
235 | ]) | |
236 | ||
237 | def testSimpleClassDef(self): | |
238 | code = textwrap.dedent("""\ | |
239 | class Klass: # c1 | |
240 | # c2 | |
241 | p = 1 | |
242 | """) | |
243 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
244 | self._CheckLogicalLines(llines, [ | |
245 | (0, ['class', 'Klass', ':', '# c1']), | |
246 | (1, ['# c2']), | |
247 | (1, ['p', '=', '1']), | |
248 | ]) | |
249 | ||
250 | def testSingleLineStmtInFunc(self): | |
251 | code = textwrap.dedent("""\ | |
252 | def f(): return 37 | |
253 | """) | |
254 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
255 | self._CheckLogicalLines(llines, [ | |
256 | (0, ['def', 'f', '(', ')', ':']), | |
257 | (1, ['return', '37']), | |
258 | ]) | |
259 | ||
260 | def testMultipleComments(self): | |
261 | code = textwrap.dedent("""\ | |
262 | # Comment #1 | |
263 | ||
264 | # Comment #2 | |
265 | def f(): | |
266 | pass | |
267 | """) | |
268 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
269 | self._CheckLogicalLines(llines, [ | |
270 | (0, ['# Comment #1']), | |
271 | (0, ['# Comment #2']), | |
272 | (0, ['def', 'f', '(', ')', ':']), | |
273 | (1, ['pass']), | |
274 | ]) | |
275 | ||
276 | def testSplitListWithComment(self): | |
277 | code = textwrap.dedent("""\ | |
278 | a = [ | |
279 | 'a', | |
280 | 'b', | |
281 | 'c', # hello world | |
282 | ] | |
283 | """) | |
284 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
285 | self._CheckLogicalLines(llines, [(0, [ | |
286 | 'a', '=', '[', "'a'", ',', "'b'", ',', "'c'", ',', '# hello world', ']' | |
287 | ])]) | |
288 | ||
289 | ||
290 | class MatchBracketsTest(yapf_test_helper.YAPFTest): | |
291 | ||
292 | def _CheckMatchingBrackets(self, llines, list_of_expected): | |
293 | """Check that the tokens have the expected matching bracket. | |
294 | ||
295 | Arguments: | |
296 | llines: list of LogicalLine. | |
297 | list_of_expected: list of (index, index) pairs. The matching brackets at | |
298 | the indexes need to match. Non-semantic tokens are filtered out from the | |
299 | expected values. | |
300 | """ | |
301 | actual = [] | |
302 | for lline in llines: | |
303 | filtered_values = [(ft, ft.matching_bracket) | |
304 | for ft in lline.tokens | |
305 | if ft.name not in pytree_utils.NONSEMANTIC_TOKENS] | |
306 | if filtered_values: | |
307 | actual.append(filtered_values) | |
308 | ||
309 | for index, bracket_list in enumerate(list_of_expected): | |
310 | lline = actual[index] | |
311 | if not bracket_list: | |
312 | for value in lline: | |
313 | self.assertIsNone(value[1]) | |
314 | else: | |
315 | for open_bracket, close_bracket in bracket_list: | |
316 | self.assertEqual(lline[open_bracket][0], lline[close_bracket][1]) | |
317 | self.assertEqual(lline[close_bracket][0], lline[open_bracket][1]) | |
318 | ||
319 | def testFunctionDef(self): | |
320 | code = textwrap.dedent("""\ | |
321 | def foo(a, b=['w','d'], c=[42, 37]): | |
322 | pass | |
323 | """) | |
324 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
325 | self._CheckMatchingBrackets(llines, [ | |
326 | [(2, 20), (7, 11), (15, 19)], | |
327 | [], | |
328 | ]) | |
329 | ||
330 | def testDecorator(self): | |
331 | code = textwrap.dedent("""\ | |
332 | @bar() | |
333 | def foo(a, b, c): | |
334 | pass | |
335 | """) | |
336 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
337 | self._CheckMatchingBrackets(llines, [ | |
338 | [(2, 3)], | |
339 | [(2, 8)], | |
340 | [], | |
341 | ]) | |
342 | ||
343 | def testClassDef(self): | |
344 | code = textwrap.dedent("""\ | |
345 | class A(B, C, D): | |
346 | pass | |
347 | """) | |
348 | llines = yapf_test_helper.ParseAndUnwrap(code) | |
349 | self._CheckMatchingBrackets(llines, [ | |
350 | [(2, 8)], | |
351 | [], | |
352 | ]) | |
353 | ||
354 | ||
355 | if __name__ == '__main__': | |
356 | unittest.main() |