gh-109118: Allow lambdas in annotation scopes in classes (#118019)
https://github.com/python/cpython/commit/85f727c5fb2afa60affa9ae3396ce4149cf... commit: 85f727c5fb2afa60affa9ae3396ce4149cf5215d branch: main author: Jelle Zijlstra <jelle.zijlstra@gmail.com> committer: JelleZijlstra <jelle.zijlstra@gmail.com> date: 2024-04-22T12:50:26-07:00 summary: gh-109118: Allow lambdas in annotation scopes in classes (#118019) files: A Misc/NEWS.d/next/Core and Builtins/2024-04-17-17-52-32.gh-issue-109118.q9iPEI.rst M Doc/whatsnew/3.13.rst M Lib/test/test_type_params.py M Python/symtable.c diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index c04dc924d1efa5..67d1956a19697e 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -241,6 +241,9 @@ Other Language Changes ones if configured to do so. (Contributed by Pedro Sousa Lacerda in :gh:`66449`.) +* :ref:`annotation scope <annotation-scopes>` within class scopes can now + contain lambdas. (Contributed by Jelle Zijlstra in :gh:`109118`.) + New Modules =========== diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py index 25ee188731f31f..fbb80d9aac9942 100644 --- a/Lib/test/test_type_params.py +++ b/Lib/test/test_type_params.py @@ -486,8 +486,6 @@ class C[T]: {} """ error_cases = [ - "type Alias1[T] = lambda: T", - "type Alias2 = lambda: T", "type Alias3[T] = (T for _ in (1,))", "type Alias4 = (T for _ in (1,))", "type Alias5[T] = [T for _ in (1,)]", @@ -499,6 +497,54 @@ class C[T]: r"Cannot use [a-z]+ in annotation scope within class scope"): run_code(code.format(case)) + def test_lambda_in_alias_in_class(self): + code = """ + T = "global" + class C: + T = "class" + type Alias = lambda: T + """ + C = run_code(code)["C"] + self.assertEqual(C.Alias.__value__(), "global") + + def test_lambda_in_alias_in_generic_class(self): + code = """ + class C[T]: + T = "class" + type Alias = lambda: T + """ + C = run_code(code)["C"] + self.assertIs(C.Alias.__value__(), C.__type_params__[0]) + + def test_lambda_in_generic_alias_in_class(self): + # A lambda nested in the alias cannot see the class scope, but can see + # a surrounding annotation scope. + code = """ + T = U = "global" + class C: + T = "class" + U = "class" + type Alias[T] = lambda: (T, U) + """ + C = run_code(code)["C"] + T, U = C.Alias.__value__() + self.assertIs(T, C.Alias.__type_params__[0]) + self.assertEqual(U, "global") + + def test_lambda_in_generic_alias_in_generic_class(self): + # A lambda nested in the alias cannot see the class scope, but can see + # a surrounding annotation scope. + code = """ + class C[T, U]: + T = "class" + U = "class" + type Alias[T] = lambda: (T, U) + """ + C = run_code(code)["C"] + T, U = C.Alias.__value__() + self.assertIs(T, C.Alias.__type_params__[0]) + self.assertIs(U, C.__type_params__[1]) + def make_base(arg): class Base: diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-17-17-52-32.gh-issue-109118.q9iPEI.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-17-17-52-32.gh-issue-109118.q9iPEI.rst new file mode 100644 index 00000000000000..124540045547b1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-17-17-52-32.gh-issue-109118.q9iPEI.rst @@ -0,0 +1,2 @@ +:ref:`annotation scope <annotation-scopes>` within class scopes can now +contain lambdas. diff --git a/Python/symtable.c b/Python/symtable.c index 36ccc0e73723d5..483ef1c3c46542 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -2140,17 +2140,6 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT(st, expr, e->v.UnaryOp.operand); break; case Lambda_kind: { - if (st->st_cur->ste_can_see_class_scope) { - // gh-109118 - PyErr_Format(PyExc_SyntaxError, - "Cannot use lambda in annotation scope within class scope"); - PyErr_RangedSyntaxLocationObject(st->st_filename, - e->lineno, - e->col_offset + 1, - e->end_lineno, - e->end_col_offset + 1); - VISIT_QUIT(st, 0); - } if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (e->v.Lambda.args->kw_defaults)
participants (1)
-
JelleZijlstra