aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelle Zijlstra <jelle.zijlstra@gmail.com>2023-06-05 06:46:12 -0700
committerGitHub <noreply@github.com>2023-06-05 13:46:12 +0000
commit48957888d28b0f2b4ae0bf19ffce6bc1e10b94f4 (patch)
tree797d64466e032f5ce040285462beb93cf462aae1
parentaca77b5530c34fb2ada0fe02fb83f4c9fa9256f3 (diff)
downloadcpython3-48957888d28b0f2b4ae0bf19ffce6bc1e10b94f4.tar.gz
[3.11] gh-105164: Detect annotations inside match blocks (GH-105177). (#105314)
(cherry picked from commit 69d1245685cf95ddc678633e978a56673da64865)
-rw-r--r--Lib/test/test_type_annotations.py111
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-05-31-19-35-22.gh-issue-105164.6Wajph.rst2
-rw-r--r--Python/compile.c9
3 files changed, 122 insertions, 0 deletions
diff --git a/Lib/test/test_type_annotations.py b/Lib/test/test_type_annotations.py
index 87f46c2ce8..bf39fdfa95 100644
--- a/Lib/test/test_type_annotations.py
+++ b/Lib/test/test_type_annotations.py
@@ -1,3 +1,4 @@
+import textwrap
import unittest
class TypeAnnotationTests(unittest.TestCase):
@@ -101,3 +102,113 @@ class TypeAnnotationTests(unittest.TestCase):
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
+ """)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-31-19-35-22.gh-issue-105164.6Wajph.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-31-19-35-22.gh-issue-105164.6Wajph.rst
new file mode 100644
index 0000000000..7d3486c3b6
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-05-31-19-35-22.gh-issue-105164.6Wajph.rst
@@ -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.
diff --git a/Python/compile.c b/Python/compile.c
index 1c712fba31..5f26da8608 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -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;
}