Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Include/Python-ast.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Lib/test/test_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
Traceback (most recent call last):
SyntaxError: cannot assign to True

>>> (True := 1)
Traceback (most recent call last):
SyntaxError: cannot use named assignment with True

>>> obj.__debug__ = 1
Traceback (most recent call last):
SyntaxError: cannot assign to __debug__
Expand Down
2 changes: 1 addition & 1 deletion Parser/Python.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ module Python
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

expr_context = Load | Store | Del | AugLoad | AugStore | Param | NamedStore
expr_context = Load | Store | Del | AugLoad | AugStore | Param

slice = Slice(expr? lower, expr? upper, expr? step)
| ExtSlice(slice* dims)
Expand Down
21 changes: 1 addition & 20 deletions Python/Python-ast.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

199 changes: 90 additions & 109 deletions Python/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ expr_context_name(expr_context_ty ctx)
return "Load";
case Store:
return "Store";
case NamedStore:
return "NamedStore";
case Del:
return "Del";
case AugLoad:
Expand Down Expand Up @@ -1029,6 +1027,80 @@ copy_location(expr_ty e, const node *n)
return e;
}

static const char *
get_expr_name(expr_ty e)
{
switch (e->kind) {
case Attribute_kind:
return "attribute";
case Subscript_kind:
return "subscript";
case Starred_kind:
return "starred";
case Name_kind:
return "name";
case List_kind:
return "list";
case Tuple_kind:
return "tuple";
case Lambda_kind:
return "lambda";
case Call_kind:
return "function call";
case BoolOp_kind:
case BinOp_kind:
case UnaryOp_kind:
return "operator";
case GeneratorExp_kind:
return "generator expression";
case Yield_kind:
case YieldFrom_kind:
return "yield expression";
case Await_kind:
return "await expression";
case ListComp_kind:
return "list comprehension";
case SetComp_kind:
return "set comprehension";
case DictComp_kind:
return "dict comprehension";
case Dict_kind:
return "dict display";
case Set_kind:
return "set display";
case JoinedStr_kind:
case FormattedValue_kind:
return "f-string expression";
case Constant_kind: {
PyObject *value = e->v.Constant.value;
if (value == Py_None) {
return "None";
}
if (value == Py_False) {
return "False";
}
if (value == Py_True) {
return "True";
}
if (value == Py_Ellipsis) {
return "Ellipsis";
}
return "literal";
}
case Compare_kind:
return "comparison";
case IfExp_kind:
return "conditional expression";
case NamedExpr_kind:
return "named expression";
default:
PyErr_Format(PyExc_SystemError,
"unexpected expression in assignment %d (line %d)",
e->kind, e->lineno);
return NULL;
}
}

/* Set the context ctx for expr_ty e, recursively traversing e.

Only sets context for expr kinds that "can appear in assignment context"
Expand All @@ -1040,10 +1112,6 @@ static int
set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
{
asdl_seq *s = NULL;
/* If a particular expression type can't be used for assign / delete,
set expr_name to its name and an error message will be generated.
*/
const char* expr_name = NULL;

/* The ast defines augmented store and load contexts, but the
implementation here doesn't actually use them. The code may be
Expand All @@ -1056,136 +1124,41 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)

switch (e->kind) {
case Attribute_kind:
if (ctx == NamedStore) {
expr_name = "attribute";
break;
}

e->v.Attribute.ctx = ctx;
if (ctx == Store && forbidden_name(c, e->v.Attribute.attr, n, 1))
return 0;
break;
case Subscript_kind:
if (ctx == NamedStore) {
expr_name = "subscript";
break;
}

e->v.Subscript.ctx = ctx;
break;
case Starred_kind:
if (ctx == NamedStore) {
expr_name = "starred";
break;
}

e->v.Starred.ctx = ctx;
if (!set_context(c, e->v.Starred.value, ctx, n))
return 0;
break;
case Name_kind:
if (ctx == Store || ctx == NamedStore) {
if (ctx == Store) {
if (forbidden_name(c, e->v.Name.id, n, 0))
return 0; /* forbidden_name() calls ast_error() */
}
e->v.Name.ctx = ctx;
break;
case List_kind:
if (ctx == NamedStore) {
expr_name = "list";
break;
}

e->v.List.ctx = ctx;
s = e->v.List.elts;
break;
case Tuple_kind:
if (ctx == NamedStore) {
expr_name = "tuple";
break;
}

e->v.Tuple.ctx = ctx;
s = e->v.Tuple.elts;
break;
case Lambda_kind:
expr_name = "lambda";
break;
case Call_kind:
expr_name = "function call";
break;
case BoolOp_kind:
case BinOp_kind:
case UnaryOp_kind:
expr_name = "operator";
break;
case GeneratorExp_kind:
expr_name = "generator expression";
break;
case Yield_kind:
case YieldFrom_kind:
expr_name = "yield expression";
break;
case Await_kind:
expr_name = "await expression";
break;
case ListComp_kind:
expr_name = "list comprehension";
break;
case SetComp_kind:
expr_name = "set comprehension";
break;
case DictComp_kind:
expr_name = "dict comprehension";
break;
case Dict_kind:
expr_name = "dict display";
break;
case Set_kind:
expr_name = "set display";
break;
case JoinedStr_kind:
case FormattedValue_kind:
expr_name = "f-string expression";
break;
case Constant_kind: {
PyObject *value = e->v.Constant.value;
if (value == Py_None || value == Py_False || value == Py_True
|| value == Py_Ellipsis)
{
return ast_error(c, n, "cannot %s %R",
ctx == Store ? "assign to" : "delete",
value);
default: {
const char *expr_name = get_expr_name(e);
if (expr_name != NULL) {
ast_error(c, n, "cannot %s %s",
ctx == Store ? "assign to" : "delete",
expr_name);
}
expr_name = "literal";
break;
}
case Compare_kind:
expr_name = "comparison";
break;
case IfExp_kind:
expr_name = "conditional expression";
break;
case NamedExpr_kind:
expr_name = "named expression";
break;
default:
PyErr_Format(PyExc_SystemError,
"unexpected expression in %sassignment %d (line %d)",
ctx == NamedStore ? "named ": "",
e->kind, e->lineno);
return 0;
}
/* Check for error string set by switch */
if (expr_name) {
if (ctx == NamedStore) {
return ast_error(c, n, "cannot use named assignment with %s",
expr_name);
}
else {
return ast_error(c, n, "cannot %s %s",
ctx == Store ? "assign to" : "delete",
expr_name);
}
}

Expand Down Expand Up @@ -1895,7 +1868,15 @@ ast_for_namedexpr(struct compiling *c, const node *n)
if (!value)
return NULL;

if (!set_context(c, target, NamedStore, n))
if (target->kind != Name_kind) {
const char *expr_name = get_expr_name(target);
if (expr_name != NULL) {
ast_error(c, n, "cannot use named assignment with %s", expr_name);
}
return NULL;
}

if (!set_context(c, target, Store, n))
return NULL;

return NamedExpr(target, value, LINENO(n), n->n_col_offset, n->n_end_lineno,
Expand Down
Loading