Skip to content

Commit

Permalink
[3.11] pythongh-105164: Detect annotations inside match blocks (pytho…
Browse files Browse the repository at this point in the history
…nGH-105177).

(cherry picked from commit 69d1245)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
  • Loading branch information
JelleZijlstra committed Jun 5, 2023
1 parent aca77b5 commit 9c30ecb
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
111 changes: 111 additions & 0 deletions Lib/test/test_type_annotations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import textwrap
import unittest

class TypeAnnotationTests(unittest.TestCase):
Expand Down Expand Up @@ -101,3 +102,113 @@ class D(metaclass=C):
with self.assertRaises(AttributeError):
del D.__annotations__
self.assertEqual(D.__annotations__, {})


class TestSetupAnnotations(unittest.TestCase):
def check(self, code: str):
code = textwrap.dedent(code)
for scope in ("module", "class"):
with self.subTest(scope=scope):
if scope == "class":
code = f"class C:\n{textwrap.indent(code, ' ')}"
ns = {}
exec(code, ns)
if scope == "class":
annotations = ns["C"].__annotations__
else:
annotations = ns["__annotations__"]
self.assertEqual(annotations, {"x": int})

def test_top_level(self):
self.check("x: int = 1")

def test_blocks(self):
self.check("if True:\n x: int = 1")
self.check("""
while True:
x: int = 1
break
""")
self.check("""
while False:
pass
else:
x: int = 1
""")
self.check("""
for i in range(1):
x: int = 1
""")
self.check("""
for i in range(1):
pass
else:
x: int = 1
""")

def test_try(self):
self.check("""
try:
x: int = 1
except:
pass
""")
self.check("""
try:
pass
except:
pass
else:
x: int = 1
""")
self.check("""
try:
pass
except:
pass
finally:
x: int = 1
""")
self.check("""
try:
1/0
except:
x: int = 1
""")

def test_try_star(self):
self.check("""
try:
x: int = 1
except* Exception:
pass
""")
self.check("""
try:
pass
except* Exception:
pass
else:
x: int = 1
""")
self.check("""
try:
pass
except* Exception:
pass
finally:
x: int = 1
""")
self.check("""
try:
1/0
except* Exception:
x: int = 1
""")

def test_match(self):
self.check("""
match 0:
case 0:
x: int = 1
""")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Ensure annotations are set up correctly if the only annotation in a block is
within a :keyword:`match` block. Patch by Jelle Zijlstra.
9 changes: 9 additions & 0 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1905,6 +1905,15 @@ find_ann(asdl_stmt_seq *stmts)
find_ann(st->v.TryStar.finalbody) ||
find_ann(st->v.TryStar.orelse);
break;
case Match_kind:
for (j = 0; j < asdl_seq_LEN(st->v.Match.cases); j++) {
match_case_ty match_case = (match_case_ty)asdl_seq_GET(
st->v.Match.cases, j);
if (find_ann(match_case->body)) {
return true;
}
}
break;
default:
res = 0;
}
Expand Down

0 comments on commit 9c30ecb

Please sign in to comment.