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