self.assertRaises(IndentationError, exec, code)
+ @support.cpython_only
+ def test_disallowed_type_param_names(self):
+ # See gh-128632
+
+ self._check_error(f"class A[__classdict__]: pass",
+ f"reserved name '__classdict__' cannot be used for type parameter")
+ self._check_error(f"def f[__classdict__](): pass",
+ f"reserved name '__classdict__' cannot be used for type parameter")
+ self._check_error(f"type T[__classdict__] = tuple[__classdict__]",
+ f"reserved name '__classdict__' cannot be used for type parameter")
+
+ # These compilations are here to make sure __class__, __classcell__ and __classdictcell__
+ # don't break in the future like __classdict__ did in this case.
+ for name in ('__class__', '__classcell__', '__classdictcell__'):
+ compile(f"""
+class A:
+ class B[{name}]: pass
+ """, "<testcase>", mode="exec")
+
@support.cpython_only
def test_nested_named_except_blocks(self):
code = ""
VISIT_QUIT(st, 1);
}
+static int
+symtable_visit_type_param_check_reserved_name(struct symtable *st, type_param_ty tp, identifier name)
+{
+ if (_PyUnicode_Equal(name, &_Py_ID(__classdict__))) {
+ PyObject *error_msg = PyUnicode_FromFormat("reserved name '%U' cannot be "
+ "used for type parameter", name);
+ PyErr_SetObject(PyExc_SyntaxError, error_msg);
+ Py_DECREF(error_msg);
+ PyErr_RangedSyntaxLocationObject(st->st_filename,
+ tp->lineno,
+ tp->col_offset + 1,
+ tp->end_lineno,
+ tp->end_col_offset + 1);
+ return 0;
+ }
+ return 1;
+}
+
static int
symtable_visit_type_param(struct symtable *st, type_param_ty tp)
{
}
switch(tp->kind) {
case TypeVar_kind:
+ if (!symtable_visit_type_param_check_reserved_name(st, tp, tp->v.TypeVar.name))
+ VISIT_QUIT(st, 0);
if (!symtable_add_def(st, tp->v.TypeVar.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
VISIT_QUIT(st, 0);
if (tp->v.TypeVar.bound) {
}
break;
case TypeVarTuple_kind:
+ if (!symtable_visit_type_param_check_reserved_name(st, tp, tp->v.TypeVarTuple.name))
+ VISIT_QUIT(st, 0);
if (!symtable_add_def(st, tp->v.TypeVarTuple.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
VISIT_QUIT(st, 0);
break;
case ParamSpec_kind:
+ if (!symtable_visit_type_param_check_reserved_name(st, tp, tp->v.ParamSpec.name))
+ VISIT_QUIT(st, 0);
if (!symtable_add_def(st, tp->v.ParamSpec.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
VISIT_QUIT(st, 0);
break;