Skip to content

Commit 4895788

Browse files
[3.11] gh-105164: Detect annotations inside match blocks (GH-105177). (#105314)
(cherry picked from commit 69d1245)
1 parent aca77b5 commit 4895788

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

Lib/test/test_type_annotations.py

+111
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import textwrap
12
import unittest
23

34
class TypeAnnotationTests(unittest.TestCase):
@@ -101,3 +102,113 @@ class D(metaclass=C):
101102
with self.assertRaises(AttributeError):
102103
del D.__annotations__
103104
self.assertEqual(D.__annotations__, {})
105+
106+
107+
class TestSetupAnnotations(unittest.TestCase):
108+
def check(self, code: str):
109+
code = textwrap.dedent(code)
110+
for scope in ("module", "class"):
111+
with self.subTest(scope=scope):
112+
if scope == "class":
113+
code = f"class C:\n{textwrap.indent(code, ' ')}"
114+
ns = {}
115+
exec(code, ns)
116+
if scope == "class":
117+
annotations = ns["C"].__annotations__
118+
else:
119+
annotations = ns["__annotations__"]
120+
self.assertEqual(annotations, {"x": int})
121+
122+
def test_top_level(self):
123+
self.check("x: int = 1")
124+
125+
def test_blocks(self):
126+
self.check("if True:\n x: int = 1")
127+
self.check("""
128+
while True:
129+
x: int = 1
130+
break
131+
""")
132+
self.check("""
133+
while False:
134+
pass
135+
else:
136+
x: int = 1
137+
""")
138+
self.check("""
139+
for i in range(1):
140+
x: int = 1
141+
""")
142+
self.check("""
143+
for i in range(1):
144+
pass
145+
else:
146+
x: int = 1
147+
""")
148+
149+
def test_try(self):
150+
self.check("""
151+
try:
152+
x: int = 1
153+
except:
154+
pass
155+
""")
156+
self.check("""
157+
try:
158+
pass
159+
except:
160+
pass
161+
else:
162+
x: int = 1
163+
""")
164+
self.check("""
165+
try:
166+
pass
167+
except:
168+
pass
169+
finally:
170+
x: int = 1
171+
""")
172+
self.check("""
173+
try:
174+
1/0
175+
except:
176+
x: int = 1
177+
""")
178+
179+
def test_try_star(self):
180+
self.check("""
181+
try:
182+
x: int = 1
183+
except* Exception:
184+
pass
185+
""")
186+
self.check("""
187+
try:
188+
pass
189+
except* Exception:
190+
pass
191+
else:
192+
x: int = 1
193+
""")
194+
self.check("""
195+
try:
196+
pass
197+
except* Exception:
198+
pass
199+
finally:
200+
x: int = 1
201+
""")
202+
self.check("""
203+
try:
204+
1/0
205+
except* Exception:
206+
x: int = 1
207+
""")
208+
209+
def test_match(self):
210+
self.check("""
211+
match 0:
212+
case 0:
213+
x: int = 1
214+
""")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Ensure annotations are set up correctly if the only annotation in a block is
2+
within a :keyword:`match` block. Patch by Jelle Zijlstra.

Python/compile.c

+9
Original file line numberDiff line numberDiff line change
@@ -1905,6 +1905,15 @@ find_ann(asdl_stmt_seq *stmts)
19051905
find_ann(st->v.TryStar.finalbody) ||
19061906
find_ann(st->v.TryStar.orelse);
19071907
break;
1908+
case Match_kind:
1909+
for (j = 0; j < asdl_seq_LEN(st->v.Match.cases); j++) {
1910+
match_case_ty match_case = (match_case_ty)asdl_seq_GET(
1911+
st->v.Match.cases, j);
1912+
if (find_ann(match_case->body)) {
1913+
return true;
1914+
}
1915+
}
1916+
break;
19081917
default:
19091918
res = 0;
19101919
}

0 commit comments

Comments
 (0)