Skip to content

Commit c947ec7

Browse files
committed
used context manager to manage flag, updated unit tests
1 parent d9a613e commit c947ec7

File tree

3 files changed

+70
-63
lines changed

3 files changed

+70
-63
lines changed

mypy/semanal.py

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,8 @@ def __init__(
485485
self.current_overload_item: int | None = None
486486

487487
# Used to track whether currently inside an except* block. This helps
488-
# to invoke errors when continue/break/return is used inside except * block.
489-
self.is_in_except_block: bool = False
488+
# to invoke errors when continue/break/return is used inside except* block.
489+
self.inside_except_star_block: bool = False
490490

491491
# mypyc doesn't properly handle implementing an abstractproperty
492492
# with a regular attribute so we make them properties
@@ -515,6 +515,15 @@ def allow_unbound_tvars_set(self) -> Iterator[None]:
515515
finally:
516516
self.allow_unbound_tvars = old
517517

518+
@contextmanager
519+
def inside_except_star_block_set(self, value: bool) -> Iterator[None]:
520+
old = self.inside_except_star_block
521+
self.inside_except_star_block = value
522+
try:
523+
yield
524+
finally:
525+
self.inside_except_star_block = old
526+
518527
#
519528
# Preparing module (performed before semantic analysis)
520529
#
@@ -858,9 +867,6 @@ def file_context(
858867
def visit_func_def(self, defn: FuncDef) -> None:
859868
self.statement = defn
860869

861-
was_in_except_block: bool = self.is_in_except_block
862-
self.is_in_except_block = False
863-
864870
# Visit default values because they may contain assignment expressions.
865871
for arg in defn.arguments:
866872
if arg.initializer:
@@ -881,13 +887,11 @@ def visit_func_def(self, defn: FuncDef) -> None:
881887
self.add_function_to_symbol_table(defn)
882888

883889
if not self.recurse_into_functions:
884-
self.is_in_except_block = was_in_except_block
885890
return
886891

887892
with self.scope.function_scope(defn):
888-
self.analyze_func_def(defn)
889-
890-
self.is_in_except_block = was_in_except_block
893+
with self.inside_except_star_block_set(False):
894+
self.analyze_func_def(defn)
891895

892896
def function_fullname(self, fullname: str) -> str:
893897
if self.current_overload_item is None:
@@ -5273,7 +5277,7 @@ def visit_return_stmt(self, s: ReturnStmt) -> None:
52735277
self.statement = s
52745278
if not self.is_func_scope():
52755279
self.fail('"return" outside function', s)
5276-
if self.is_in_except_block:
5280+
if self.inside_except_star_block:
52775281
self.fail('"return" not allowed in except* block', s, serious=True, blocker=True)
52785282
if s.expr:
52795283
s.expr.accept(self)
@@ -5307,12 +5311,10 @@ def visit_operator_assignment_stmt(self, s: OperatorAssignmentStmt) -> None:
53075311
def visit_while_stmt(self, s: WhileStmt) -> None:
53085312
self.statement = s
53095313
s.expr.accept(self)
5310-
was_in_except_block: bool = self.is_in_except_block
5311-
self.is_in_except_block = False
53125314
self.loop_depth[-1] += 1
5313-
s.body.accept(self)
5315+
with self.inside_except_star_block_set(False):
5316+
s.body.accept(self)
53145317
self.loop_depth[-1] -= 1
5315-
self.is_in_except_block = was_in_except_block
53165318
self.visit_block_maybe(s.else_body)
53175319

53185320
def visit_for_stmt(self, s: ForStmt) -> None:
@@ -5334,27 +5336,24 @@ def visit_for_stmt(self, s: ForStmt) -> None:
53345336
self.store_declared_types(s.index, analyzed)
53355337
s.index_type = analyzed
53365338

5337-
was_in_except_block: bool = self.is_in_except_block
5338-
self.is_in_except_block = False
53395339
self.loop_depth[-1] += 1
5340-
self.visit_block(s.body)
5340+
with self.inside_except_star_block_set(False):
5341+
self.visit_block(s.body)
53415342
self.loop_depth[-1] -= 1
5342-
self.is_in_except_block = was_in_except_block
5343-
53445343
self.visit_block_maybe(s.else_body)
53455344

53465345
def visit_break_stmt(self, s: BreakStmt) -> None:
53475346
self.statement = s
53485347
if self.loop_depth[-1] == 0:
53495348
self.fail('"break" outside loop', s, serious=True, blocker=True)
5350-
if self.is_in_except_block:
5349+
if self.inside_except_star_block:
53515350
self.fail('"break" not allowed in except* block', s, serious=True, blocker=True)
53525351

53535352
def visit_continue_stmt(self, s: ContinueStmt) -> None:
53545353
self.statement = s
53555354
if self.loop_depth[-1] == 0:
53565355
self.fail('"continue" outside loop', s, serious=True, blocker=True)
5357-
if self.is_in_except_block:
5356+
if self.inside_except_star_block:
53585357
self.fail('"continue" not allowed in except* block', s, serious=True, blocker=True)
53595358

53605359
def visit_if_stmt(self, s: IfStmt) -> None:
@@ -5376,12 +5375,7 @@ def analyze_try_stmt(self, s: TryStmt, visitor: NodeVisitor[None]) -> None:
53765375
type.accept(visitor)
53775376
if var:
53785377
self.analyze_lvalue(var)
5379-
if s.is_star:
5380-
was_in_except_block: bool = self.is_in_except_block
5381-
self.is_in_except_block = True
5382-
handler.accept(visitor)
5383-
self.is_in_except_block = was_in_except_block
5384-
else:
5378+
with self.inside_except_star_block_set(s.is_star):
53855379
handler.accept(visitor)
53865380
if s.else_body:
53875381
s.else_body.accept(visitor)

test-data/unit/check-except-star.test

Lines changed: 0 additions & 36 deletions
This file was deleted.

test-data/unit/check-python311.test

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,52 @@ Alias4 = Callable[[*IntList], int] # E: "List[int]" cannot be unpacked (must be
173173
x4: Alias4[int] # E: Bad number of arguments for type alias, expected 0, given 1
174174
reveal_type(x4) # N: Revealed type is "def (*Any) -> builtins.int"
175175
[builtins fixtures/tuple.pyi]
176+
177+
[case testReturnInExceptStarBlock]
178+
# flags: --python-version 3.11
179+
def foo() -> None:
180+
try:
181+
pass
182+
except* Exception:
183+
return # E: "return" not allowed in except* block
184+
finally:
185+
return
186+
[builtins fixtures/exception.pyi]
187+
188+
[case testBreakContinueReturnInExceptStarBlock1]
189+
# flags: --python-version 3.11
190+
class range: pass
191+
def foo() -> None:
192+
for _ in range(5):
193+
try:
194+
pass
195+
except* Exception:
196+
continue # E: "continue" not allowed in except* block
197+
except* Exception:
198+
for _ in range(2):
199+
continue
200+
break # E: "break" not allowed in except* block
201+
except* Exception:
202+
return # E: "return" not allowed in except* block
203+
[builtins fixtures/exception.pyi]
204+
205+
[case testBreakContinueReturnInExceptStarBlock2]
206+
# flags: --python-version 3.11
207+
def foo():
208+
while True:
209+
try:
210+
pass
211+
except* Exception:
212+
def inner():
213+
while True:
214+
if 1 < 1:
215+
continue
216+
else:
217+
break
218+
return
219+
if 1 < 2:
220+
break # E: "break" not allowed in except* block
221+
if 1 < 2:
222+
continue # E: "continue" not allowed in except* block
223+
return # E: "return" not allowed in except* block
224+
[builtins fixtures/exception.pyi]

0 commit comments

Comments
 (0)