|  | 
| 846 | 846 | SyntaxError: 'function call' is an illegal expression for augmented assignment | 
| 847 | 847 | 
 | 
| 848 | 848 | 
 | 
| 849 |  | -Test continue in finally in weird combinations. | 
|  | 849 | +Test control flow in finally | 
| 850 | 850 | 
 | 
| 851 | 851 | continue in for loop under finally should be ok. | 
| 852 | 852 | 
 | 
|  | 
| 860 | 860 |     >>> test() | 
| 861 | 861 |     9 | 
| 862 | 862 | 
 | 
| 863 |  | -continue in a finally should be ok. | 
|  | 863 | +break in for loop under finally should be ok. | 
| 864 | 864 | 
 | 
| 865 | 865 |     >>> def test(): | 
| 866 |  | -    ...    for abc in range(10): | 
| 867 |  | -    ...        try: | 
| 868 |  | -    ...            pass | 
| 869 |  | -    ...        finally: | 
| 870 |  | -    ...            continue | 
| 871 |  | -    ...    print(abc) | 
|  | 866 | +    ...     try: | 
|  | 867 | +    ...         pass | 
|  | 868 | +    ...     finally: | 
|  | 869 | +    ...         for abc in range(10): | 
|  | 870 | +    ...             break | 
|  | 871 | +    ...     print(abc) | 
| 872 | 872 |     >>> test() | 
| 873 |  | -    9 | 
|  | 873 | +    0 | 
|  | 874 | +
 | 
|  | 875 | +return in function under finally should be ok. | 
| 874 | 876 | 
 | 
| 875 | 877 |     >>> def test(): | 
| 876 |  | -    ...    for abc in range(10): | 
| 877 |  | -    ...        try: | 
| 878 |  | -    ...            pass | 
| 879 |  | -    ...        finally: | 
| 880 |  | -    ...            try: | 
| 881 |  | -    ...                continue | 
| 882 |  | -    ...            except: | 
| 883 |  | -    ...                pass | 
| 884 |  | -    ...    print(abc) | 
|  | 878 | +    ...     try: | 
|  | 879 | +    ...         pass | 
|  | 880 | +    ...     finally: | 
|  | 881 | +    ...         def f(): | 
|  | 882 | +    ...             return 42 | 
|  | 883 | +    ...     print(f()) | 
| 885 | 884 |     >>> test() | 
| 886 |  | -    9 | 
|  | 885 | +    42 | 
|  | 886 | +
 | 
|  | 887 | +combine for loop and function def | 
|  | 888 | +
 | 
|  | 889 | +return in function under finally should be ok. | 
| 887 | 890 | 
 | 
| 888 | 891 |     >>> def test(): | 
| 889 |  | -    ...    for abc in range(10): | 
| 890 |  | -    ...        try: | 
| 891 |  | -    ...            pass | 
| 892 |  | -    ...        finally: | 
| 893 |  | -    ...            try: | 
| 894 |  | -    ...                pass | 
| 895 |  | -    ...            except: | 
| 896 |  | -    ...                continue | 
| 897 |  | -    ...    print(abc) | 
|  | 892 | +    ...     try: | 
|  | 893 | +    ...         pass | 
|  | 894 | +    ...     finally: | 
|  | 895 | +    ...         for i in range(10): | 
|  | 896 | +    ...             def f(): | 
|  | 897 | +    ...                 return 42 | 
|  | 898 | +    ...     print(f()) | 
| 898 | 899 |     >>> test() | 
| 899 |  | -    9 | 
|  | 900 | +    42 | 
|  | 901 | +
 | 
|  | 902 | +    >>> def test(): | 
|  | 903 | +    ...     try: | 
|  | 904 | +    ...         pass | 
|  | 905 | +    ...     finally: | 
|  | 906 | +    ...         def f(): | 
|  | 907 | +    ...             for i in range(10): | 
|  | 908 | +    ...                 return 42 | 
|  | 909 | +    ...     print(f()) | 
|  | 910 | +    >>> test() | 
|  | 911 | +    42 | 
| 900 | 912 | 
 | 
| 901 | 913 | A continue outside loop should not be allowed. | 
| 902 | 914 | 
 | 
| 903 | 915 |     >>> def foo(): | 
| 904 | 916 |     ...     try: | 
| 905 |  | -    ...         pass | 
| 906 |  | -    ...     finally: | 
| 907 | 917 |     ...         continue | 
|  | 918 | +    ...     finally: | 
|  | 919 | +    ...         pass | 
| 908 | 920 |     Traceback (most recent call last): | 
| 909 | 921 |       ... | 
| 910 | 922 |     SyntaxError: 'continue' not properly in loop | 
| @@ -2381,15 +2393,96 @@ def f(x: *b) | 
| 2381 | 2393 | 
 | 
| 2382 | 2394 | from test import support | 
| 2383 | 2395 | 
 | 
