Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fe2bbb1

Browse filesBrowse files
bpo-32489: Allow 'continue' in 'finally' clause. (GH-5822)
1 parent 134cb01 commit fe2bbb1
Copy full SHA for fe2bbb1

File tree

Expand file treeCollapse file tree

10 files changed

+97
-70
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

10 files changed

+97
-70
lines changed
Open diff view settings
Collapse file

‎Doc/library/dis.rst‎

Copy file name to clipboardExpand all lines: Doc/library/dis.rst
+2-2Lines changed: 2 additions & 2 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -698,8 +698,8 @@ iterations of the loop.
698698
removed from the block stack.
699699

700700
It is similar to :opcode:`END_FINALLY`, but doesn't change the bytecode
701-
counter nor raise an exception. Used for implementing :keyword:`break`
702-
and :keyword:`return` in the :keyword:`finally` block.
701+
counter nor raise an exception. Used for implementing :keyword:`break`,
702+
:keyword:`continue` and :keyword:`return` in the :keyword:`finally` block.
703703

704704
.. versionadded:: 3.8
705705

Collapse file

‎Doc/reference/compound_stmts.rst‎

Copy file name to clipboardExpand all lines: Doc/reference/compound_stmts.rst
+7-6Lines changed: 7 additions & 6 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,8 @@ not handled, the exception is temporarily saved. The :keyword:`finally` clause
321321
is executed. If there is a saved exception it is re-raised at the end of the
322322
:keyword:`finally` clause. If the :keyword:`finally` clause raises another
323323
exception, the saved exception is set as the context of the new exception.
324-
If the :keyword:`finally` clause executes a :keyword:`return` or :keyword:`break`
325-
statement, the saved exception is discarded::
324+
If the :keyword:`finally` clause executes a :keyword:`return`, :keyword:`break`
325+
or :keyword:`continue` statement, the saved exception is discarded::
326326

327327
>>> def f():
328328
... try:
@@ -343,10 +343,7 @@ the :keyword:`finally` clause.
343343

344344
When a :keyword:`return`, :keyword:`break` or :keyword:`continue` statement is
345345
executed in the :keyword:`try` suite of a :keyword:`try`...\ :keyword:`finally`
346-
statement, the :keyword:`finally` clause is also executed 'on the way out.' A
347-
:keyword:`continue` statement is illegal in the :keyword:`finally` clause. (The
348-
reason is a problem with the current implementation --- this restriction may be
349-
lifted in the future).
346+
statement, the :keyword:`finally` clause is also executed 'on the way out.'
350347

351348
The return value of a function is determined by the last :keyword:`return`
352349
statement executed. Since the :keyword:`finally` clause always executes, a
@@ -366,6 +363,10 @@ Additional information on exceptions can be found in section :ref:`exceptions`,
366363
and information on using the :keyword:`raise` statement to generate exceptions
367364
may be found in section :ref:`raise`.
368365

366+
.. versionchanged:: 3.8
367+
Prior to Python 3.8, a :keyword:`continue` statement was illegal in the
368+
:keyword:`finally` clause due to a problem with the implementation.
369+
369370

370371
.. _with:
371372
.. _as:
Collapse file

‎Doc/reference/simple_stmts.rst‎

Copy file name to clipboardExpand all lines: Doc/reference/simple_stmts.rst
+2-3Lines changed: 2 additions & 3 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -686,9 +686,8 @@ The :keyword:`continue` statement
686686
continue_stmt: "continue"
687687

688688
:keyword:`continue` may only occur syntactically nested in a :keyword:`for` or
689-
:keyword:`while` loop, but not nested in a function or class definition or
690-
:keyword:`finally` clause within that loop. It continues with the next
691-
cycle of the nearest enclosing loop.
689+
:keyword:`while` loop, but not nested in a function or class definition within
690+
that loop. It continues with the next cycle of the nearest enclosing loop.
692691

693692
When :keyword:`continue` passes control out of a :keyword:`try` statement with a
694693
:keyword:`finally` clause, that :keyword:`finally` clause is executed before
Collapse file

‎Doc/whatsnew/3.8.rst‎

Copy file name to clipboardExpand all lines: Doc/whatsnew/3.8.rst
+5Lines changed: 5 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ New Features
7272
Other Language Changes
7373
======================
7474

75+
* A :keyword:`continue` statement was illegal in the :keyword:`finally` clause
76+
due to a problem with the implementation. In Python 3.8 this restriction
77+
was lifted.
78+
(Contributed by Serhiy Storchaka in :issue:`32489`.)
79+
7580
* Added support of ``\N{name}`` escapes in :mod:`regular expressions <re>`.
7681
(Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.)
7782

Collapse file

‎Lib/test/test_compile.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_compile.py
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,14 +856,16 @@ def test_for_break_continue_inside_try_finally_block(self):
856856
"""
857857
self.check_stack_size(snippet)
858858

859-
def test_for_break_inside_finally_block(self):
859+
def test_for_break_continue_inside_finally_block(self):
860860
snippet = """
861861
for x in y:
862862
try:
863863
t
864864
finally:
865865
if z:
866866
break
867+
elif u:
868+
continue
867869
else:
868870
a
869871
else:
Collapse file

