From b164476aaf77ceffac36ddbbdc7f4df90fbfebd3 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Thu, 8 Sep 2016 20:50:03 -0700 Subject: Issue #27985: Implement PEP 526 -- Syntax for Variable Annotations. Patch by Ivan Levkivskyi. --- Python/Python-ast.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) (limited to 'Python/Python-ast.c') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 1193c7c66b..6ab57dfe8e 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -86,6 +86,15 @@ static char *AugAssign_fields[]={ "op", "value", }; +static PyTypeObject *AnnAssign_type; +_Py_IDENTIFIER(annotation); +_Py_IDENTIFIER(simple); +static char *AnnAssign_fields[]={ + "target", + "annotation", + "value", + "simple", +}; static PyTypeObject *For_type; _Py_IDENTIFIER(iter); _Py_IDENTIFIER(orelse); @@ -466,7 +475,6 @@ static char *arg_attributes[] = { "col_offset", }; _Py_IDENTIFIER(arg); -_Py_IDENTIFIER(annotation); static char *arg_fields[]={ "arg", "annotation", @@ -873,6 +881,8 @@ static int init_types(void) if (!Assign_type) return 0; AugAssign_type = make_type("AugAssign", stmt_type, AugAssign_fields, 3); if (!AugAssign_type) return 0; + AnnAssign_type = make_type("AnnAssign", stmt_type, AnnAssign_fields, 4); + if (!AnnAssign_type) return 0; For_type = make_type("For", stmt_type, For_fields, 4); if (!For_type) return 0; AsyncFor_type = make_type("AsyncFor", stmt_type, AsyncFor_fields, 4); @@ -1406,6 +1416,34 @@ AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int return p; } +stmt_ty +AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int simple, int + lineno, int col_offset, PyArena *arena) +{ + stmt_ty p; + if (!target) { + PyErr_SetString(PyExc_ValueError, + "field target is required for AnnAssign"); + return NULL; + } + if (!annotation) { + PyErr_SetString(PyExc_ValueError, + "field annotation is required for AnnAssign"); + return NULL; + } + p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = AnnAssign_kind; + p->v.AnnAssign.target = target; + p->v.AnnAssign.annotation = annotation; + p->v.AnnAssign.value = value; + p->v.AnnAssign.simple = simple; + p->lineno = lineno; + p->col_offset = col_offset; + return p; +} + stmt_ty For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int lineno, int col_offset, PyArena *arena) @@ -2740,6 +2778,30 @@ ast2obj_stmt(void* _o) goto failed; Py_DECREF(value); break; + case AnnAssign_kind: + result = PyType_GenericNew(AnnAssign_type, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(o->v.AnnAssign.target); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_target, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(o->v.AnnAssign.annotation); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_annotation, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(o->v.AnnAssign.value); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_int(o->v.AnnAssign.simple); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_simple, value) == -1) + goto failed; + Py_DECREF(value); + break; case For_kind: result = PyType_GenericNew(For_type, NULL, NULL); if (!result) goto failed; @@ -4535,6 +4597,64 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } + isinstance = PyObject_IsInstance(obj, (PyObject*)AnnAssign_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + expr_ty target; + expr_ty annotation; + expr_ty value; + int simple; + + if (_PyObject_HasAttrId(obj, &PyId_target)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_target); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &target, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AnnAssign"); + return 1; + } + if (_PyObject_HasAttrId(obj, &PyId_annotation)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_annotation); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &annotation, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"annotation\" missing from AnnAssign"); + return 1; + } + if (exists_not_none(obj, &PyId_value)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_value); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &value, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + value = NULL; + } + if (_PyObject_HasAttrId(obj, &PyId_simple)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_simple); + if (tmp == NULL) goto failed; + res = obj2ast_int(tmp, &simple, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"simple\" missing from AnnAssign"); + return 1; + } + *out = AnnAssign(target, annotation, value, simple, lineno, col_offset, + arena); + if (*out == NULL) goto failed; + return 0; + } isinstance = PyObject_IsInstance(obj, (PyObject*)For_type); if (isinstance == -1) { return 1; @@ -7517,6 +7637,8 @@ PyInit__ast(void) NULL; if (PyDict_SetItemString(d, "AugAssign", (PyObject*)AugAssign_type) < 0) return NULL; + if (PyDict_SetItemString(d, "AnnAssign", (PyObject*)AnnAssign_type) < 0) + return NULL; if (PyDict_SetItemString(d, "For", (PyObject*)For_type) < 0) return NULL; if (PyDict_SetItemString(d, "AsyncFor", (PyObject*)AsyncFor_type) < 0) return NULL; -- cgit v1.2.1 From b26bd4a4bf3de9dbedbbbd1209fea77cd7af7689 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Fri, 9 Sep 2016 10:36:01 -0700 Subject: Issue #28008: Implement PEP 530 -- asynchronous comprehensions. --- Python/Python-ast.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'Python/Python-ast.c') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 6ab57dfe8e..f10e315707 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -435,10 +435,12 @@ static PyTypeObject *NotIn_type; static PyTypeObject *comprehension_type; static PyObject* ast2obj_comprehension(void*); _Py_IDENTIFIER(ifs); +_Py_IDENTIFIER(is_async); static char *comprehension_fields[]={ "target", "iter", "ifs", + "is_async", }; static PyTypeObject *excepthandler_type; static char *excepthandler_attributes[] = { @@ -1148,7 +1150,7 @@ static int init_types(void) NotIn_singleton = PyType_GenericNew(NotIn_type, NULL, NULL); if (!NotIn_singleton) return 0; comprehension_type = make_type("comprehension", &AST_type, - comprehension_fields, 3); + comprehension_fields, 4); if (!comprehension_type) return 0; if (!add_attributes(comprehension_type, NULL, 0)) return 0; excepthandler_type = make_type("excepthandler", &AST_type, NULL, 0); @@ -2445,7 +2447,8 @@ Index(expr_ty value, PyArena *arena) } comprehension_ty -comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena) +comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, int is_async, + PyArena *arena) { comprehension_ty p; if (!target) { @@ -2464,6 +2467,7 @@ comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena) p->target = target; p->iter = iter; p->ifs = ifs; + p->is_async = is_async; return p; } @@ -3722,6 +3726,11 @@ ast2obj_comprehension(void* _o) if (_PyObject_SetAttrId(result, &PyId_ifs, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_int(o->is_async); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_is_async, value) == -1) + goto failed; + Py_DECREF(value); return result; failed: Py_XDECREF(value); @@ -7146,6 +7155,7 @@ obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena* arena) expr_ty target; expr_ty iter; asdl_seq* ifs; + int is_async; if (_PyObject_HasAttrId(obj, &PyId_target)) { int res; @@ -7193,7 +7203,18 @@ obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"ifs\" missing from comprehension"); return 1; } - *out = comprehension(target, iter, ifs, arena); + if (_PyObject_HasAttrId(obj, &PyId_is_async)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_is_async); + if (tmp == NULL) goto failed; + res = obj2ast_int(tmp, &is_async, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"is_async\" missing from comprehension"); + return 1; + } + *out = comprehension(target, iter, ifs, is_async, arena); return 0; failed: Py_XDECREF(tmp); -- cgit v1.2.1