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