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 16import textwrap 17import unittest 18 19from yapf.yapflib import pytree_utils 20 21from yapftests import yapf_test_helper 22 23 24class PytreeUnwrapperTest(yapf_test_helper.YAPFTest): 25 26 def _CheckUnwrappedLines(self, uwlines, list_of_expected): 27 """Check that the given UnwrappedLines match expectations. 28 29 Args: 30 uwlines: list of UnwrappedLine 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 uwl in uwlines: 36 filtered_values = [ 37 ft.value 38 for ft in uwl.tokens 39 if ft.name not in pytree_utils.NONSEMANTIC_TOKENS 40 ] 41 actual.append((uwl.depth, filtered_values)) 42 43 self.assertEqual(list_of_expected, actual) 44 45 def testSimpleFileScope(self): 46 code = textwrap.dedent(r""" 47 x = 1 48 # a comment 49 y = 2 50 """) 51 uwlines = yapf_test_helper.ParseAndUnwrap(code) 52 self._CheckUnwrappedLines(uwlines, [ 53 (0, ['x', '=', '1']), 54 (0, ['# a comment']), 55 (0, ['y', '=', '2']), 56 ]) 57 58 def testSimpleMultilineStatement(self): 59 code = textwrap.dedent(r""" 60 y = (1 + 61 x) 62 """) 63 uwlines = yapf_test_helper.ParseAndUnwrap(code) 64 self._CheckUnwrappedLines(uwlines, [ 65 (0, ['y', '=', '(', '1', '+', 'x', ')']), 66 ]) 67 68 def testFileScopeWithInlineComment(self): 69 code = textwrap.dedent(r""" 70 x = 1 # a comment 71 y = 2 72 """) 73 uwlines = yapf_test_helper.ParseAndUnwrap(code) 74 self._CheckUnwrappedLines(uwlines, [ 75 (0, ['x', '=', '1', '# a comment']), 76 (0, ['y', '=', '2']), 77 ]) 78 79 def testSimpleIf(self): 80 code = textwrap.dedent(r""" 81 if foo: 82 x = 1 83 y = 2 84 """) 85 uwlines = yapf_test_helper.ParseAndUnwrap(code) 86 self._CheckUnwrappedLines(uwlines, [ 87 (0, ['if', 'foo', ':']), 88 (1, ['x', '=', '1']), 89 (1, ['y', '=', '2']), 90 ]) 91 92 def testSimpleIfWithComments(self): 93 code = textwrap.dedent(r""" 94 # c1 95 if foo: # c2 96 x = 1 97 y = 2 98 """) 99 uwlines = yapf_test_helper.ParseAndUnwrap(code) 100 self._CheckUnwrappedLines(uwlines, [ 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(r""" 109 if foo: 110 # c1 111 x = 1 # c2 112 # c3 113 y = 2 114 """) 115 uwlines = yapf_test_helper.ParseAndUnwrap(code) 116 self._CheckUnwrappedLines(uwlines, [ 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(r""" 126 if x: 127 x = 1 # c1 128 elif y: # c2 129 y = 1 130 else: 131 # c3 132 z = 1 133 """) 134 uwlines = yapf_test_helper.ParseAndUnwrap(code) 135 self._CheckUnwrappedLines(uwlines, [ 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(r""" 147 if x: 148 x = 1 # c1 149 while t: 150 # c2 151 j = 1 152 k = 1 153 """) 154 uwlines = yapf_test_helper.ParseAndUnwrap(code) 155 self._CheckUnwrappedLines(uwlines, [ 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(r""" 166 while x > 1: # c1 167 # c2 168 x = 1 169 """) 170 uwlines = yapf_test_helper.ParseAndUnwrap(code) 171 self._CheckUnwrappedLines(uwlines, [ 172 (0, ['while', 'x', '>', '1', ':', '# c1']), 173 (1, ['# c2']), 174 (1, ['x', '=', '1']), 175 ]) 176 177 def testSimpleTry(self): 178 code = textwrap.dedent(r""" 179 try: 180 pass 181 except: 182 pass 183 except: 184 pass 185 else: 186 pass 187 finally: 188 pass 189 """) 190 uwlines = yapf_test_helper.ParseAndUnwrap(code) 191 self._CheckUnwrappedLines(uwlines, [ 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(r""" 206 def foo(x): # c1 207 # c2 208 return x 209 """) 210 uwlines = yapf_test_helper.ParseAndUnwrap(code) 211 self._CheckUnwrappedLines(uwlines, [ 212 (0, ['def', 'foo', '(', 'x', ')', ':', '# c1']), 213 (1, ['# c2']), 214 (1, ['return', 'x']), 215 ]) 216 217 def testTwoFuncDefs(self): 218 code = textwrap.dedent(r""" 219 def foo(x): # c1 220 # c2 221 return x 222 223 def bar(): # c3 224 # c4 225 return x 226 """) 227 uwlines = yapf_test_helper.ParseAndUnwrap(code) 228 self._CheckUnwrappedLines(uwlines, [ 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(r""" 239 class Klass: # c1 240 # c2 241 p = 1 242 """) 243 uwlines = yapf_test_helper.ParseAndUnwrap(code) 244 self._CheckUnwrappedLines(uwlines, [ 245 (0, ['class', 'Klass', ':', '# c1']), 246 (1, ['# c2']), 247 (1, ['p', '=', '1']), 248 ]) 249 250 def testSingleLineStmtInFunc(self): 251 code = textwrap.dedent(r""" 252 def f(): return 37 253 """) 254 uwlines = yapf_test_helper.ParseAndUnwrap(code) 255 self._CheckUnwrappedLines(uwlines, [ 256 (0, ['def', 'f', '(', ')', ':']), 257 (1, ['return', '37']), 258 ]) 259 260 def testMultipleComments(self): 261 code = textwrap.dedent(r""" 262 # Comment #1 263 264 # Comment #2 265 def f(): 266 pass 267 """) 268 uwlines = yapf_test_helper.ParseAndUnwrap(code) 269 self._CheckUnwrappedLines(uwlines, [ 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(r""" 278 a = [ 279 'a', 280 'b', 281 'c', # hello world 282 ] 283 """) 284 uwlines = yapf_test_helper.ParseAndUnwrap(code) 285 self._CheckUnwrappedLines(uwlines, [(0, [ 286 'a', '=', '[', "'a'", ',', "'b'", ',', "'c'", ',', '# hello world', ']' 287 ])]) 288 289 290class MatchBracketsTest(yapf_test_helper.YAPFTest): 291 292 def _CheckMatchingBrackets(self, uwlines, list_of_expected): 293 """Check that the tokens have the expected matching bracket. 294 295 Arguments: 296 uwlines: list of UnwrappedLine. 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 uwl in uwlines: 303 filtered_values = [(ft, ft.matching_bracket) 304 for ft in uwl.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 uwline = actual[index] 311 if not bracket_list: 312 for value in uwline: 313 self.assertIsNone(value[1]) 314 else: 315 for open_bracket, close_bracket in bracket_list: 316 self.assertEqual(uwline[open_bracket][0], uwline[close_bracket][1]) 317 self.assertEqual(uwline[close_bracket][0], uwline[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 uwlines = yapf_test_helper.ParseAndUnwrap(code) 325 self._CheckMatchingBrackets(uwlines, [ 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 uwlines = yapf_test_helper.ParseAndUnwrap(code) 337 self._CheckMatchingBrackets(uwlines, [ 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 uwlines = yapf_test_helper.ParseAndUnwrap(code) 349 self._CheckMatchingBrackets(uwlines, [ 350 [(2, 8)], 351 [], 352 ]) 353 354 355if __name__ == '__main__': 356 unittest.main() 357