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