Skip to content
This repository was archived by the owner on Jul 5, 2023. It is now read-only.

Add checks for some 3.5+ only syntax (async/await and the @ operator) #41

Merged
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
40 changes: 37 additions & 3 deletions ast3/Python/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ Ta3AST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename_str,
*/

static operator_ty
get_operator(const node *n)
get_operator(struct compiling *c, const node *n)
{
switch (TYPE(n)) {
case VBAR:
Expand All @@ -990,6 +990,11 @@ get_operator(const node *n)
case STAR:
return Mult;
case AT:
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;
case SLASH:
return Div;
Expand Down Expand Up @@ -1198,6 +1203,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 @@ -1697,6 +1707,12 @@ ast_for_funcdef_impl(struct compiling *c, const node *n,
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");
return NULL;
}

REQ(n, funcdef);

name = NEW_IDENTIFIER(CHILD(n, name_i));
Expand Down Expand Up @@ -2444,7 +2460,7 @@ ast_for_binop(struct compiling *c, const node *n)
if (!expr2)
return NULL;

newoperator = get_operator(CHILD(n, 1));
newoperator = get_operator(c, CHILD(n, 1));
if (!newoperator)
return NULL;

Expand All @@ -2458,7 +2474,7 @@ ast_for_binop(struct compiling *c, const node *n)
expr_ty tmp_result, tmp;
const node* next_oper = CHILD(n, i * 2 + 1);

newoperator = get_operator(next_oper);
newoperator = get_operator(c, next_oper);
if (!newoperator)
return NULL;

Expand Down Expand Up @@ -2587,6 +2603,11 @@ ast_for_atom_expr(struct compiling *c, const node *n)
nch = NCH(n);

if (TYPE(CHILD(n, 0)) == AWAIT) {
if (c->c_feature_version < 5) {
ast_error(c, n,
"Await expressions are only supported in Python 3.5 and greater");
return NULL;
}
start = 1;
assert(nch > 1);
}
Expand Down Expand Up @@ -3840,6 +3861,13 @@ ast_for_for_stmt(struct compiling *c, const node *n, int is_async)
const node *node_target;
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 @@ -4035,6 +4063,12 @@ ast_for_with_stmt(struct compiling *c, const node *n, int 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
8 changes: 6 additions & 2 deletions typed_ast/ast3.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ def parse(source, filename='<unknown>', mode='exec', feature_version=LATEST_MINO
Set feature_version to limit the syntax parsed to that minor version of
Python 3. For example, feature_version=5 will prevent new syntax features
from Python 3.6+ from being used, such as fstrings. Currently only
supported for Python 3.5+, so feature_version=4 or less are all equivalent
to feature_version=5.
fully supported for Python 3.5+ with partial support for Python 3.4.
So, feature_version=3 or less are all equivalent to feature_version=4.

When feature_version=4, the parser will forbid the use of the async/await
keywords and the '@' operator, but will not forbid the use of PEP 448
additional unpacking generalizations, which were also added in Python 3.5.
"""
return _ast3._parse(source, filename, mode, feature_version)

Expand Down