1# -*- coding: utf-8 -*- 2# Copyright 2015 Google Inc. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15"""Tests for yapf.yapf.""" 16 17import io 18import logging 19import os 20import shutil 21import subprocess 22import sys 23import tempfile 24import textwrap 25import unittest 26 27from lib2to3.pgen2 import tokenize 28 29from yapf.yapflib import errors 30from yapf.yapflib import py3compat 31from yapf.yapflib import style 32from yapf.yapflib import yapf_api 33 34from yapftests import utils 35from yapftests import yapf_test_helper 36 37ROOT_DIR = os.path.dirname(os.path.abspath(os.path.dirname(__file__))) 38 39# Verification is turned off by default, but want to enable it for testing. 40YAPF_BINARY = [sys.executable, '-m', 'yapf', '--verify', '--no-local-style'] 41 42 43class FormatCodeTest(yapf_test_helper.YAPFTest): 44 45 def _Check(self, unformatted_code, expected_formatted_code): 46 formatted_code, _ = yapf_api.FormatCode( 47 unformatted_code, style_config='yapf') 48 self.assertCodeEqual(expected_formatted_code, formatted_code) 49 50 def testSimple(self): 51 unformatted_code = textwrap.dedent("""\ 52 print('foo') 53 """) 54 self._Check(unformatted_code, unformatted_code) 55 56 def testNoEndingNewline(self): 57 unformatted_code = textwrap.dedent("""\ 58 if True: 59 pass""") 60 expected_formatted_code = textwrap.dedent("""\ 61 if True: 62 pass 63 """) 64 self._Check(unformatted_code, expected_formatted_code) 65 66 @unittest.skipUnless(py3compat.PY36, 'Requires Python 3.6') 67 def testPrintAfterPeriod(self): 68 unformatted_code = textwrap.dedent("""a.print\n""") 69 expected_formatted_code = textwrap.dedent("""a.print\n""") 70 self._Check(unformatted_code, expected_formatted_code) 71 72 73class FormatFileTest(unittest.TestCase): 74 75 def setUp(self): # pylint: disable=g-missing-super-call 76 self.test_tmpdir = tempfile.mkdtemp() 77 78 def tearDown(self): # pylint: disable=g-missing-super-call 79 shutil.rmtree(self.test_tmpdir) 80 81 def assertCodeEqual(self, expected_code, code): 82 if code != expected_code: 83 msg = 'Code format mismatch:\n' 84 msg += 'Expected:\n >' 85 msg += '\n > '.join(expected_code.splitlines()) 86 msg += '\nActual:\n >' 87 msg += '\n > '.join(code.splitlines()) 88 # TODO(sbc): maybe using difflib here to produce easy to read deltas? 89 self.fail(msg) 90 91 def testFormatFile(self): 92 unformatted_code = textwrap.dedent(u"""\ 93 if True: 94 pass 95 """) 96 expected_formatted_code_pep8 = textwrap.dedent(u"""\ 97 if True: 98 pass 99 """) 100 expected_formatted_code_yapf = textwrap.dedent(u"""\ 101 if True: 102 pass 103 """) 104 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 105 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 106 self.assertCodeEqual(expected_formatted_code_pep8, formatted_code) 107 108 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='yapf') 109 self.assertCodeEqual(expected_formatted_code_yapf, formatted_code) 110 111 def testDisableLinesPattern(self): 112 unformatted_code = textwrap.dedent(u"""\ 113 if a: b 114 115 # yapf: disable 116 if f: g 117 118 if h: i 119 """) 120 expected_formatted_code = textwrap.dedent(u"""\ 121 if a: b 122 123 # yapf: disable 124 if f: g 125 126 if h: i 127 """) 128 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 129 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 130 self.assertCodeEqual(expected_formatted_code, formatted_code) 131 132 def testDisableAndReenableLinesPattern(self): 133 unformatted_code = textwrap.dedent(u"""\ 134 if a: b 135 136 # yapf: disable 137 if f: g 138 # yapf: enable 139 140 if h: i 141 """) 142 expected_formatted_code = textwrap.dedent(u"""\ 143 if a: b 144 145 # yapf: disable 146 if f: g 147 # yapf: enable 148 149 if h: i 150 """) 151 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 152 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 153 self.assertCodeEqual(expected_formatted_code, formatted_code) 154 155 def testDisablePartOfMultilineComment(self): 156 unformatted_code = textwrap.dedent(u"""\ 157 if a: b 158 159 # This is a multiline comment that disables YAPF. 160 # yapf: disable 161 if f: g 162 # yapf: enable 163 # This is a multiline comment that enables YAPF. 164 165 if h: i 166 """) 167 168 expected_formatted_code = textwrap.dedent(u"""\ 169 if a: b 170 171 # This is a multiline comment that disables YAPF. 172 # yapf: disable 173 if f: g 174 # yapf: enable 175 # This is a multiline comment that enables YAPF. 176 177 if h: i 178 """) 179 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 180 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 181 self.assertCodeEqual(expected_formatted_code, formatted_code) 182 183 code = textwrap.dedent(u"""\ 184 def foo_function(): 185 # some comment 186 # yapf: disable 187 188 foo( 189 bar, 190 baz 191 ) 192 193 # yapf: enable 194 """) 195 with utils.TempFileContents(self.test_tmpdir, code) as filepath: 196 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 197 self.assertCodeEqual(code, formatted_code) 198 199 def testEnabledDisabledSameComment(self): 200 code = textwrap.dedent(u"""\ 201 # yapf: disable 202 a(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, ddddddddddddddddddddddd, eeeeeeeeeeeeeeeeeeeeeeeeeee) 203 # yapf: enable 204 # yapf: disable 205 a(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, ddddddddddddddddddddddd, eeeeeeeeeeeeeeeeeeeeeeeeeee) 206 # yapf: enable 207 """) # noqa 208 with utils.TempFileContents(self.test_tmpdir, code) as filepath: 209 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 210 self.assertCodeEqual(code, formatted_code) 211 212 def testFormatFileLinesSelection(self): 213 unformatted_code = textwrap.dedent(u"""\ 214 if a: b 215 216 if f: g 217 218 if h: i 219 """) 220 expected_formatted_code_lines1and2 = textwrap.dedent(u"""\ 221 if a: b 222 223 if f: g 224 225 if h: i 226 """) 227 expected_formatted_code_lines3 = textwrap.dedent(u"""\ 228 if a: b 229 230 if f: g 231 232 if h: i 233 """) 234 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 235 formatted_code, _, _ = yapf_api.FormatFile( 236 filepath, style_config='pep8', lines=[(1, 2)]) 237 self.assertCodeEqual(expected_formatted_code_lines1and2, formatted_code) 238 formatted_code, _, _ = yapf_api.FormatFile( 239 filepath, style_config='pep8', lines=[(3, 3)]) 240 self.assertCodeEqual(expected_formatted_code_lines3, formatted_code) 241 242 def testFormatFileDiff(self): 243 unformatted_code = textwrap.dedent(u"""\ 244 if True: 245 pass 246 """) 247 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 248 diff, _, _ = yapf_api.FormatFile(filepath, print_diff=True) 249 self.assertIn(u'+ pass', diff) 250 251 def testFormatFileInPlace(self): 252 unformatted_code = u'True==False\n' 253 formatted_code = u'True == False\n' 254 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 255 result, _, _ = yapf_api.FormatFile(filepath, in_place=True) 256 self.assertEqual(result, None) 257 with open(filepath) as fd: 258 if sys.version_info[0] <= 2: 259 self.assertCodeEqual(formatted_code, fd.read().decode('ascii')) 260 else: 261 self.assertCodeEqual(formatted_code, fd.read()) 262 263 self.assertRaises( 264 ValueError, 265 yapf_api.FormatFile, 266 filepath, 267 in_place=True, 268 print_diff=True) 269 270 def testNoFile(self): 271 stream = py3compat.StringIO() 272 handler = logging.StreamHandler(stream) 273 logger = logging.getLogger('mylogger') 274 logger.addHandler(handler) 275 self.assertRaises( 276 IOError, yapf_api.FormatFile, 'not_a_file.py', logger=logger.error) 277 self.assertEqual(stream.getvalue(), 278 "[Errno 2] No such file or directory: 'not_a_file.py'\n") 279 280 def testCommentsUnformatted(self): 281 code = textwrap.dedent(u"""\ 282 foo = [# A list of things 283 # bork 284 'one', 285 # quark 286 'two'] # yapf: disable 287 """) 288 with utils.TempFileContents(self.test_tmpdir, code) as filepath: 289 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 290 self.assertCodeEqual(code, formatted_code) 291 292 def testDisabledHorizontalFormattingOnNewLine(self): 293 code = textwrap.dedent(u"""\ 294 # yapf: disable 295 a = [ 296 1] 297 # yapf: enable 298 """) 299 with utils.TempFileContents(self.test_tmpdir, code) as filepath: 300 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 301 self.assertCodeEqual(code, formatted_code) 302 303 def testSplittingSemicolonStatements(self): 304 unformatted_code = textwrap.dedent(u"""\ 305 def f(): 306 x = y + 42 ; z = n * 42 307 if True: a += 1 ; b += 1; c += 1 308 """) 309 expected_formatted_code = textwrap.dedent(u"""\ 310 def f(): 311 x = y + 42 312 z = n * 42 313 if True: 314 a += 1 315 b += 1 316 c += 1 317 """) 318 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 319 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 320 self.assertCodeEqual(expected_formatted_code, formatted_code) 321 322 def testSemicolonStatementsDisabled(self): 323 unformatted_code = textwrap.dedent(u"""\ 324 def f(): 325 x = y + 42 ; z = n * 42 # yapf: disable 326 if True: a += 1 ; b += 1; c += 1 327 """) 328 expected_formatted_code = textwrap.dedent(u"""\ 329 def f(): 330 x = y + 42 ; z = n * 42 # yapf: disable 331 if True: 332 a += 1 333 b += 1 334 c += 1 335 """) 336 with utils.TempFileContents(self.test_tmpdir, unformatted_code) as filepath: 337 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 338 self.assertCodeEqual(expected_formatted_code, formatted_code) 339 340 def testDisabledSemiColonSeparatedStatements(self): 341 code = textwrap.dedent(u"""\ 342 # yapf: disable 343 if True: a ; b 344 """) 345 with utils.TempFileContents(self.test_tmpdir, code) as filepath: 346 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='pep8') 347 self.assertCodeEqual(code, formatted_code) 348 349 def testDisabledMultilineStringInDictionary(self): 350 code = textwrap.dedent(u"""\ 351 # yapf: disable 352 353 A = [ 354 { 355 "aaaaaaaaaaaaaaaaaaa": ''' 356 bbbbbbbbbbb: "ccccccccccc" 357 dddddddddddddd: 1 358 eeeeeeee: 0 359 ffffffffff: "ggggggg" 360 ''', 361 }, 362 ] 363 """) 364 with utils.TempFileContents(self.test_tmpdir, code) as filepath: 365 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='yapf') 366 self.assertCodeEqual(code, formatted_code) 367 368 def testDisabledWithPrecedingText(self): 369 code = textwrap.dedent(u"""\ 370 # TODO(fix formatting): yapf: disable 371 372 A = [ 373 { 374 "aaaaaaaaaaaaaaaaaaa": ''' 375 bbbbbbbbbbb: "ccccccccccc" 376 dddddddddddddd: 1 377 eeeeeeee: 0 378 ffffffffff: "ggggggg" 379 ''', 380 }, 381 ] 382 """) 383 with utils.TempFileContents(self.test_tmpdir, code) as filepath: 384 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='yapf') 385 self.assertCodeEqual(code, formatted_code) 386 387 def testCRLFLineEnding(self): 388 code = u'class _():\r\n pass\r\n' 389 with utils.TempFileContents(self.test_tmpdir, code) as filepath: 390 formatted_code, _, _ = yapf_api.FormatFile(filepath, style_config='yapf') 391 self.assertCodeEqual(code, formatted_code) 392 393 394class CommandLineTest(unittest.TestCase): 395 """Test how calling yapf from the command line acts.""" 396 397 @classmethod 398 def setUpClass(cls): # pylint: disable=g-missing-super-call 399 cls.test_tmpdir = tempfile.mkdtemp() 400 401 @classmethod 402 def tearDownClass(cls): # pylint: disable=g-missing-super-call 403 shutil.rmtree(cls.test_tmpdir) 404 405 def assertYapfReformats(self, 406 unformatted, 407 expected, 408 extra_options=None, 409 env=None): 410 """Check that yapf reformats the given code as expected. 411 412 Invokes yapf in a subprocess, piping the unformatted code into its stdin. 413 Checks that the formatted output is as expected. 414 415 Arguments: 416 unformatted: unformatted code - input to yapf 417 expected: expected formatted code at the output of yapf 418 extra_options: iterable of extra command-line options to pass to yapf 419 env: dict of environment variables. 420 """ 421 cmdline = YAPF_BINARY + (extra_options or []) 422 p = subprocess.Popen( 423 cmdline, 424 stdout=subprocess.PIPE, 425 stdin=subprocess.PIPE, 426 stderr=subprocess.PIPE, 427 env=env) 428 reformatted_code, stderrdata = p.communicate( 429 unformatted.encode('utf-8-sig')) 430 self.assertEqual(stderrdata, b'') 431 self.assertMultiLineEqual(reformatted_code.decode('utf-8'), expected) 432 433 @unittest.skipUnless(py3compat.PY36, 'Requires Python 3.6') 434 def testUnicodeEncodingPipedToFile(self): 435 unformatted_code = textwrap.dedent(u"""\ 436 def foo(): 437 print('⇒') 438 """) 439 with utils.NamedTempFile( 440 dirname=self.test_tmpdir, suffix='.py') as (out, _): 441 with utils.TempFileContents( 442 self.test_tmpdir, unformatted_code, suffix='.py') as filepath: 443 subprocess.check_call(YAPF_BINARY + ['--diff', filepath], stdout=out) 444 445 def testInPlaceReformatting(self): 446 unformatted_code = textwrap.dedent(u"""\ 447 def foo(): 448 x = 37 449 """) 450 expected_formatted_code = textwrap.dedent("""\ 451 def foo(): 452 x = 37 453 """) 454 with utils.TempFileContents( 455 self.test_tmpdir, unformatted_code, suffix='.py') as filepath: 456 p = subprocess.Popen(YAPF_BINARY + ['--in-place', filepath]) 457 p.wait() 458 with io.open(filepath, mode='r', newline='') as fd: 459 reformatted_code = fd.read() 460 self.assertEqual(reformatted_code, expected_formatted_code) 461 462 def testInPlaceReformattingBlank(self): 463 unformatted_code = u'\n\n' 464 expected_formatted_code = u'\n' 465 with utils.TempFileContents( 466 self.test_tmpdir, unformatted_code, suffix='.py') as filepath: 467 p = subprocess.Popen(YAPF_BINARY + ['--in-place', filepath]) 468 p.wait() 469 with io.open(filepath, mode='r', encoding='utf-8', newline='') as fd: 470 reformatted_code = fd.read() 471 self.assertEqual(reformatted_code, expected_formatted_code) 472 473 def testInPlaceReformattingEmpty(self): 474 unformatted_code = u'' 475 expected_formatted_code = u'' 476 with utils.TempFileContents( 477 self.test_tmpdir, unformatted_code, suffix='.py') as filepath: 478 p = subprocess.Popen(YAPF_BINARY + ['--in-place', filepath]) 479 p.wait() 480 with io.open(filepath, mode='r', encoding='utf-8', newline='') as fd: 481 reformatted_code = fd.read() 482 self.assertEqual(reformatted_code, expected_formatted_code) 483 484 def testReadFromStdin(self): 485 unformatted_code = textwrap.dedent("""\ 486 def foo(): 487 x = 37 488 """) 489 expected_formatted_code = textwrap.dedent("""\ 490 def foo(): 491 x = 37 492 """) 493 self.assertYapfReformats(unformatted_code, expected_formatted_code) 494 495 def testReadFromStdinWithEscapedStrings(self): 496 unformatted_code = textwrap.dedent("""\ 497 s = "foo\\nbar" 498 """) 499 expected_formatted_code = textwrap.dedent("""\ 500 s = "foo\\nbar" 501 """) 502 self.assertYapfReformats(unformatted_code, expected_formatted_code) 503 504 def testSetYapfStyle(self): 505 unformatted_code = textwrap.dedent("""\ 506 def foo(): # trail 507 x = 37 508 """) 509 expected_formatted_code = textwrap.dedent("""\ 510 def foo(): # trail 511 x = 37 512 """) 513 self.assertYapfReformats( 514 unformatted_code, 515 expected_formatted_code, 516 extra_options=['--style=yapf']) 517 518 def testSetCustomStyleBasedOnYapf(self): 519 unformatted_code = textwrap.dedent("""\ 520 def foo(): # trail 521 x = 37 522 """) 523 expected_formatted_code = textwrap.dedent("""\ 524 def foo(): # trail 525 x = 37 526 """) 527 style_file = textwrap.dedent(u'''\ 528 [style] 529 based_on_style = yapf 530 spaces_before_comment = 4 531 ''') 532 with utils.TempFileContents(self.test_tmpdir, style_file) as stylepath: 533 self.assertYapfReformats( 534 unformatted_code, 535 expected_formatted_code, 536 extra_options=['--style={0}'.format(stylepath)]) 537 538 def testSetCustomStyleSpacesBeforeComment(self): 539 unformatted_code = textwrap.dedent("""\ 540 a_very_long_statement_that_extends_way_beyond # Comment 541 short # This is a shorter statement 542 """) 543 expected_formatted_code = textwrap.dedent("""\ 544 a_very_long_statement_that_extends_way_beyond # Comment 545 short # This is a shorter statement 546 """) # noqa 547 style_file = textwrap.dedent(u'''\ 548 [style] 549 spaces_before_comment = 15, 20 550 ''') 551 with utils.TempFileContents(self.test_tmpdir, style_file) as stylepath: 552 self.assertYapfReformats( 553 unformatted_code, 554 expected_formatted_code, 555 extra_options=['--style={0}'.format(stylepath)]) 556 557 def testReadSingleLineCodeFromStdin(self): 558 unformatted_code = textwrap.dedent("""\ 559 if True: pass 560 """) 561 expected_formatted_code = textwrap.dedent("""\ 562 if True: pass 563 """) 564 self.assertYapfReformats(unformatted_code, expected_formatted_code) 565 566 def testEncodingVerification(self): 567 unformatted_code = textwrap.dedent(u"""\ 568 '''The module docstring.''' 569 # -*- coding: utf-8 -*- 570 def f(): 571 x = 37 572 """) 573 574 with utils.NamedTempFile( 575 suffix='.py', dirname=self.test_tmpdir) as (out, _): 576 with utils.TempFileContents( 577 self.test_tmpdir, unformatted_code, suffix='.py') as filepath: 578 try: 579 subprocess.check_call(YAPF_BINARY + ['--diff', filepath], stdout=out) 580 except subprocess.CalledProcessError as e: 581 # Indicates the text changed. 582 self.assertEqual(e.returncode, 1) # pylint: disable=g-assert-in-except # noqa 583 584 def testReformattingSpecificLines(self): 585 unformatted_code = textwrap.dedent("""\ 586 def h(): 587 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 588 pass 589 590 591 def g(): 592 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 593 pass 594 """) # noqa 595 expected_formatted_code = textwrap.dedent("""\ 596 def h(): 597 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and 598 xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 599 pass 600 601 602 def g(): 603 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 604 pass 605 """) # noqa 606 # TODO(ambv): the `expected_formatted_code` here is not PEP8 compliant, 607 # raising "E129 visually indented line with same indent as next logical 608 # line" with flake8. 609 self.assertYapfReformats( 610 unformatted_code, 611 expected_formatted_code, 612 extra_options=['--lines', '1-2']) 613 614 def testOmitFormattingLinesBeforeDisabledFunctionComment(self): 615 unformatted_code = textwrap.dedent("""\ 616 import sys 617 618 # Comment 619 def some_func(x): 620 x = ["badly" , "formatted","line" ] 621 """) 622 expected_formatted_code = textwrap.dedent("""\ 623 import sys 624 625 # Comment 626 def some_func(x): 627 x = ["badly", "formatted", "line"] 628 """) 629 self.assertYapfReformats( 630 unformatted_code, 631 expected_formatted_code, 632 extra_options=['--lines', '5-5']) 633 634 def testReformattingSkippingLines(self): 635 unformatted_code = textwrap.dedent("""\ 636 def h(): 637 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 638 pass 639 640 # yapf: disable 641 def g(): 642 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 643 pass 644 # yapf: enable 645 """) # noqa 646 expected_formatted_code = textwrap.dedent("""\ 647 def h(): 648 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and 649 xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 650 pass 651 652 653 # yapf: disable 654 def g(): 655 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 656 pass 657 # yapf: enable 658 """) # noqa 659 self.assertYapfReformats(unformatted_code, expected_formatted_code) 660 661 def testReformattingSkippingToEndOfFile(self): 662 unformatted_code = textwrap.dedent("""\ 663 def h(): 664 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 665 pass 666 667 # yapf: disable 668 def g(): 669 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 670 pass 671 672 def f(): 673 def e(): 674 while (xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz]) == 'aaaaaaaaaaa' and 675 xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz].aaaaaaaa[0]) == 676 'bbbbbbb'): 677 pass 678 """) # noqa 679 expected_formatted_code = textwrap.dedent("""\ 680 def h(): 681 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and 682 xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 683 pass 684 685 686 # yapf: disable 687 def g(): 688 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 689 pass 690 691 def f(): 692 def e(): 693 while (xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz]) == 'aaaaaaaaaaa' and 694 xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz].aaaaaaaa[0]) == 695 'bbbbbbb'): 696 pass 697 """) # noqa 698 self.assertYapfReformats(unformatted_code, expected_formatted_code) 699 700 def testReformattingSkippingSingleLine(self): 701 unformatted_code = textwrap.dedent("""\ 702 def h(): 703 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 704 pass 705 706 def g(): 707 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): # yapf: disable 708 pass 709 """) # noqa 710 expected_formatted_code = textwrap.dedent("""\ 711 def h(): 712 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and 713 xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 714 pass 715 716 717 def g(): 718 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): # yapf: disable 719 pass 720 """) # noqa 721 self.assertYapfReformats(unformatted_code, expected_formatted_code) 722 723 def testDisableWholeDataStructure(self): 724 unformatted_code = textwrap.dedent("""\ 725 A = set([ 726 'hello', 727 'world', 728 ]) # yapf: disable 729 """) 730 expected_formatted_code = textwrap.dedent("""\ 731 A = set([ 732 'hello', 733 'world', 734 ]) # yapf: disable 735 """) 736 self.assertYapfReformats(unformatted_code, expected_formatted_code) 737 738 def testDisableButAdjustIndentations(self): 739 unformatted_code = textwrap.dedent("""\ 740 class SplitPenaltyTest(unittest.TestCase): 741 742 def testUnbreakable(self): 743 self._CheckPenalties(tree, [ 744 ]) # yapf: disable 745 """) 746 expected_formatted_code = textwrap.dedent("""\ 747 class SplitPenaltyTest(unittest.TestCase): 748 749 def testUnbreakable(self): 750 self._CheckPenalties(tree, [ 751 ]) # yapf: disable 752 """) 753 self.assertYapfReformats(unformatted_code, expected_formatted_code) 754 755 def testRetainingHorizontalWhitespace(self): 756 unformatted_code = textwrap.dedent("""\ 757 def h(): 758 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 759 pass 760 761 def g(): 762 if (xxxxxxxxxxxx.yyyyyyyy (zzzzzzzzzzzzz [0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): # yapf: disable 763 pass 764 """) # noqa 765 expected_formatted_code = textwrap.dedent("""\ 766 def h(): 767 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and 768 xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 769 pass 770 771 772 def g(): 773 if (xxxxxxxxxxxx.yyyyyyyy (zzzzzzzzzzzzz [0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): # yapf: disable 774 pass 775 """) # noqa 776 self.assertYapfReformats(unformatted_code, expected_formatted_code) 777 778 def testRetainingVerticalWhitespace(self): 779 unformatted_code = textwrap.dedent("""\ 780 def h(): 781 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 782 pass 783 784 def g(): 785 786 787 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 788 789 pass 790 """) # noqa 791 expected_formatted_code = textwrap.dedent("""\ 792 def h(): 793 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and 794 xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 795 pass 796 797 def g(): 798 799 800 if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'): 801 802 pass 803 """) # noqa 804 self.assertYapfReformats( 805 unformatted_code, 806 expected_formatted_code, 807 extra_options=['--lines', '1-2']) 808 809 unformatted_code = textwrap.dedent("""\ 810 811 812 if a: b 813 814 815 if c: 816 to_much + indent 817 818 same 819 820 821 822 #comment 823 824 # trailing whitespace 825 """) 826 expected_formatted_code = textwrap.dedent("""\ 827 if a: b 828 829 830 if c: 831 to_much + indent 832 833 same 834 835 836 837 #comment 838 839 # trailing whitespace 840 """) 841 self.assertYapfReformats( 842 unformatted_code, 843 expected_formatted_code, 844 extra_options=['--lines', '3-3', '--lines', '13-13']) 845 846 unformatted_code = textwrap.dedent("""\ 847 ''' 848 docstring 849 850 ''' 851 852 import blah 853 """) 854 855 self.assertYapfReformats( 856 unformatted_code, unformatted_code, extra_options=['--lines', '2-2']) 857 858 def testVerticalSpacingWithCommentWithContinuationMarkers(self): 859 unformatted_code = """\ 860# \\ 861# \\ 862# \\ 863 864x = { 865} 866""" 867 expected_formatted_code = """\ 868# \\ 869# \\ 870# \\ 871 872x = { 873} 874""" 875 self.assertYapfReformats( 876 unformatted_code, 877 expected_formatted_code, 878 extra_options=['--lines', '1-1']) 879 880 def testRetainingSemicolonsWhenSpecifyingLines(self): 881 unformatted_code = textwrap.dedent("""\ 882 a = line_to_format 883 def f(): 884 x = y + 42; z = n * 42 885 if True: a += 1 ; b += 1 ; c += 1 886 """) 887 expected_formatted_code = textwrap.dedent("""\ 888 a = line_to_format 889 def f(): 890 x = y + 42; z = n * 42 891 if True: a += 1 ; b += 1 ; c += 1 892 """) 893 self.assertYapfReformats( 894 unformatted_code, 895 expected_formatted_code, 896 extra_options=['--lines', '1-1']) 897 898 def testDisabledMultilineStrings(self): 899 unformatted_code = textwrap.dedent('''\ 900 foo=42 901 def f(): 902 email_text += """<html>This is a really long docstring that goes over the column limit and is multi-line.<br><br> 903 <b>Czar: </b>"""+despot["Nicholas"]+"""<br> 904 <b>Minion: </b>"""+serf["Dmitri"]+"""<br> 905 <b>Residence: </b>"""+palace["Winter"]+"""<br> 906 </body> 907 </html>""" 908 ''') # noqa 909 expected_formatted_code = textwrap.dedent('''\ 910 foo = 42 911 def f(): 912 email_text += """<html>This is a really long docstring that goes over the column limit and is multi-line.<br><br> 913 <b>Czar: </b>"""+despot["Nicholas"]+"""<br> 914 <b>Minion: </b>"""+serf["Dmitri"]+"""<br> 915 <b>Residence: </b>"""+palace["Winter"]+"""<br> 916 </body> 917 </html>""" 918 ''') # noqa 919 self.assertYapfReformats( 920 unformatted_code, 921 expected_formatted_code, 922 extra_options=['--lines', '1-1']) 923 924 def testDisableWhenSpecifyingLines(self): 925 unformatted_code = textwrap.dedent("""\ 926 # yapf: disable 927 A = set([ 928 'hello', 929 'world', 930 ]) 931 # yapf: enable 932 B = set([ 933 'hello', 934 'world', 935 ]) # yapf: disable 936 """) 937 expected_formatted_code = textwrap.dedent("""\ 938 # yapf: disable 939 A = set([ 940 'hello', 941 'world', 942 ]) 943 # yapf: enable 944 B = set([ 945 'hello', 946 'world', 947 ]) # yapf: disable 948 """) 949 self.assertYapfReformats( 950 unformatted_code, 951 expected_formatted_code, 952 extra_options=['--lines', '1-10']) 953 954 def testDisableFormattingInDataLiteral(self): 955 unformatted_code = textwrap.dedent("""\ 956 def horrible(): 957 oh_god() 958 why_would_you() 959 [ 960 'do', 961 962 'that', 963 ] 964 965 def still_horrible(): 966 oh_god() 967 why_would_you() 968 [ 969 'do', 970 971 'that' 972 ] 973 """) 974 expected_formatted_code = textwrap.dedent("""\ 975 def horrible(): 976 oh_god() 977 why_would_you() 978 [ 979 'do', 980 981 'that', 982 ] 983 984 def still_horrible(): 985 oh_god() 986 why_would_you() 987 ['do', 'that'] 988 """) 989 self.assertYapfReformats( 990 unformatted_code, 991 expected_formatted_code, 992 extra_options=['--lines', '14-15']) 993 994 def testRetainVerticalFormattingBetweenDisabledAndEnabledLines(self): 995 unformatted_code = textwrap.dedent("""\ 996 class A(object): 997 def aaaaaaaaaaaaa(self): 998 c = bbbbbbbbb.ccccccccc('challenge', 0, 1, 10) 999 self.assertEqual( 1000 ('ddddddddddddddddddddddddd', 1001 'eeeeeeeeeeeeeeeeeeeeeeeee.%s' % 1002 c.ffffffffffff), 1003 gggggggggggg.hhhhhhhhh(c, c.ffffffffffff)) 1004 iiiii = jjjjjjjjjjjjjj.iiiii 1005 """) 1006 expected_formatted_code = textwrap.dedent("""\ 1007 class A(object): 1008 def aaaaaaaaaaaaa(self): 1009 c = bbbbbbbbb.ccccccccc('challenge', 0, 1, 10) 1010 self.assertEqual(('ddddddddddddddddddddddddd', 1011 'eeeeeeeeeeeeeeeeeeeeeeeee.%s' % c.ffffffffffff), 1012 gggggggggggg.hhhhhhhhh(c, c.ffffffffffff)) 1013 iiiii = jjjjjjjjjjjjjj.iiiii 1014 """) # noqa 1015 self.assertYapfReformats( 1016 unformatted_code, 1017 expected_formatted_code, 1018 extra_options=['--lines', '4-7']) 1019 1020 def testRetainVerticalFormattingBetweenDisabledLines(self): 1021 unformatted_code = textwrap.dedent("""\ 1022 class A(object): 1023 def aaaaaaaaaaaaa(self): 1024 pass 1025 1026 1027 def bbbbbbbbbbbbb(self): # 5 1028 pass 1029 """) 1030 expected_formatted_code = textwrap.dedent("""\ 1031 class A(object): 1032 def aaaaaaaaaaaaa(self): 1033 pass 1034 1035 1036 def bbbbbbbbbbbbb(self): # 5 1037 pass 1038 """) 1039 self.assertYapfReformats( 1040 unformatted_code, 1041 expected_formatted_code, 1042 extra_options=['--lines', '4-4']) 1043 1044 def testFormatLinesSpecifiedInMiddleOfExpression(self): 1045 unformatted_code = textwrap.dedent("""\ 1046 class A(object): 1047 def aaaaaaaaaaaaa(self): 1048 c = bbbbbbbbb.ccccccccc('challenge', 0, 1, 10) 1049 self.assertEqual( 1050 ('ddddddddddddddddddddddddd', 1051 'eeeeeeeeeeeeeeeeeeeeeeeee.%s' % 1052 c.ffffffffffff), 1053 gggggggggggg.hhhhhhhhh(c, c.ffffffffffff)) 1054 iiiii = jjjjjjjjjjjjjj.iiiii 1055 """) 1056 expected_formatted_code = textwrap.dedent("""\ 1057 class A(object): 1058 def aaaaaaaaaaaaa(self): 1059 c = bbbbbbbbb.ccccccccc('challenge', 0, 1, 10) 1060 self.assertEqual(('ddddddddddddddddddddddddd', 1061 'eeeeeeeeeeeeeeeeeeeeeeeee.%s' % c.ffffffffffff), 1062 gggggggggggg.hhhhhhhhh(c, c.ffffffffffff)) 1063 iiiii = jjjjjjjjjjjjjj.iiiii 1064 """) # noqa 1065 self.assertYapfReformats( 1066 unformatted_code, 1067 expected_formatted_code, 1068 extra_options=['--lines', '5-6']) 1069 1070 def testCommentFollowingMultilineString(self): 1071 unformatted_code = textwrap.dedent("""\ 1072 def foo(): 1073 '''First line. 1074 Second line. 1075 ''' # comment 1076 x = '''hello world''' # second comment 1077 return 42 # another comment 1078 """) 1079 expected_formatted_code = textwrap.dedent("""\ 1080 def foo(): 1081 '''First line. 1082 Second line. 1083 ''' # comment 1084 x = '''hello world''' # second comment 1085 return 42 # another comment 1086 """) 1087 self.assertYapfReformats( 1088 unformatted_code, 1089 expected_formatted_code, 1090 extra_options=['--lines', '1-1']) 1091 1092 def testDedentClosingBracket(self): 1093 # no line-break on the first argument, not dedenting closing brackets 1094 unformatted_code = textwrap.dedent("""\ 1095 def overly_long_function_name(first_argument_on_the_same_line, 1096 second_argument_makes_the_line_too_long): 1097 pass 1098 """) 1099 expected_formatted_code = textwrap.dedent("""\ 1100 def overly_long_function_name(first_argument_on_the_same_line, 1101 second_argument_makes_the_line_too_long): 1102 pass 1103 """) 1104 self.assertYapfReformats( 1105 unformatted_code, 1106 expected_formatted_code, 1107 extra_options=['--style=pep8']) 1108 1109 # TODO(ambv): currently the following produces the closing bracket on a new 1110 # line but indented to the opening bracket which is the worst of both 1111 # worlds. Expected behaviour would be to format as --style=pep8 does in 1112 # this case. 1113 # self.assertYapfReformats(unformatted_code, expected_formatted_code, 1114 # extra_options=['--style=facebook']) 1115 1116 # line-break before the first argument, dedenting closing brackets if set 1117 unformatted_code = textwrap.dedent("""\ 1118 def overly_long_function_name( 1119 first_argument_on_the_same_line, 1120 second_argument_makes_the_line_too_long): 1121 pass 1122 """) 1123 # expected_formatted_pep8_code = textwrap.dedent("""\ 1124 # def overly_long_function_name( 1125 # first_argument_on_the_same_line, 1126 # second_argument_makes_the_line_too_long): 1127 # pass 1128 # """) 1129 expected_formatted_fb_code = textwrap.dedent("""\ 1130 def overly_long_function_name( 1131 first_argument_on_the_same_line, second_argument_makes_the_line_too_long 1132 ): 1133 pass 1134 """) # noqa 1135 self.assertYapfReformats( 1136 unformatted_code, 1137 expected_formatted_fb_code, 1138 extra_options=['--style=facebook']) 1139 # TODO(ambv): currently the following produces code that is not PEP8 1140 # compliant, raising "E125 continuation line with same indent as next 1141 # logical line" with flake8. Expected behaviour for PEP8 would be to use 1142 # double-indentation here. 1143 # self.assertYapfReformats(unformatted_code, expected_formatted_pep8_code, 1144 # extra_options=['--style=pep8']) 1145 1146 def testCoalesceBrackets(self): 1147 unformatted_code = textwrap.dedent("""\ 1148 some_long_function_name_foo( 1149 { 1150 'first_argument_of_the_thing': id, 1151 'second_argument_of_the_thing': "some thing" 1152 } 1153 )""") 1154 expected_formatted_code = textwrap.dedent("""\ 1155 some_long_function_name_foo({ 1156 'first_argument_of_the_thing': id, 1157 'second_argument_of_the_thing': "some thing" 1158 }) 1159 """) 1160 with utils.NamedTempFile(dirname=self.test_tmpdir, mode='w') as (f, name): 1161 f.write( 1162 textwrap.dedent(u'''\ 1163 [style] 1164 column_limit=82 1165 coalesce_brackets = True 1166 ''')) 1167 f.flush() 1168 self.assertYapfReformats( 1169 unformatted_code, 1170 expected_formatted_code, 1171 extra_options=['--style={0}'.format(name)]) 1172 1173 def testPseudoParenSpaces(self): 1174 unformatted_code = textwrap.dedent("""\ 1175 def foo(): 1176 def bar(): 1177 return {msg_id: author for author, msg_id in reader} 1178 """) 1179 expected_formatted_code = textwrap.dedent("""\ 1180 def foo(): 1181 def bar(): 1182 return {msg_id: author for author, msg_id in reader} 1183 """) 1184 self.assertYapfReformats( 1185 unformatted_code, 1186 expected_formatted_code, 1187 extra_options=['--lines', '1-1', '--style', 'yapf']) 1188 1189 def testMultilineCommentFormattingDisabled(self): 1190 unformatted_code = textwrap.dedent("""\ 1191 # This is a comment 1192 FOO = { 1193 aaaaaaaa.ZZZ: [ 1194 bbbbbbbbbb.Pop(), 1195 # Multiline comment. 1196 # Line two. 1197 bbbbbbbbbb.Pop(), 1198 ], 1199 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': 1200 ('yyyyy', zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz), 1201 '#': lambda x: x # do nothing 1202 } 1203 """) 1204 expected_formatted_code = textwrap.dedent("""\ 1205 # This is a comment 1206 FOO = { 1207 aaaaaaaa.ZZZ: [ 1208 bbbbbbbbbb.Pop(), 1209 # Multiline comment. 1210 # Line two. 1211 bbbbbbbbbb.Pop(), 1212 ], 1213 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': 1214 ('yyyyy', zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz), 1215 '#': lambda x: x # do nothing 1216 } 1217 """) 1218 self.assertYapfReformats( 1219 unformatted_code, 1220 expected_formatted_code, 1221 extra_options=['--lines', '1-1', '--style', 'yapf']) 1222 1223 def testTrailingCommentsWithDisabledFormatting(self): 1224 unformatted_code = textwrap.dedent("""\ 1225 import os 1226 1227 SCOPES = [ 1228 'hello world' # This is a comment. 1229 ] 1230 """) 1231 expected_formatted_code = textwrap.dedent("""\ 1232 import os 1233 1234 SCOPES = [ 1235 'hello world' # This is a comment. 1236 ] 1237 """) 1238 self.assertYapfReformats( 1239 unformatted_code, 1240 expected_formatted_code, 1241 extra_options=['--lines', '1-1', '--style', 'yapf']) 1242 1243 def testUseTabs(self): 1244 unformatted_code = """\ 1245def foo_function(): 1246 if True: 1247 pass 1248""" 1249 expected_formatted_code = """\ 1250def foo_function(): 1251 if True: 1252 pass 1253""" # noqa: W191,E101 1254 style_contents = u"""\ 1255[style] 1256based_on_style = yapf 1257USE_TABS = true 1258INDENT_WIDTH=1 1259""" 1260 with utils.TempFileContents(self.test_tmpdir, style_contents) as stylepath: 1261 self.assertYapfReformats( 1262 unformatted_code, 1263 expected_formatted_code, 1264 extra_options=['--style={0}'.format(stylepath)]) 1265 1266 def testUseTabsWith(self): 1267 unformatted_code = """\ 1268def f(): 1269 return ['hello', 'world',] 1270""" 1271 expected_formatted_code = """\ 1272def f(): 1273 return [ 1274 'hello', 1275 'world', 1276 ] 1277""" # noqa: W191,E101 1278 style_contents = u"""\ 1279[style] 1280based_on_style = yapf 1281USE_TABS = true 1282INDENT_WIDTH=1 1283""" 1284 with utils.TempFileContents(self.test_tmpdir, style_contents) as stylepath: 1285 self.assertYapfReformats( 1286 unformatted_code, 1287 expected_formatted_code, 1288 extra_options=['--style={0}'.format(stylepath)]) 1289 1290 def testUseTabsContinuationAlignStyleFixed(self): 1291 unformatted_code = """\ 1292def foo_function(arg1, arg2, arg3): 1293 return ['hello', 'world',] 1294""" 1295 expected_formatted_code = """\ 1296def foo_function( 1297 arg1, arg2, arg3): 1298 return [ 1299 'hello', 1300 'world', 1301 ] 1302""" # noqa: W191,E101 1303 style_contents = u"""\ 1304[style] 1305based_on_style = yapf 1306USE_TABS = true 1307COLUMN_LIMIT=32 1308INDENT_WIDTH=4 1309CONTINUATION_INDENT_WIDTH=8 1310CONTINUATION_ALIGN_STYLE = fixed 1311""" 1312 with utils.TempFileContents(self.test_tmpdir, style_contents) as stylepath: 1313 self.assertYapfReformats( 1314 unformatted_code, 1315 expected_formatted_code, 1316 extra_options=['--style={0}'.format(stylepath)]) 1317 1318 def testUseTabsContinuationAlignStyleVAlignRight(self): 1319 unformatted_code = """\ 1320def foo_function(arg1, arg2, arg3): 1321 return ['hello', 'world',] 1322""" 1323 expected_formatted_code = """\ 1324def foo_function(arg1, arg2, 1325 arg3): 1326 return [ 1327 'hello', 1328 'world', 1329 ] 1330""" # noqa: W191,E101 1331 style_contents = u"""\ 1332[style] 1333based_on_style = yapf 1334USE_TABS = true 1335COLUMN_LIMIT=32 1336INDENT_WIDTH=4 1337CONTINUATION_INDENT_WIDTH=8 1338CONTINUATION_ALIGN_STYLE = valign-right 1339""" 1340 with utils.TempFileContents(self.test_tmpdir, style_contents) as stylepath: 1341 self.assertYapfReformats( 1342 unformatted_code, 1343 expected_formatted_code, 1344 extra_options=['--style={0}'.format(stylepath)]) 1345 1346 def testUseSpacesContinuationAlignStyleFixed(self): 1347 unformatted_code = """\ 1348def foo_function(arg1, arg2, arg3): 1349 return ['hello', 'world',] 1350""" 1351 expected_formatted_code = """\ 1352def foo_function( 1353 arg1, arg2, arg3): 1354 return [ 1355 'hello', 1356 'world', 1357 ] 1358""" 1359 style_contents = u"""\ 1360[style] 1361based_on_style = yapf 1362COLUMN_LIMIT=32 1363INDENT_WIDTH=4 1364CONTINUATION_INDENT_WIDTH=8 1365CONTINUATION_ALIGN_STYLE = fixed 1366""" 1367 with utils.TempFileContents(self.test_tmpdir, style_contents) as stylepath: 1368 self.assertYapfReformats( 1369 unformatted_code, 1370 expected_formatted_code, 1371 extra_options=['--style={0}'.format(stylepath)]) 1372 1373 def testUseSpacesContinuationAlignStyleVAlignRight(self): 1374 unformatted_code = """\ 1375def foo_function(arg1, arg2, arg3): 1376 return ['hello', 'world',] 1377""" 1378 expected_formatted_code = """\ 1379def foo_function(arg1, arg2, 1380 arg3): 1381 return [ 1382 'hello', 1383 'world', 1384 ] 1385""" 1386 style_contents = u"""\ 1387[style] 1388based_on_style = yapf 1389COLUMN_LIMIT=32 1390INDENT_WIDTH=4 1391CONTINUATION_INDENT_WIDTH=8 1392CONTINUATION_ALIGN_STYLE = valign-right 1393""" 1394 with utils.TempFileContents(self.test_tmpdir, style_contents) as stylepath: 1395 self.assertYapfReformats( 1396 unformatted_code, 1397 expected_formatted_code, 1398 extra_options=['--style={0}'.format(stylepath)]) 1399 1400 def testStyleOutputRoundTrip(self): 1401 unformatted_code = textwrap.dedent("""\ 1402 def foo_function(): 1403 pass 1404 """) 1405 expected_formatted_code = textwrap.dedent("""\ 1406 def foo_function(): 1407 pass 1408 """) 1409 1410 with utils.NamedTempFile(dirname=self.test_tmpdir) as (stylefile, 1411 stylepath): 1412 p = subprocess.Popen( 1413 YAPF_BINARY + ['--style-help'], 1414 stdout=stylefile, 1415 stdin=subprocess.PIPE, 1416 stderr=subprocess.PIPE) 1417 _, stderrdata = p.communicate() 1418 self.assertEqual(stderrdata, b'') 1419 self.assertYapfReformats( 1420 unformatted_code, 1421 expected_formatted_code, 1422 extra_options=['--style={0}'.format(stylepath)]) 1423 1424 def testSpacingBeforeComments(self): 1425 unformatted_code = textwrap.dedent("""\ 1426 A = 42 1427 1428 1429 # A comment 1430 def x(): 1431 pass 1432 def _(): 1433 pass 1434 """) 1435 expected_formatted_code = textwrap.dedent("""\ 1436 A = 42 1437 1438 1439 # A comment 1440 def x(): 1441 pass 1442 def _(): 1443 pass 1444 """) 1445 self.assertYapfReformats( 1446 unformatted_code, 1447 expected_formatted_code, 1448 extra_options=['--lines', '1-2']) 1449 1450 def testSpacingBeforeCommentsInDicts(self): 1451 unformatted_code = textwrap.dedent("""\ 1452 A=42 1453 1454 X = { 1455 # 'Valid' statuses. 1456 PASSED: # Passed 1457 'PASSED', 1458 FAILED: # Failed 1459 'FAILED', 1460 TIMED_OUT: # Timed out. 1461 'FAILED', 1462 BORKED: # Broken. 1463 'BROKEN' 1464 } 1465 """) 1466 expected_formatted_code = textwrap.dedent("""\ 1467 A = 42 1468 1469 X = { 1470 # 'Valid' statuses. 1471 PASSED: # Passed 1472 'PASSED', 1473 FAILED: # Failed 1474 'FAILED', 1475 TIMED_OUT: # Timed out. 1476 'FAILED', 1477 BORKED: # Broken. 1478 'BROKEN' 1479 } 1480 """) 1481 self.assertYapfReformats( 1482 unformatted_code, 1483 expected_formatted_code, 1484 extra_options=['--style', 'yapf', '--lines', '1-1']) 1485 1486 def testDisableWithLinesOption(self): 1487 unformatted_code = textwrap.dedent("""\ 1488 # yapf_lines_bug.py 1489 # yapf: disable 1490 def outer_func(): 1491 def inner_func(): 1492 return 1493 return 1494 # yapf: enable 1495 """) 1496 expected_formatted_code = textwrap.dedent("""\ 1497 # yapf_lines_bug.py 1498 # yapf: disable 1499 def outer_func(): 1500 def inner_func(): 1501 return 1502 return 1503 # yapf: enable 1504 """) 1505 self.assertYapfReformats( 1506 unformatted_code, 1507 expected_formatted_code, 1508 extra_options=['--lines', '1-8']) 1509 1510 @unittest.skipUnless(py3compat.PY36, 'Requires Python 3.6') 1511 def testNoSpacesAroundBinaryOperators(self): 1512 unformatted_code = """\ 1513a = 4-b/c@d**37 1514""" 1515 expected_formatted_code = """\ 1516a = 4-b / c@d**37 1517""" 1518 self.assertYapfReformats( 1519 unformatted_code, 1520 expected_formatted_code, 1521 extra_options=[ 1522 '--style', 1523 '{based_on_style: pep8, ' 1524 'no_spaces_around_selected_binary_operators: "@,**,-"}', 1525 ]) 1526 1527 @unittest.skipUnless(py3compat.PY36, 'Requires Python 3.6') 1528 def testCP936Encoding(self): 1529 unformatted_code = 'print("中文")\n' 1530 expected_formatted_code = 'print("中文")\n' 1531 self.assertYapfReformats( 1532 unformatted_code, 1533 expected_formatted_code, 1534 env={'PYTHONIOENCODING': 'cp936'}) 1535 1536 def testDisableWithLineRanges(self): 1537 unformatted_code = """\ 1538# yapf: disable 1539a = [ 1540 1, 1541 2, 1542 1543 3 1544] 1545""" 1546 expected_formatted_code = """\ 1547# yapf: disable 1548a = [ 1549 1, 1550 2, 1551 1552 3 1553] 1554""" 1555 self.assertYapfReformats( 1556 unformatted_code, 1557 expected_formatted_code, 1558 extra_options=['--style', 'yapf', '--lines', '1-100']) 1559 1560 1561class BadInputTest(unittest.TestCase): 1562 """Test yapf's behaviour when passed bad input.""" 1563 1564 def testBadSyntax(self): 1565 code = ' a = 1\n' 1566 self.assertRaises(errors.YapfError, yapf_api.FormatCode, code) 1567 1568 def testBadCode(self): 1569 code = 'x = """hello\n' 1570 self.assertRaises(errors.YapfError, yapf_api.FormatCode, code) 1571 1572 1573class DiffIndentTest(unittest.TestCase): 1574 1575 @staticmethod 1576 def _OwnStyle(): 1577 my_style = style.CreatePEP8Style() 1578 my_style['INDENT_WIDTH'] = 3 1579 my_style['CONTINUATION_INDENT_WIDTH'] = 3 1580 return my_style 1581 1582 def _Check(self, unformatted_code, expected_formatted_code): 1583 formatted_code, _ = yapf_api.FormatCode( 1584 unformatted_code, style_config=style.SetGlobalStyle(self._OwnStyle())) 1585 self.assertEqual(expected_formatted_code, formatted_code) 1586 1587 def testSimple(self): 1588 unformatted_code = textwrap.dedent("""\ 1589 for i in range(5): 1590 print('bar') 1591 """) 1592 expected_formatted_code = textwrap.dedent("""\ 1593 for i in range(5): 1594 print('bar') 1595 """) 1596 self._Check(unformatted_code, expected_formatted_code) 1597 1598 1599class HorizontallyAlignedTrailingCommentsTest(yapf_test_helper.YAPFTest): 1600 1601 @staticmethod 1602 def _OwnStyle(): 1603 my_style = style.CreatePEP8Style() 1604 my_style['SPACES_BEFORE_COMMENT'] = [ 1605 15, 1606 25, 1607 35, 1608 ] 1609 return my_style 1610 1611 def _Check(self, unformatted_code, expected_formatted_code): 1612 formatted_code, _ = yapf_api.FormatCode( 1613 unformatted_code, style_config=style.SetGlobalStyle(self._OwnStyle())) 1614 self.assertCodeEqual(expected_formatted_code, formatted_code) 1615 1616 def testSimple(self): 1617 unformatted_code = textwrap.dedent("""\ 1618 foo = '1' # Aligned at first list value 1619 1620 foo = '2__<15>' # Aligned at second list value 1621 1622 foo = '3____________<25>' # Aligned at third list value 1623 1624 foo = '4______________________<35>' # Aligned beyond list values 1625 """) 1626 expected_formatted_code = textwrap.dedent("""\ 1627 foo = '1' # Aligned at first list value 1628 1629 foo = '2__<15>' # Aligned at second list value 1630 1631 foo = '3____________<25>' # Aligned at third list value 1632 1633 foo = '4______________________<35>' # Aligned beyond list values 1634 """) 1635 self._Check(unformatted_code, expected_formatted_code) 1636 1637 def testBlock(self): 1638 unformatted_code = textwrap.dedent("""\ 1639 func(1) # Line 1 1640 func(2) # Line 2 1641 # Line 3 1642 func(3) # Line 4 1643 # Line 5 1644 # Line 6 1645 """) 1646 expected_formatted_code = textwrap.dedent("""\ 1647 func(1) # Line 1 1648 func(2) # Line 2 1649 # Line 3 1650 func(3) # Line 4 1651 # Line 5 1652 # Line 6 1653 """) 1654 self._Check(unformatted_code, expected_formatted_code) 1655 1656 def testBlockWithLongLine(self): 1657 unformatted_code = textwrap.dedent("""\ 1658 func(1) # Line 1 1659 func___________________(2) # Line 2 1660 # Line 3 1661 func(3) # Line 4 1662 # Line 5 1663 # Line 6 1664 """) 1665 expected_formatted_code = textwrap.dedent("""\ 1666 func(1) # Line 1 1667 func___________________(2) # Line 2 1668 # Line 3 1669 func(3) # Line 4 1670 # Line 5 1671 # Line 6 1672 """) 1673 self._Check(unformatted_code, expected_formatted_code) 1674 1675 def testBlockFuncSuffix(self): 1676 unformatted_code = textwrap.dedent("""\ 1677 func(1) # Line 1 1678 func(2) # Line 2 1679 # Line 3 1680 func(3) # Line 4 1681 # Line 5 1682 # Line 6 1683 1684 def Func(): 1685 pass 1686 """) 1687 expected_formatted_code = textwrap.dedent("""\ 1688 func(1) # Line 1 1689 func(2) # Line 2 1690 # Line 3 1691 func(3) # Line 4 1692 # Line 5 1693 # Line 6 1694 1695 1696 def Func(): 1697 pass 1698 """) 1699 self._Check(unformatted_code, expected_formatted_code) 1700 1701 def testBlockCommentSuffix(self): 1702 unformatted_code = textwrap.dedent("""\ 1703 func(1) # Line 1 1704 func(2) # Line 2 1705 # Line 3 1706 func(3) # Line 4 1707 # Line 5 - SpliceComments makes this part of the previous block 1708 # Line 6 1709 1710 # Aligned with prev comment block 1711 """) # noqa 1712 expected_formatted_code = textwrap.dedent("""\ 1713 func(1) # Line 1 1714 func(2) # Line 2 1715 # Line 3 1716 func(3) # Line 4 1717 # Line 5 - SpliceComments makes this part of the previous block 1718 # Line 6 1719 1720 # Aligned with prev comment block 1721 """) # noqa 1722 self._Check(unformatted_code, expected_formatted_code) 1723 1724 def testBlockIndentedFuncSuffix(self): 1725 unformatted_code = textwrap.dedent("""\ 1726 if True: 1727 func(1) # Line 1 1728 func(2) # Line 2 1729 # Line 3 1730 func(3) # Line 4 1731 # Line 5 - SpliceComments makes this a new block 1732 # Line 6 1733 1734 # Aligned with Func 1735 1736 def Func(): 1737 pass 1738 """) # noqa 1739 expected_formatted_code = textwrap.dedent("""\ 1740 if True: 1741 func(1) # Line 1 1742 func(2) # Line 2 1743 # Line 3 1744 func(3) # Line 4 1745 1746 # Line 5 - SpliceComments makes this a new block 1747 # Line 6 1748 1749 # Aligned with Func 1750 1751 1752 def Func(): 1753 pass 1754 """) 1755 self._Check(unformatted_code, expected_formatted_code) 1756 1757 def testBlockIndentedCommentSuffix(self): 1758 unformatted_code = textwrap.dedent("""\ 1759 if True: 1760 func(1) # Line 1 1761 func(2) # Line 2 1762 # Line 3 1763 func(3) # Line 4 1764 # Line 5 1765 # Line 6 1766 1767 # Not aligned 1768 """) 1769 expected_formatted_code = textwrap.dedent("""\ 1770 if True: 1771 func(1) # Line 1 1772 func(2) # Line 2 1773 # Line 3 1774 func(3) # Line 4 1775 # Line 5 1776 # Line 6 1777 1778 # Not aligned 1779 """) 1780 self._Check(unformatted_code, expected_formatted_code) 1781 1782 def testBlockMultiIndented(self): 1783 unformatted_code = textwrap.dedent("""\ 1784 if True: 1785 if True: 1786 if True: 1787 func(1) # Line 1 1788 func(2) # Line 2 1789 # Line 3 1790 func(3) # Line 4 1791 # Line 5 1792 # Line 6 1793 1794 # Not aligned 1795 """) # noqa 1796 expected_formatted_code = textwrap.dedent("""\ 1797 if True: 1798 if True: 1799 if True: 1800 func(1) # Line 1 1801 func(2) # Line 2 1802 # Line 3 1803 func(3) # Line 4 1804 # Line 5 1805 # Line 6 1806 1807 # Not aligned 1808 """) 1809 self._Check(unformatted_code, expected_formatted_code) 1810 1811 def testArgs(self): 1812 unformatted_code = textwrap.dedent("""\ 1813 def MyFunc( 1814 arg1, # Desc 1 1815 arg2, # Desc 2 1816 a_longer_var_name, # Desc 3 1817 arg4, 1818 arg5, # Desc 5 1819 arg6, 1820 ): 1821 pass 1822 """) 1823 expected_formatted_code = textwrap.dedent("""\ 1824 def MyFunc( 1825 arg1, # Desc 1 1826 arg2, # Desc 2 1827 a_longer_var_name, # Desc 3 1828 arg4, 1829 arg5, # Desc 5 1830 arg6, 1831 ): 1832 pass 1833 """) 1834 self._Check(unformatted_code, expected_formatted_code) 1835 1836 def testDisableBlock(self): 1837 unformatted_code = textwrap.dedent("""\ 1838 a() # comment 1 1839 b() # comment 2 1840 1841 # yapf: disable 1842 c() # comment 3 1843 d() # comment 4 1844 # yapf: enable 1845 1846 e() # comment 5 1847 f() # comment 6 1848 """) 1849 expected_formatted_code = textwrap.dedent("""\ 1850 a() # comment 1 1851 b() # comment 2 1852 1853 # yapf: disable 1854 c() # comment 3 1855 d() # comment 4 1856 # yapf: enable 1857 1858 e() # comment 5 1859 f() # comment 6 1860 """) 1861 self._Check(unformatted_code, expected_formatted_code) 1862 1863 def testDisabledLine(self): 1864 unformatted_code = textwrap.dedent("""\ 1865 short # comment 1 1866 do_not_touch1 # yapf: disable 1867 do_not_touch2 # yapf: disable 1868 a_longer_statement # comment 2 1869 """) 1870 expected_formatted_code = textwrap.dedent("""\ 1871 short # comment 1 1872 do_not_touch1 # yapf: disable 1873 do_not_touch2 # yapf: disable 1874 a_longer_statement # comment 2 1875 """) 1876 self._Check(unformatted_code, expected_formatted_code) 1877 1878 1879class _SpacesAroundDictListTupleTestImpl(unittest.TestCase): 1880 1881 @staticmethod 1882 def _OwnStyle(): 1883 my_style = style.CreatePEP8Style() 1884 my_style['DISABLE_ENDING_COMMA_HEURISTIC'] = True 1885 my_style['SPLIT_ALL_COMMA_SEPARATED_VALUES'] = False 1886 my_style['SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED'] = False 1887 return my_style 1888 1889 def _Check(self, unformatted_code, expected_formatted_code): 1890 formatted_code, _ = yapf_api.FormatCode( 1891 unformatted_code, style_config=style.SetGlobalStyle(self._OwnStyle())) 1892 self.assertEqual(expected_formatted_code, formatted_code) 1893 1894 def setUp(self): 1895 self.maxDiff = None 1896 1897 1898class SpacesAroundDictTest(_SpacesAroundDictListTupleTestImpl): 1899 1900 @classmethod 1901 def _OwnStyle(cls): 1902 style = super(SpacesAroundDictTest, cls)._OwnStyle() 1903 style['SPACES_AROUND_DICT_DELIMITERS'] = True 1904 1905 return style 1906 1907 def testStandard(self): 1908 unformatted_code = textwrap.dedent("""\ 1909 {1 : 2} 1910 {k:v for k, v in other.items()} 1911 {k for k in [1, 2, 3]} 1912 1913 # The following statements should not change 1914 {} 1915 {1 : 2} # yapf: disable 1916 1917 # yapf: disable 1918 {1 : 2} 1919 # yapf: enable 1920 1921 # Dict settings should not impact lists or tuples 1922 [1, 2] 1923 (3, 4) 1924 """) 1925 expected_formatted_code = textwrap.dedent("""\ 1926 { 1: 2 } 1927 { k: v for k, v in other.items() } 1928 { k for k in [1, 2, 3] } 1929 1930 # The following statements should not change 1931 {} 1932 {1 : 2} # yapf: disable 1933 1934 # yapf: disable 1935 {1 : 2} 1936 # yapf: enable 1937 1938 # Dict settings should not impact lists or tuples 1939 [1, 2] 1940 (3, 4) 1941 """) 1942 1943 self._Check(unformatted_code, expected_formatted_code) 1944 1945 1946class SpacesAroundListTest(_SpacesAroundDictListTupleTestImpl): 1947 1948 @classmethod 1949 def _OwnStyle(cls): 1950 style = super(SpacesAroundListTest, cls)._OwnStyle() 1951 style['SPACES_AROUND_LIST_DELIMITERS'] = True 1952 1953 return style 1954 1955 def testStandard(self): 1956 unformatted_code = textwrap.dedent("""\ 1957 [a,b,c] 1958 [4,5,] 1959 [6, [7, 8], 9] 1960 [v for v in [1,2,3] if v & 1] 1961 1962 # The following statements should not change 1963 index[0] 1964 index[a, b] 1965 [] 1966 [v for v in [1,2,3] if v & 1] # yapf: disable 1967 1968 # yapf: disable 1969 [a,b,c] 1970 [4,5,] 1971 # yapf: enable 1972 1973 # List settings should not impact dicts or tuples 1974 {a: b} 1975 (1, 2) 1976 """) 1977 expected_formatted_code = textwrap.dedent("""\ 1978 [ a, b, c ] 1979 [ 4, 5, ] 1980 [ 6, [ 7, 8 ], 9 ] 1981 [ v for v in [ 1, 2, 3 ] if v & 1 ] 1982 1983 # The following statements should not change 1984 index[0] 1985 index[a, b] 1986 [] 1987 [v for v in [1,2,3] if v & 1] # yapf: disable 1988 1989 # yapf: disable 1990 [a,b,c] 1991 [4,5,] 1992 # yapf: enable 1993 1994 # List settings should not impact dicts or tuples 1995 {a: b} 1996 (1, 2) 1997 """) 1998 1999 self._Check(unformatted_code, expected_formatted_code) 2000 2001 2002class SpacesAroundTupleTest(_SpacesAroundDictListTupleTestImpl): 2003 2004 @classmethod 2005 def _OwnStyle(cls): 2006 style = super(SpacesAroundTupleTest, cls)._OwnStyle() 2007 style['SPACES_AROUND_TUPLE_DELIMITERS'] = True 2008 2009 return style 2010 2011 def testStandard(self): 2012 unformatted_code = textwrap.dedent("""\ 2013 (0, 1) 2014 (2, 3) 2015 (4, 5, 6,) 2016 func((7, 8), 9) 2017 2018 # The following statements should not change 2019 func(1, 2) 2020 (this_func or that_func)(3, 4) 2021 if (True and False): pass 2022 () 2023 2024 (0, 1) # yapf: disable 2025 2026 # yapf: disable 2027 (0, 1) 2028 (2, 3) 2029 # yapf: enable 2030 2031 # Tuple settings should not impact dicts or lists 2032 {a: b} 2033 [3, 4] 2034 """) 2035 expected_formatted_code = textwrap.dedent("""\ 2036 ( 0, 1 ) 2037 ( 2, 3 ) 2038 ( 4, 5, 6, ) 2039 func(( 7, 8 ), 9) 2040 2041 # The following statements should not change 2042 func(1, 2) 2043 (this_func or that_func)(3, 4) 2044 if (True and False): pass 2045 () 2046 2047 (0, 1) # yapf: disable 2048 2049 # yapf: disable 2050 (0, 1) 2051 (2, 3) 2052 # yapf: enable 2053 2054 # Tuple settings should not impact dicts or lists 2055 {a: b} 2056 [3, 4] 2057 """) 2058 2059 self._Check(unformatted_code, expected_formatted_code) 2060 2061 2062if __name__ == '__main__': 2063 unittest.main() 2064