Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2326d6c

Browse files
gh-109118: Make comprehensions work within annotation scopes, but without inlining (#118160)
Co-authored-by: Carl Meyer <carl@oddbird.net>
1 parent51aefc5 commit2326d6c

File tree

4 files changed

+39
-34
lines changed

4 files changed

+39
-34
lines changed

‎Doc/whatsnew/3.13.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,9 @@ Other Language Changes
276276
(Contributed by Pedro Sousa Lacerda in:gh:`66449`.)
277277

278278
*:ref:`annotation scope<annotation-scopes>` within class scopes can now
279-
contain lambdas. (Contributed by Jelle Zijlstra in:gh:`109118`.)
279+
contain lambdas and comprehensions. Comprehensions that are located within
280+
class scopes are not inlined into their parent scope. (Contributed by
281+
Jelle Zijlstra in:gh:`109118` and:gh:`118160`.)
280282

281283

282284
New Modules

‎Lib/test/test_type_params.py

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,11 @@ class C[T]:
436436
class Inner[U](make_base(T for _ in (1,)), make_base(T)):
437437
pass
438438
"""
439-
withself.assertRaisesRegex(SyntaxError,
440-
"Cannot use comprehension in annotation scope within class scope"):
441-
run_code(code)
439+
ns=run_code(code)
440+
inner=ns["C"].Inner
441+
base1,base2,_=inner.__bases__
442+
self.assertEqual(list(base1.__arg__), [ns["C"].__type_params__[0]])
443+
self.assertEqual(base2.__arg__,"class")
442444

443445
deftest_listcomp_in_nested_class(self):
444446
code="""
@@ -464,9 +466,11 @@ class C[T]:
464466
class Inner[U](make_base([T for _ in (1,)]), make_base(T)):
465467
pass
466468
"""
467-
withself.assertRaisesRegex(SyntaxError,
468-
"Cannot use comprehension in annotation scope within class scope"):
469-
run_code(code)
469+
ns=run_code(code)
470+
inner=ns["C"].Inner
471+
base1,base2,_=inner.__bases__
472+
self.assertEqual(base1.__arg__, [ns["C"].__type_params__[0]])
473+
self.assertEqual(base2.__arg__,"class")
470474

471475
deftest_gen_exp_in_generic_method(self):
472476
code="""
@@ -475,27 +479,33 @@ class C[T]:
475479
def meth[U](x: (T for _ in (1,)), y: T):
476480
pass
477481
"""
478-
withself.assertRaisesRegex(SyntaxError,
479-
"Cannot use comprehension in annotation scope within class scope"):
480-
run_code(code)
482+
ns=run_code(code)
483+
meth=ns["C"].meth
484+
self.assertEqual(list(meth.__annotations__["x"]), [ns["C"].__type_params__[0]])
485+
self.assertEqual(meth.__annotations__["y"],"class")
481486

482487
deftest_nested_scope_in_generic_alias(self):
483488
code="""
484-
class C[T]:
489+
T = "global"
490+
class C:
485491
T = "class"
486492
{}
487493
"""
488-
error_cases= [
489-
"typeAlias3[T] = (T for _ in (1,))",
490-
"typeAlias4 = (T for _ in (1,))",
491-
"typeAlias5[T] = [T for _ in (1,)]",
492-
"typeAlias6 = [T for _ in (1,)]",
494+
cases= [
495+
"typeAlias[T] = (T for _ in (1,))",
496+
"typeAlias = (T for _ in (1,))",
497+
"typeAlias[T] = [T for _ in (1,)]",
498+
"typeAlias = [T for _ in (1,)]",
493499
]
494-
forcaseinerror_cases:
500+
forcaseincases:
495501
withself.subTest(case=case):
496-
withself.assertRaisesRegex(SyntaxError,
497-
r"Cannot use [a-z]+ in annotation scope within class scope"):
498-
run_code(code.format(case))
502+
ns=run_code(code.format(case))
503+
alias=ns["C"].Alias
504+
value=list(alias.__value__)[0]
505+
ifalias.__type_params__:
506+
self.assertIs(value,alias.__type_params__[0])
507+
else:
508+
self.assertEqual(value,"global")
499509

500510
deftest_lambda_in_alias_in_class(self):
501511
code="""
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:ref:`Annotation scopes<annotation-scopes>` within classes can now contain
2+
comprehensions. However, such comprehensions are not inlined into their
3+
parent scope at runtime. Patch by Jelle Zijlstra.

‎Python/symtable.c

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,10 +1154,12 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
11541154
}
11551155
}
11561156

1157-
// we inline all non-generator-expression comprehensions
1157+
// we inline all non-generator-expression comprehensions,
1158+
// except those in annotation scopes that are nested in classes
11581159
intinline_comp=
11591160
entry->ste_comprehension&&
1160-
!entry->ste_generator;
1161+
!entry->ste_generator&&
1162+
!ste->ste_can_see_class_scope;
11611163

11621164
if (!analyze_child_block(entry,newbound,newfree,newglobal,
11631165
type_params,new_class_entry,&child_free))
@@ -2589,18 +2591,6 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e,
25892591
identifierscope_name,asdl_comprehension_seq*generators,
25902592
expr_tyelt,expr_tyvalue)
25912593
{
2592-
if (st->st_cur->ste_can_see_class_scope) {
2593-
// gh-109118
2594-
PyErr_Format(PyExc_SyntaxError,
2595-
"Cannot use comprehension in annotation scope within class scope");
2596-
PyErr_RangedSyntaxLocationObject(st->st_filename,
2597-
e->lineno,
2598-
e->col_offset+1,
2599-
e->end_lineno,
2600-
e->end_col_offset+1);
2601-
VISIT_QUIT(st,0);
2602-
}
2603-
26042594
intis_generator= (e->kind==GeneratorExp_kind);
26052595
comprehension_tyoutermost= ((comprehension_ty)
26062596
asdl_seq_GET(generators,0));

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp