Skip to content

Commit e4151e6

Browse files
committed
gh-130080: implement PEP 765
1 parent c357d69 commit e4151e6

File tree

5 files changed

+258
-47
lines changed

5 files changed

+258
-47
lines changed

Include/internal/pycore_compile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ extern int _PyCompile_AstOptimize(
3636
extern int _PyAST_Optimize(
3737
struct _mod *,
3838
struct _arena *arena,
39+
PyObject *filename,
3940
int optimize,
4041
int ff_features);
4142

Lib/test/test_except_star.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ def test_break_in_except_star(self):
8484
if i == 2:
8585
break
8686
finally:
87-
return 0
87+
pass
88+
return 0
8889
""")
8990

9091

@@ -117,7 +118,8 @@ def test_continue_in_except_star_block_invalid(self):
117118
if i == 2:
118119
continue
119120
finally:
120-
return 0
121+
pass
122+
return 0
121123
""")
122124

123125
def test_return_in_except_star_block_invalid(self):

Lib/test/test_syntax.py

Lines changed: 126 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@
846846
SyntaxError: 'function call' is an illegal expression for augmented assignment
847847
848848
849-
Test continue in finally in weird combinations.
849+
Test control flow in finally
850850
851851
continue in for loop under finally should be ok.
852852
@@ -860,51 +860,63 @@
860860
>>> test()
861861
9
862862
863-
continue in a finally should be ok.
863+
break in for loop under finally should be ok.
864864
865865
>>> 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)
872872
>>> test()
873-
9
873+
0
874+
875+
return in function under finally should be ok.
874876
875877
>>> 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())
885884
>>> test()
886-
9
885+
42
886+
887+
combine for loop and function def
888+
889+
return in function under finally should be ok.
887890
888891
>>> 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())
898899
>>> 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
900912
901913
A continue outside loop should not be allowed.
902914
903915
>>> def foo():
904916
... try:
905-
... pass
906-
... finally:
907917
... continue
918+
... finally:
919+
... pass
908920
Traceback (most recent call last):
909921
...
910922
SyntaxError: 'continue' not properly in loop
@@ -2381,15 +2393,96 @@ def f(x: *b)
23812393

23822394
from test import support
23832395

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):
23852478

23862479
def _check_error(self, code, errtext,
23872480
filename="<testcase>", mode="exec", subclass=None,
23882481
lineno=None, offset=None, end_lineno=None, end_offset=None):
23892482
"""Check that compiling code raises SyntaxError with errtext.
23902483
23912484
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
23932486
is the expected subclass of SyntaxError (e.g. IndentationError).
23942487
"""
23952488
try:

0 commit comments

Comments
 (0)