diff --git a/ast3/Python/ast.c b/ast3/Python/ast.c index 905788d7..2c1120e5 100644 --- a/ast3/Python/ast.c +++ b/ast3/Python/ast.c @@ -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: @@ -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; @@ -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)); @@ -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)); @@ -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; @@ -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; @@ -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); } @@ -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); @@ -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; diff --git a/typed_ast/ast3.py b/typed_ast/ast3.py index f09b2031..e44632cd 100644 --- a/typed_ast/ast3.py +++ b/typed_ast/ast3.py @@ -48,8 +48,12 @@ def parse(source, filename='', 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)