Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-35975: Support parsing earlier minor versions of Python 3 #12086

Merged
merged 14 commits into from
Mar 7, 2019
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Implement further restrictions on feature_version
This is everything currently in typeshed except await expressions (but
it does reject async functions etc.):

    - Reject async functions and async for/with in minor versions < 5

    - Reject async comprehensions in minor versions < 6

    - Reject underscores in numeric literals in minor versions < 6

    - Reject variable annotations in minor versions < 6

    - Reject `X @= Y` in minor versions < 5
  • Loading branch information
gvanrossum committed Mar 5, 2019
commit 8caf275763a2c232d81ba0ac1900955215c99bd3
55 changes: 54 additions & 1 deletion Python/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,11 @@ ast_for_augassign(struct compiling *c, const node *n)
else
return Mult;
case '@':
if (c->c_feature_version < 5) {
ast_error(c, n,
"The '@' operator is only supported in Python 3.5 and greater");
return (operator_ty)0;
}
return MatMult;
default:
PyErr_Format(PyExc_SystemError, "invalid augassign: %s", STR(n));
Expand Down Expand Up @@ -1726,6 +1731,12 @@ ast_for_funcdef_impl(struct compiling *c, const node *n0,
node *tc;
string type_comment = NULL;

if (is_async && c->c_feature_version < 5) {
ast_error(c, n,
"Async functions are only supported in Python 3.5 and greater");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here indentation looks good.

return NULL;
}

REQ(n, funcdef);

name = NEW_IDENTIFIER(CHILD(n, name_i));
Expand Down Expand Up @@ -2050,6 +2061,13 @@ ast_for_comprehension(struct compiling *c, const node *n)
}
REQ(sync_n, sync_comp_for);

/* Async comprehensions only allowed in Python 3.6 and greater */
if (is_async && c->c_feature_version < 6) {
ast_error(c, n,
"Async comprehensions are only supported in Python 3.6 and greater");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation here and in several other places is a bit unusual, I would rather justify it after (.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, fixed. My guess is that at some point in the past that function had had a name that was 2 characters shorter. :-)

return NULL;
}

for_ch = CHILD(sync_n, 1);
t = ast_for_exprlist(c, for_ch, Store);
if (!t)
Expand Down Expand Up @@ -2344,7 +2362,15 @@ ast_for_atom(struct compiling *c, const node *n)
return str;
}
case NUMBER: {
PyObject *pynum = parsenumber(c, STR(ch));
PyObject *pynum;
/* Underscores in numeric literals are only allowed in Python 3.6 or greater */
/* Check for underscores here rather than in parse_number so we can report a line number on error */
if (c->c_feature_version < 6 && strchr(STR(ch), '_') != NULL) {
ast_error(c, ch,
"Underscores in numeric literals are only supported in Python 3.6 and greater");
return NULL;
}
pynum = parsenumber(c, STR(ch));
if (!pynum)
return NULL;

Expand Down Expand Up @@ -3240,6 +3266,13 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
node *deep, *ann = CHILD(n, 1);
int simple = 1;

/* AnnAssigns are only allowed in Python 3.6 or greater */
if (c->c_feature_version < 6) {
ast_error(c, ch,
"Variable annotation syntax is only supported in Python 3.6 and greater");
return NULL;
}

/* we keep track of parens to qualify (x) as expression not name */
deep = ch;
while (NCH(deep) == 1) {
Expand Down Expand Up @@ -4057,6 +4090,13 @@ ast_for_for_stmt(struct compiling *c, const node *n0, bool is_async)
int end_lineno, end_col_offset;
int has_type_comment;
string type_comment;

if (is_async && c->c_feature_version < 5) {
ast_error(c, n,
"Async for loops are only supported in Python 3.5 and greater");
return NULL;
}

/* for_stmt: 'for' exprlist 'in' testlist ':' [TYPE_COMMENT] suite ['else' ':' suite] */
REQ(n, for_stmt);

Expand Down Expand Up @@ -4285,6 +4325,12 @@ ast_for_with_stmt(struct compiling *c, const node *n0, bool is_async)
asdl_seq *items, *body;
string type_comment;

if (is_async && c->c_feature_version < 5) {
ast_error(c, n,
"Async with statements are only supported in Python 3.5 and greater");
return NULL;
}

REQ(n, with_stmt);

has_type_comment = TYPE(CHILD(n, NCH(n) - 2)) == TYPE_COMMENT;
Expand Down Expand Up @@ -5576,6 +5622,13 @@ parsestr(struct compiling *c, const node *n, int *bytesmode, int *rawmode,
}
}
}

/* fstrings are only allowed in Python 3.6 and greater */
if (fmode && c->c_feature_version < 6) {
ast_error(c, n, "Format strings are only supported in Python 3.6 and greater");
return -1;
}

if (fmode && *bytesmode) {
PyErr_BadInternalCall();
return -1;
Expand Down