1# Copyright 2016 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"""Python 3 tests for yapf.reformatter.""" 15 16import sys 17import textwrap 18import unittest 19 20from yapf.yapflib import py3compat 21from yapf.yapflib import reformatter 22from yapf.yapflib import style 23 24from yapftests import yapf_test_helper 25 26 27@unittest.skipUnless(py3compat.PY3, 'Requires Python 3') 28class TestsForPython3Code(yapf_test_helper.YAPFTest): 29 """Test a few constructs that are new Python 3 syntax.""" 30 31 @classmethod 32 def setUpClass(cls): # pylint: disable=g-missing-super-call 33 style.SetGlobalStyle(style.CreatePEP8Style()) 34 35 def testTypedNames(self): 36 unformatted_code = textwrap.dedent("""\ 37 def x(aaaaaaaaaaaaaaa:int,bbbbbbbbbbbbbbbb:str,ccccccccccccccc:dict,eeeeeeeeeeeeee:set={1, 2, 3})->bool: 38 pass 39 """) # noqa 40 expected_formatted_code = textwrap.dedent("""\ 41 def x(aaaaaaaaaaaaaaa: int, 42 bbbbbbbbbbbbbbbb: str, 43 ccccccccccccccc: dict, 44 eeeeeeeeeeeeee: set = {1, 2, 3}) -> bool: 45 pass 46 """) 47 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 48 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 49 50 def testTypedNameWithLongNamedArg(self): 51 unformatted_code = textwrap.dedent("""\ 52 def func(arg=long_function_call_that_pushes_the_line_over_eighty_characters()) -> ReturnType: 53 pass 54 """) # noqa 55 expected_formatted_code = textwrap.dedent("""\ 56 def func(arg=long_function_call_that_pushes_the_line_over_eighty_characters() 57 ) -> ReturnType: 58 pass 59 """) # noqa 60 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 61 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 62 63 def testKeywordOnlyArgSpecifier(self): 64 unformatted_code = textwrap.dedent("""\ 65 def foo(a, *, kw): 66 return a+kw 67 """) 68 expected_formatted_code = textwrap.dedent("""\ 69 def foo(a, *, kw): 70 return a + kw 71 """) 72 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 73 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 74 75 @unittest.skipUnless(py3compat.PY36, 'Requires Python 3.6') 76 def testPEP448ParameterExpansion(self): 77 unformatted_code = textwrap.dedent("""\ 78 { ** x } 79 { **{} } 80 { **{ **x }, **x } 81 {'a': 1, **kw , 'b':3, **kw2 } 82 """) 83 expected_formatted_code = textwrap.dedent("""\ 84 {**x} 85 {**{}} 86 {**{**x}, **x} 87 {'a': 1, **kw, 'b': 3, **kw2} 88 """) 89 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 90 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 91 92 def testAnnotations(self): 93 unformatted_code = textwrap.dedent("""\ 94 def foo(a: list, b: "bar") -> dict: 95 return a+b 96 """) 97 expected_formatted_code = textwrap.dedent("""\ 98 def foo(a: list, b: "bar") -> dict: 99 return a + b 100 """) 101 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 102 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 103 104 def testExecAsNonKeyword(self): 105 unformatted_code = 'methods.exec( sys.modules[name])\n' 106 expected_formatted_code = 'methods.exec(sys.modules[name])\n' 107 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 108 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 109 110 def testAsyncFunctions(self): 111 if sys.version_info[1] < 5: 112 return 113 code = textwrap.dedent("""\ 114 import asyncio 115 import time 116 117 118 @print_args 119 async def slow_operation(): 120 await asyncio.sleep(1) 121 # print("Slow operation {} complete".format(n)) 122 123 124 async def main(): 125 start = time.time() 126 if (await get_html()): 127 pass 128 """) 129 llines = yapf_test_helper.ParseAndUnwrap(code) 130 self.assertCodeEqual(code, reformatter.Reformat(llines, verify=False)) 131 132 def testNoSpacesAroundPowerOperator(self): 133 unformatted_code = textwrap.dedent("""\ 134 a**b 135 """) 136 expected_formatted_code = textwrap.dedent("""\ 137 a ** b 138 """) 139 140 try: 141 style.SetGlobalStyle( 142 style.CreateStyleFromConfig( 143 '{based_on_style: pep8, SPACES_AROUND_POWER_OPERATOR: True}')) 144 145 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 146 self.assertCodeEqual(expected_formatted_code, 147 reformatter.Reformat(llines)) 148 finally: 149 style.SetGlobalStyle(style.CreatePEP8Style()) 150 151 def testSpacesAroundDefaultOrNamedAssign(self): 152 unformatted_code = textwrap.dedent("""\ 153 f(a=5) 154 """) 155 expected_formatted_code = textwrap.dedent("""\ 156 f(a = 5) 157 """) 158 159 try: 160 style.SetGlobalStyle( 161 style.CreateStyleFromConfig( 162 '{based_on_style: pep8, ' 163 'SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN: True}')) 164 165 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 166 self.assertCodeEqual(expected_formatted_code, 167 reformatter.Reformat(llines)) 168 finally: 169 style.SetGlobalStyle(style.CreatePEP8Style()) 170 171 def testTypeHint(self): 172 unformatted_code = textwrap.dedent("""\ 173 def foo(x: int=42): 174 pass 175 176 177 def foo2(x: 'int' =42): 178 pass 179 """) 180 expected_formatted_code = textwrap.dedent("""\ 181 def foo(x: int = 42): 182 pass 183 184 185 def foo2(x: 'int' = 42): 186 pass 187 """) 188 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 189 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 190 191 def testMatrixMultiplication(self): 192 unformatted_code = textwrap.dedent("""\ 193 a=b@c 194 """) 195 expected_formatted_code = textwrap.dedent("""\ 196 a = b @ c 197 """) 198 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 199 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 200 201 def testNoneKeyword(self): 202 code = """\ 203None.__ne__() 204""" 205 llines = yapf_test_helper.ParseAndUnwrap(code) 206 self.assertCodeEqual(code, reformatter.Reformat(llines)) 207 208 def testAsyncWithPrecedingComment(self): 209 if sys.version_info[1] < 5: 210 return 211 unformatted_code = textwrap.dedent("""\ 212 import asyncio 213 214 # Comment 215 async def bar(): 216 pass 217 218 async def foo(): 219 pass 220 """) 221 expected_formatted_code = textwrap.dedent("""\ 222 import asyncio 223 224 225 # Comment 226 async def bar(): 227 pass 228 229 230 async def foo(): 231 pass 232 """) 233 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 234 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 235 236 def testAsyncFunctionsNested(self): 237 if sys.version_info[1] < 5: 238 return 239 code = textwrap.dedent("""\ 240 async def outer(): 241 242 async def inner(): 243 pass 244 """) 245 llines = yapf_test_helper.ParseAndUnwrap(code) 246 self.assertCodeEqual(code, reformatter.Reformat(llines)) 247 248 def testKeepTypesIntact(self): 249 if sys.version_info[1] < 5: 250 return 251 unformatted_code = textwrap.dedent("""\ 252 def _ReduceAbstractContainers( 253 self, *args: Optional[automation_converter.PyiCollectionAbc]) -> List[ 254 automation_converter.PyiCollectionAbc]: 255 pass 256 """) # noqa 257 expected_formatted_code = textwrap.dedent("""\ 258 def _ReduceAbstractContainers( 259 self, *args: Optional[automation_converter.PyiCollectionAbc] 260 ) -> List[automation_converter.PyiCollectionAbc]: 261 pass 262 """) 263 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 264 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 265 266 def testContinuationIndentWithAsync(self): 267 if sys.version_info[1] < 5: 268 return 269 unformatted_code = textwrap.dedent("""\ 270 async def start_websocket(): 271 async with session.ws_connect( 272 r"ws://a_really_long_long_long_long_long_long_url") as ws: 273 pass 274 """) 275 expected_formatted_code = textwrap.dedent("""\ 276 async def start_websocket(): 277 async with session.ws_connect( 278 r"ws://a_really_long_long_long_long_long_long_url") as ws: 279 pass 280 """) 281 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 282 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 283 284 def testSplittingArguments(self): 285 if sys.version_info[1] < 5: 286 return 287 288 unformatted_code = """\ 289async def open_file(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None): 290 pass 291 292async def run_sync_in_worker_thread(sync_fn, *args, cancellable=False, limiter=None): 293 pass 294 295def open_file(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None): 296 pass 297 298def run_sync_in_worker_thread(sync_fn, *args, cancellable=False, limiter=None): 299 pass 300""" # noqa 301 expected_formatted_code = """\ 302async def open_file( 303 file, 304 mode='r', 305 buffering=-1, 306 encoding=None, 307 errors=None, 308 newline=None, 309 closefd=True, 310 opener=None 311): 312 pass 313 314 315async def run_sync_in_worker_thread( 316 sync_fn, *args, cancellable=False, limiter=None 317): 318 pass 319 320 321def open_file( 322 file, 323 mode='r', 324 buffering=-1, 325 encoding=None, 326 errors=None, 327 newline=None, 328 closefd=True, 329 opener=None 330): 331 pass 332 333 334def run_sync_in_worker_thread(sync_fn, *args, cancellable=False, limiter=None): 335 pass 336""" 337 338 try: 339 style.SetGlobalStyle( 340 style.CreateStyleFromConfig( 341 '{based_on_style: pep8, ' 342 'dedent_closing_brackets: true, ' 343 'coalesce_brackets: false, ' 344 'space_between_ending_comma_and_closing_bracket: false, ' 345 'split_arguments_when_comma_terminated: true, ' 346 'split_before_first_argument: true}')) 347 348 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 349 self.assertCodeEqual(expected_formatted_code, 350 reformatter.Reformat(llines)) 351 finally: 352 style.SetGlobalStyle(style.CreatePEP8Style()) 353 354 def testDictUnpacking(self): 355 if sys.version_info[1] < 5: 356 return 357 unformatted_code = """\ 358class Foo: 359 def foo(self): 360 foofoofoofoofoofoofoofoo('foofoofoofoofoo', { 361 362 'foo': 'foo', 363 364 **foofoofoo 365 }) 366""" 367 expected_formatted_code = """\ 368class Foo: 369 370 def foo(self): 371 foofoofoofoofoofoofoofoo('foofoofoofoofoo', { 372 'foo': 'foo', 373 **foofoofoo 374 }) 375""" 376 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 377 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 378 379 def testMultilineFormatString(self): 380 if sys.version_info[1] < 6: 381 return 382 code = """\ 383# yapf: disable 384(f''' 385 ''') 386# yapf: enable 387""" 388 # https://github.com/google/yapf/issues/513 389 llines = yapf_test_helper.ParseAndUnwrap(code) 390 self.assertCodeEqual(code, reformatter.Reformat(llines)) 391 392 def testEllipses(self): 393 if sys.version_info[1] < 6: 394 return 395 code = """\ 396def dirichlet(x12345678901234567890123456789012345678901234567890=...) -> None: 397 return 398""" 399 # https://github.com/google/yapf/issues/533 400 llines = yapf_test_helper.ParseAndUnwrap(code) 401 self.assertCodeEqual(code, reformatter.Reformat(llines)) 402 403 def testFunctionTypedReturnNextLine(self): 404 code = """\ 405def _GenerateStatsEntries( 406 process_id: Text, 407 timestamp: Optional[ffffffff.FFFFFFFFFFF] = None 408) -> Sequence[ssssssssssss.SSSSSSSSSSSSSSS]: 409 pass 410""" 411 llines = yapf_test_helper.ParseAndUnwrap(code) 412 self.assertCodeEqual(code, reformatter.Reformat(llines)) 413 414 def testFunctionTypedReturnSameLine(self): 415 code = """\ 416def rrrrrrrrrrrrrrrrrrrrrr( 417 ccccccccccccccccccccccc: Tuple[Text, Text]) -> List[Tuple[Text, Text]]: 418 pass 419""" 420 llines = yapf_test_helper.ParseAndUnwrap(code) 421 self.assertCodeEqual(code, reformatter.Reformat(llines)) 422 423 def testAsyncForElseNotIndentedInsideBody(self): 424 if sys.version_info[1] < 5: 425 return 426 code = textwrap.dedent("""\ 427 async def fn(): 428 async for message in websocket: 429 for i in range(10): 430 pass 431 else: 432 pass 433 else: 434 pass 435 """) 436 llines = yapf_test_helper.ParseAndUnwrap(code) 437 self.assertCodeEqual(code, reformatter.Reformat(llines)) 438 439 def testForElseInAsyncNotMixedWithAsyncFor(self): 440 if sys.version_info[1] < 5: 441 return 442 code = textwrap.dedent("""\ 443 async def fn(): 444 for i in range(10): 445 pass 446 else: 447 pass 448 """) 449 llines = yapf_test_helper.ParseAndUnwrap(code) 450 self.assertCodeEqual(code, reformatter.Reformat(llines)) 451 452 def testParameterListIndentationConflicts(self): 453 unformatted_code = textwrap.dedent("""\ 454 def raw_message( # pylint: disable=too-many-arguments 455 self, text, user_id=1000, chat_type='private', forward_date=None, forward_from=None): 456 pass 457 """) # noqa 458 expected_formatted_code = textwrap.dedent("""\ 459 def raw_message( # pylint: disable=too-many-arguments 460 self, 461 text, 462 user_id=1000, 463 chat_type='private', 464 forward_date=None, 465 forward_from=None): 466 pass 467 """) 468 llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) 469 self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(llines)) 470 471 472if __name__ == '__main__': 473 unittest.main() 474