xref: /aosp_15_r20/external/yapf/yapftests/yapf_test.py (revision 7249d1a64f4850ccf838e62a46276f891f72998e)
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