‎Lib/test/test_exceptions.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_exceptions.py
-9Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,6 @@ def ckmsg(src, msg):
138138
else:
139139
self.fail("failed to get expected SyntaxError")
140140

141-
s = '''while 1:
142-
try:
143-
pass
144-
finally:
145-
continue'''
146-
147-
if not sys.platform.startswith('java'):
148-
ckmsg(s, "'continue' not supported inside 'finally' clause")
149-
150141
s = '''if 1:
151142
try:
152143
continue
Collapse file

‎Lib/test/test_grammar.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_grammar.py
+53Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,59 @@ def test_break_in_finally(self):
859859
break
860860
self.assertEqual(count, 0)
861861

862+
def test_continue_in_finally(self):
863+
count = 0
864+
while count < 2:
865+
count += 1
866+
try:
867+
pass
868+
finally:
869+
continue
870+
break
871+
self.assertEqual(count, 2)
872+
873+
count = 0
874+
while count < 2:
875+
count += 1
876+
try:
877+
break
878+
finally:
879+
continue
880+
self.assertEqual(count, 2)
881+
882+
count = 0
883+
while count < 2:
884+
count += 1
885+
try:
886+
1/0
887+
finally:
888+
continue
889+
break
890+
self.assertEqual(count, 2)
891+
892+
for count in [0, 1]:
893+
try:
894+
pass
895+
finally:
896+
continue
897+
break
898+
self.assertEqual(count, 1)
899+
900+
for count in [0, 1]:
901+
try:
902+
break
903+
finally:
904+
continue
905+
self.assertEqual(count, 1)
906+
907+
for count in [0, 1]:
908+
try:
909+
1/0
910+
finally:
911+
continue
912+
break
913+
self.assertEqual(count, 1)
914+
862915
def test_return_in_finally(self):
863916
def g1():
864917
try:
Collapse file

‎Lib/test/test_syntax.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_syntax.py
+23-45Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -298,19 +298,17 @@
298298
>>> test()
299299
9
300300
301-
Start simple, a continue in a finally should not be allowed.
301+
continue in a finally should be ok.
302302
303303
>>> def test():
304304
... for abc in range(10):
305305
... try:
306306
... pass
307307
... finally:
308308
... continue
309-
Traceback (most recent call last):
310-
...
311-
SyntaxError: 'continue' not supported inside 'finally' clause
312-
313-
This is essentially a continue in a finally which should not be allowed.
309+
... print(abc)
310+
>>> test()
311+
9
314312
315313
>>> def test():
316314
... for abc in range(10):
@@ -321,9 +319,24 @@
321319
... continue
322320
... except:
323321
... pass
324-
Traceback (most recent call last):
325-
...
326-
SyntaxError: 'continue' not supported inside 'finally' clause
322+
... print(abc)
323+
>>> test()
324+
9
325+
326+
>>> def test():
327+
... for abc in range(10):
328+
... try:
329+
... pass
330+
... finally:
331+
... try:
332+
... pass
333+
... except:
334+
... continue
335+
... print(abc)
336+
>>> test()
337+
9
338+
339+
A continue outside loop should not be allowed.
327340
328341
>>> def foo():
329342
... try:
@@ -332,42 +345,7 @@
332345
... continue
333346
Traceback (most recent call last):
334347
...
335-
SyntaxError: 'continue' not supported inside 'finally' clause
336-
337-
>>> def foo():
338-
... for a in ():
339-
... try:
340-
... pass
341-
... finally:
342-
... continue
343-
Traceback (most recent call last):
344-
...
345-
SyntaxError: 'continue' not supported inside 'finally' clause
346-
347-
>>> def foo():
348-
... for a in ():
349-
... try:
350-
... pass
351-
... finally:
352-
... try:
353-
... continue
354-
... finally:
355-
... pass
356-
Traceback (most recent call last):
357-
...
358-
SyntaxError: 'continue' not supported inside 'finally' clause
359-
360-
>>> def foo():
361-
... for a in ():
362-
... try: pass
363-
... finally:
364-
... try:
365-
... pass
366-
... except:
367-
... continue
368-
Traceback (most recent call last):
369-
...
370-
SyntaxError: 'continue' not supported inside 'finally' clause
348+
SyntaxError: 'continue' not properly in loop
371349
372350
There is one test for a break that is not in a loop. The compiler
373351
uses a single data structure to keep track of try-finally and loops,
Collapse file
+2Lines changed: 2 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
A :keyword:`continue` statement is now allowed in the :keyword:`finally`
2+
clause.
Collapse file

‎Python/compile.c‎

Copy file name to clipboardExpand all lines: Python/compile.c
-4Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2625,10 +2625,6 @@ compiler_continue(struct compiler *c)
26252625
ADDOP_JABS(c, JUMP_ABSOLUTE, info->fb_block);
26262626
return 1;
26272627
}
2628-
if (info->fb_type == FINALLY_END) {
2629-
return compiler_error(c,
2630-
"'continue' not supported inside 'finally' clause");
2631-
}
26322628
if (!compiler_unwind_fblock(c, info, 0))
26332629
return 0;
26342630
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.