class Inner[U](make_base(T for _ in (1,)), make_base(T)):
pass
"""
- with self.assertRaisesRegex(SyntaxError,
- "Cannot use comprehension in annotation scope within class scope"):
- run_code(code)
+ ns = run_code(code)
+ inner = ns["C"].Inner
+ base1, base2, _ = inner.__bases__
+ self.assertEqual(list(base1.__arg__), [ns["C"].__type_params__[0]])
+ self.assertEqual(base2.__arg__, "class")
def test_listcomp_in_nested_class(self):
code = """
class Inner[U](make_base([T for _ in (1,)]), make_base(T)):
pass
"""
- with self.assertRaisesRegex(SyntaxError,
- "Cannot use comprehension in annotation scope within class scope"):
- run_code(code)
+ ns = run_code(code)
+ inner = ns["C"].Inner
+ base1, base2, _ = inner.__bases__
+ self.assertEqual(base1.__arg__, [ns["C"].__type_params__[0]])
+ self.assertEqual(base2.__arg__, "class")
def test_gen_exp_in_generic_method(self):
code = """
def meth[U](x: (T for _ in (1,)), y: T):
pass
"""
- with self.assertRaisesRegex(SyntaxError,
- "Cannot use comprehension in annotation scope within class scope"):
- run_code(code)
+ ns = run_code(code)
+ meth = ns["C"].meth
+ self.assertEqual(list(meth.__annotations__["x"]), [ns["C"].__type_params__[0]])
+ self.assertEqual(meth.__annotations__["y"], "class")
def test_nested_scope_in_generic_alias(self):
code = """
- class C[T]:
+ T = "global"
+ class C:
T = "class"
{}
"""
- error_cases = [
- "type Alias3[T] = (T for _ in (1,))",
- "type Alias4 = (T for _ in (1,))",
- "type Alias5[T] = [T for _ in (1,)]",
- "type Alias6 = [T for _ in (1,)]",
+ cases = [
+ "type Alias[T] = (T for _ in (1,))",
+ "type Alias = (T for _ in (1,))",
+ "type Alias[T] = [T for _ in (1,)]",
+ "type Alias = [T for _ in (1,)]",
]
- for case in error_cases:
+ for case in cases:
with self.subTest(case=case):
- with self.assertRaisesRegex(SyntaxError,
- r"Cannot use [a-z]+ in annotation scope within class scope"):
- run_code(code.format(case))
+ ns = run_code(code.format(case))
+ alias = ns["C"].Alias
+ value = list(alias.__value__)[0]
+ if alias.__type_params__:
+ self.assertIs(value, alias.__type_params__[0])
+ else:
+ self.assertEqual(value, "global")
def test_lambda_in_alias_in_class(self):
code = """
}
}
- // we inline all non-generator-expression comprehensions
+ // we inline all non-generator-expression comprehensions,
+ // except those in annotation scopes that are nested in classes
int inline_comp =
entry->ste_comprehension &&
- !entry->ste_generator;
+ !entry->ste_generator &&
+ !ste->ste_can_see_class_scope;
if (!analyze_child_block(entry, newbound, newfree, newglobal,
type_params, new_class_entry, &child_free))
identifier scope_name, asdl_comprehension_seq *generators,
expr_ty elt, expr_ty value)
{
- if (st->st_cur->ste_can_see_class_scope) {
- // gh-109118
- PyErr_Format(PyExc_SyntaxError,
- "Cannot use comprehension 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);
- }
-
int is_generator = (e->kind == GeneratorExp_kind);
comprehension_ty outermost = ((comprehension_ty)
asdl_seq_GET(generators, 0));