| 2384 |  | -class SyntaxTestCase(unittest.TestCase): | 
|  | 2396 | +class SyntaxWarningTest(unittest.TestCase): | 
|  | 2397 | +    def check_warning(self, code, errtext, filename="<testcase>", mode="exec"): | 
|  | 2398 | +        """Check that compiling code raises SyntaxWarning with errtext. | 
|  | 2399 | +
 | 
|  | 2400 | +        errtest is a regular expression that must be present in the | 
|  | 2401 | +        text of the warning raised. | 
|  | 2402 | +        """ | 
|  | 2403 | +        with self.assertWarnsRegex(SyntaxWarning, errtext): | 
|  | 2404 | +            compile(code, filename, mode) | 
|  | 2405 | + | 
|  | 2406 | +    def test_return_in_finally(self): | 
|  | 2407 | +        source = textwrap.dedent(""" | 
|  | 2408 | +            def f(): | 
|  | 2409 | +                try: | 
|  | 2410 | +                    pass | 
|  | 2411 | +                finally: | 
|  | 2412 | +                    return 42 | 
|  | 2413 | +            """) | 
|  | 2414 | +        self.check_warning(source, "'return' in a 'finally' block") | 
|  | 2415 | + | 
|  | 2416 | +        source = textwrap.dedent(""" | 
|  | 2417 | +            def f(): | 
|  | 2418 | +                try: | 
|  | 2419 | +                    pass | 
|  | 2420 | +                finally: | 
|  | 2421 | +                    try: | 
|  | 2422 | +                        return 42 | 
|  | 2423 | +                    except: | 
|  | 2424 | +                        pass | 
|  | 2425 | +            """) | 
|  | 2426 | +        self.check_warning(source, "'return' in a 'finally' block") | 
|  | 2427 | + | 
|  | 2428 | +        source = textwrap.dedent(""" | 
|  | 2429 | +            def f(): | 
|  | 2430 | +                try: | 
|  | 2431 | +                    pass | 
|  | 2432 | +                finally: | 
|  | 2433 | +                    try: | 
|  | 2434 | +                        pass | 
|  | 2435 | +                    except: | 
|  | 2436 | +                        return 42 | 
|  | 2437 | +            """) | 
|  | 2438 | +        self.check_warning(source, "'return' in a 'finally' block") | 
|  | 2439 | + | 
|  | 2440 | +    def test_break_and_continue_in_finally(self): | 
|  | 2441 | +        for kw in ('break', 'continue'): | 
|  | 2442 | + | 
|  | 2443 | +            source = textwrap.dedent(f""" | 
|  | 2444 | +                for abc in range(10): | 
|  | 2445 | +                    try: | 
|  | 2446 | +                        pass | 
|  | 2447 | +                    finally: | 
|  | 2448 | +                        {kw} | 
|  | 2449 | +                """) | 
|  | 2450 | +            self.check_warning(source, f"'{kw}' in a 'finally' block") | 
|  | 2451 | + | 
|  | 2452 | +            source = textwrap.dedent(f""" | 
|  | 2453 | +                for abc in range(10): | 
|  | 2454 | +                    try: | 
|  | 2455 | +                        pass | 
|  | 2456 | +                    finally: | 
|  | 2457 | +                        try: | 
|  | 2458 | +                            {kw} | 
|  | 2459 | +                        except: | 
|  | 2460 | +                            pass | 
|  | 2461 | +                """) | 
|  | 2462 | +            self.check_warning(source, f"'{kw}' in a 'finally' block") | 
|  | 2463 | + | 
|  | 2464 | +            source = textwrap.dedent(f""" | 
|  | 2465 | +                for abc in range(10): | 
|  | 2466 | +                    try: | 
|  | 2467 | +                        pass | 
|  | 2468 | +                    finally: | 
|  | 2469 | +                        try: | 
|  | 2470 | +                            pass | 
|  | 2471 | +                        except: | 
|  | 2472 | +                            {kw} | 
|  | 2473 | +                """) | 
|  | 2474 | +            self.check_warning(source, f"'{kw}' in a 'finally' block") | 
|  | 2475 | + | 
|  | 2476 | + | 
|  | 2477 | +class SyntaxErrorTestCase(unittest.TestCase): | 
| 2385 | 2478 | 
 | 
| 2386 | 2479 |     def _check_error(self, code, errtext, | 
| 2387 | 2480 |                      filename="<testcase>", mode="exec", subclass=None, | 
| 2388 | 2481 |                      lineno=None, offset=None, end_lineno=None, end_offset=None): | 
| 2389 | 2482 |         """Check that compiling code raises SyntaxError with errtext. | 
| 2390 | 2483 | 
 | 
| 2391 | 2484 |         errtest is a regular expression that must be present in the | 
| 2392 |  | -        test of the exception raised.  If subclass is specified it | 
|  | 2485 | +        text of the exception raised.  If subclass is specified it | 
| 2393 | 2486 |         is the expected subclass of SyntaxError (e.g. IndentationError). | 
| 2394 | 2487 |         """ | 
| 2395 | 2488 |         try: | 
|  | 
0 commit comments