mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-29463: Add docstring field to some AST nodes. (#46)
* bpo-29463: Add docstring field to some AST nodes. ClassDef, ModuleDef, FunctionDef, and AsyncFunctionDef has docstring field for now. It was first statement of there body. * fix document. thanks travis! * doc fixes
This commit is contained in:
parent
1bc156430b
commit
cb41b2766d
15 changed files with 3153 additions and 3048 deletions
|
@ -10,8 +10,10 @@ static PyTypeObject *mod_type;
|
|||
static PyObject* ast2obj_mod(void*);
|
||||
static PyTypeObject *Module_type;
|
||||
_Py_IDENTIFIER(body);
|
||||
_Py_IDENTIFIER(docstring);
|
||||
static char *Module_fields[]={
|
||||
"body",
|
||||
"docstring",
|
||||
};
|
||||
static PyTypeObject *Interactive_type;
|
||||
static char *Interactive_fields[]={
|
||||
|
@ -44,6 +46,7 @@ static char *FunctionDef_fields[]={
|
|||
"body",
|
||||
"decorator_list",
|
||||
"returns",
|
||||
"docstring",
|
||||
};
|
||||
static PyTypeObject *AsyncFunctionDef_type;
|
||||
static char *AsyncFunctionDef_fields[]={
|
||||
|
@ -52,6 +55,7 @@ static char *AsyncFunctionDef_fields[]={
|
|||
"body",
|
||||
"decorator_list",
|
||||
"returns",
|
||||
"docstring",
|
||||
};
|
||||
static PyTypeObject *ClassDef_type;
|
||||
_Py_IDENTIFIER(bases);
|
||||
|
@ -62,6 +66,7 @@ static char *ClassDef_fields[]={
|
|||
"keywords",
|
||||
"body",
|
||||
"decorator_list",
|
||||
"docstring",
|
||||
};
|
||||
static PyTypeObject *Return_type;
|
||||
_Py_IDENTIFIER(value);
|
||||
|
@ -861,7 +866,7 @@ static int init_types(void)
|
|||
mod_type = make_type("mod", &AST_type, NULL, 0);
|
||||
if (!mod_type) return 0;
|
||||
if (!add_attributes(mod_type, NULL, 0)) return 0;
|
||||
Module_type = make_type("Module", mod_type, Module_fields, 1);
|
||||
Module_type = make_type("Module", mod_type, Module_fields, 2);
|
||||
if (!Module_type) return 0;
|
||||
Interactive_type = make_type("Interactive", mod_type, Interactive_fields,
|
||||
1);
|
||||
|
@ -874,12 +879,12 @@ static int init_types(void)
|
|||
if (!stmt_type) return 0;
|
||||
if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0;
|
||||
FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields,
|
||||
5);
|
||||
6);
|
||||
if (!FunctionDef_type) return 0;
|
||||
AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type,
|
||||
AsyncFunctionDef_fields, 5);
|
||||
AsyncFunctionDef_fields, 6);
|
||||
if (!AsyncFunctionDef_type) return 0;
|
||||
ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 5);
|
||||
ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 6);
|
||||
if (!ClassDef_type) return 0;
|
||||
Return_type = make_type("Return", stmt_type, Return_fields, 1);
|
||||
if (!Return_type) return 0;
|
||||
|
@ -1206,7 +1211,7 @@ static int obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena);
|
|||
static int obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena);
|
||||
|
||||
mod_ty
|
||||
Module(asdl_seq * body, PyArena *arena)
|
||||
Module(asdl_seq * body, string docstring, PyArena *arena)
|
||||
{
|
||||
mod_ty p;
|
||||
p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
|
@ -1214,6 +1219,7 @@ Module(asdl_seq * body, PyArena *arena)
|
|||
return NULL;
|
||||
p->kind = Module_kind;
|
||||
p->v.Module.body = body;
|
||||
p->v.Module.docstring = docstring;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -1260,8 +1266,8 @@ Suite(asdl_seq * body, PyArena *arena)
|
|||
|
||||
stmt_ty
|
||||
FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
|
||||
decorator_list, expr_ty returns, int lineno, int col_offset,
|
||||
PyArena *arena)
|
||||
decorator_list, expr_ty returns, string docstring, int lineno, int
|
||||
col_offset, PyArena *arena)
|
||||
{
|
||||
stmt_ty p;
|
||||
if (!name) {
|
||||
|
@ -1283,6 +1289,7 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
|
|||
p->v.FunctionDef.body = body;
|
||||
p->v.FunctionDef.decorator_list = decorator_list;
|
||||
p->v.FunctionDef.returns = returns;
|
||||
p->v.FunctionDef.docstring = docstring;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
return p;
|
||||
|
@ -1290,8 +1297,8 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
|
|||
|
||||
stmt_ty
|
||||
AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
|
||||
* decorator_list, expr_ty returns, int lineno, int col_offset,
|
||||
PyArena *arena)
|
||||
* decorator_list, expr_ty returns, string docstring, int
|
||||
lineno, int col_offset, PyArena *arena)
|
||||
{
|
||||
stmt_ty p;
|
||||
if (!name) {
|
||||
|
@ -1313,6 +1320,7 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
|
|||
p->v.AsyncFunctionDef.body = body;
|
||||
p->v.AsyncFunctionDef.decorator_list = decorator_list;
|
||||
p->v.AsyncFunctionDef.returns = returns;
|
||||
p->v.AsyncFunctionDef.docstring = docstring;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
return p;
|
||||
|
@ -1320,8 +1328,8 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
|
|||
|
||||
stmt_ty
|
||||
ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq *
|
||||
body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena
|
||||
*arena)
|
||||
body, asdl_seq * decorator_list, string docstring, int lineno, int
|
||||
col_offset, PyArena *arena)
|
||||
{
|
||||
stmt_ty p;
|
||||
if (!name) {
|
||||
|
@ -1338,6 +1346,7 @@ ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq *
|
|||
p->v.ClassDef.keywords = keywords;
|
||||
p->v.ClassDef.body = body;
|
||||
p->v.ClassDef.decorator_list = decorator_list;
|
||||
p->v.ClassDef.docstring = docstring;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
return p;
|
||||
|
@ -2601,6 +2610,11 @@ ast2obj_mod(void* _o)
|
|||
if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_string(o->v.Module.docstring);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case Interactive_kind:
|
||||
result = PyType_GenericNew(Interactive_type, NULL, NULL);
|
||||
|
@ -2675,6 +2689,11 @@ ast2obj_stmt(void* _o)
|
|||
if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_string(o->v.FunctionDef.docstring);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case AsyncFunctionDef_kind:
|
||||
result = PyType_GenericNew(AsyncFunctionDef_type, NULL, NULL);
|
||||
|
@ -2705,6 +2724,11 @@ ast2obj_stmt(void* _o)
|
|||
if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_string(o->v.AsyncFunctionDef.docstring);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case ClassDef_kind:
|
||||
result = PyType_GenericNew(ClassDef_type, NULL, NULL);
|
||||
|
@ -2734,6 +2758,11 @@ ast2obj_stmt(void* _o)
|
|||
if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_string(o->v.ClassDef.docstring);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case Return_kind:
|
||||
result = PyType_GenericNew(Return_type, NULL, NULL);
|
||||
|
@ -3974,6 +4003,7 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena)
|
|||
}
|
||||
if (isinstance) {
|
||||
asdl_seq* body;
|
||||
string docstring;
|
||||
|
||||
if (_PyObject_HasAttrId(obj, &PyId_body)) {
|
||||
int res;
|
||||
|
@ -4003,7 +4033,17 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena)
|
|||
PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Module");
|
||||
return 1;
|
||||
}
|
||||
*out = Module(body, arena);
|
||||
if (exists_not_none(obj, &PyId_docstring)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_docstring);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_string(tmp, &docstring, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
docstring = NULL;
|
||||
}
|
||||
*out = Module(body, docstring, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
|
@ -4159,6 +4199,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
asdl_seq* body;
|
||||
asdl_seq* decorator_list;
|
||||
expr_ty returns;
|
||||
string docstring;
|
||||
|
||||
if (_PyObject_HasAttrId(obj, &PyId_name)) {
|
||||
int res;
|
||||
|
@ -4248,8 +4289,18 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
} else {
|
||||
returns = NULL;
|
||||
}
|
||||
*out = FunctionDef(name, args, body, decorator_list, returns, lineno,
|
||||
col_offset, arena);
|
||||
if (exists_not_none(obj, &PyId_docstring)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_docstring);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_string(tmp, &docstring, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
docstring = NULL;
|
||||
}
|
||||
*out = FunctionDef(name, args, body, decorator_list, returns,
|
||||
docstring, lineno, col_offset, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
|
@ -4263,6 +4314,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
asdl_seq* body;
|
||||
asdl_seq* decorator_list;
|
||||
expr_ty returns;
|
||||
string docstring;
|
||||
|
||||
if (_PyObject_HasAttrId(obj, &PyId_name)) {
|
||||
int res;
|
||||
|
@ -4352,8 +4404,18 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
} else {
|
||||
returns = NULL;
|
||||
}
|
||||
if (exists_not_none(obj, &PyId_docstring)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_docstring);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_string(tmp, &docstring, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
docstring = NULL;
|
||||
}
|
||||
*out = AsyncFunctionDef(name, args, body, decorator_list, returns,
|
||||
lineno, col_offset, arena);
|
||||
docstring, lineno, col_offset, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
|
@ -4367,6 +4429,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
asdl_seq* keywords;
|
||||
asdl_seq* body;
|
||||
asdl_seq* decorator_list;
|
||||
string docstring;
|
||||
|
||||
if (_PyObject_HasAttrId(obj, &PyId_name)) {
|
||||
int res;
|
||||
|
@ -4491,8 +4554,18 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from ClassDef");
|
||||
return 1;
|
||||
}
|
||||
*out = ClassDef(name, bases, keywords, body, decorator_list, lineno,
|
||||
col_offset, arena);
|
||||
if (exists_not_none(obj, &PyId_docstring)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_docstring);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_string(tmp, &docstring, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
docstring = NULL;
|
||||
}
|
||||
*out = ClassDef(name, bases, keywords, body, decorator_list, docstring,
|
||||
lineno, col_offset, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
|
|
89
Python/ast.c
89
Python/ast.c
|
@ -366,9 +366,12 @@ validate_assignlist(asdl_seq *targets, expr_context_ty ctx)
|
|||
}
|
||||
|
||||
static int
|
||||
validate_body(asdl_seq *body, const char *owner)
|
||||
validate_body(asdl_seq *body, const char *owner, int allowempty)
|
||||
{
|
||||
return validate_nonempty_seq(body, "body", owner) && validate_stmts(body);
|
||||
if (!allowempty && !validate_nonempty_seq(body, "body", owner)) {
|
||||
return 0;
|
||||
}
|
||||
return validate_stmts(body);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -377,13 +380,15 @@ validate_stmt(stmt_ty stmt)
|
|||
int i;
|
||||
switch (stmt->kind) {
|
||||
case FunctionDef_kind:
|
||||
return validate_body(stmt->v.FunctionDef.body, "FunctionDef") &&
|
||||
return validate_body(stmt->v.FunctionDef.body, "FunctionDef",
|
||||
stmt->v.FunctionDef.docstring != NULL) &&
|
||||
validate_arguments(stmt->v.FunctionDef.args) &&
|
||||
validate_exprs(stmt->v.FunctionDef.decorator_list, Load, 0) &&
|
||||
(!stmt->v.FunctionDef.returns ||
|
||||
validate_expr(stmt->v.FunctionDef.returns, Load));
|
||||
case ClassDef_kind:
|
||||
return validate_body(stmt->v.ClassDef.body, "ClassDef") &&
|
||||
return validate_body(stmt->v.ClassDef.body, "ClassDef",
|
||||
stmt->v.ClassDef.docstring != NULL) &&
|
||||
validate_exprs(stmt->v.ClassDef.bases, Load, 0) &&
|
||||
validate_keywords(stmt->v.ClassDef.keywords) &&
|
||||
validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0);
|
||||
|
@ -411,20 +416,20 @@ validate_stmt(stmt_ty stmt)
|
|||
case For_kind:
|
||||
return validate_expr(stmt->v.For.target, Store) &&
|
||||
validate_expr(stmt->v.For.iter, Load) &&
|
||||
validate_body(stmt->v.For.body, "For") &&
|
||||
validate_body(stmt->v.For.body, "For", 0) &&
|
||||
validate_stmts(stmt->v.For.orelse);
|
||||
case AsyncFor_kind:
|
||||
return validate_expr(stmt->v.AsyncFor.target, Store) &&
|
||||
validate_expr(stmt->v.AsyncFor.iter, Load) &&
|
||||
validate_body(stmt->v.AsyncFor.body, "AsyncFor") &&
|
||||
validate_body(stmt->v.AsyncFor.body, "AsyncFor", 0) &&
|
||||
validate_stmts(stmt->v.AsyncFor.orelse);
|
||||
case While_kind:
|
||||
return validate_expr(stmt->v.While.test, Load) &&
|
||||
validate_body(stmt->v.While.body, "While") &&
|
||||
validate_body(stmt->v.While.body, "While", 0) &&
|
||||
validate_stmts(stmt->v.While.orelse);
|
||||
case If_kind:
|
||||
return validate_expr(stmt->v.If.test, Load) &&
|
||||
validate_body(stmt->v.If.body, "If") &&
|
||||
validate_body(stmt->v.If.body, "If", 0) &&
|
||||
validate_stmts(stmt->v.If.orelse);
|
||||
case With_kind:
|
||||
if (!validate_nonempty_seq(stmt->v.With.items, "items", "With"))
|
||||
|
@ -435,7 +440,7 @@ validate_stmt(stmt_ty stmt)
|
|||
(item->optional_vars && !validate_expr(item->optional_vars, Store)))
|
||||
return 0;
|
||||
}
|
||||
return validate_body(stmt->v.With.body, "With");
|
||||
return validate_body(stmt->v.With.body, "With", 0);
|
||||
case AsyncWith_kind:
|
||||
if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith"))
|
||||
return 0;
|
||||
|
@ -445,7 +450,7 @@ validate_stmt(stmt_ty stmt)
|
|||
(item->optional_vars && !validate_expr(item->optional_vars, Store)))
|
||||
return 0;
|
||||
}
|
||||
return validate_body(stmt->v.AsyncWith.body, "AsyncWith");
|
||||
return validate_body(stmt->v.AsyncWith.body, "AsyncWith", 0);
|
||||
case Raise_kind:
|
||||
if (stmt->v.Raise.exc) {
|
||||
return validate_expr(stmt->v.Raise.exc, Load) &&
|
||||
|
@ -457,7 +462,7 @@ validate_stmt(stmt_ty stmt)
|
|||
}
|
||||
return 1;
|
||||
case Try_kind:
|
||||
if (!validate_body(stmt->v.Try.body, "Try"))
|
||||
if (!validate_body(stmt->v.Try.body, "Try", 0))
|
||||
return 0;
|
||||
if (!asdl_seq_LEN(stmt->v.Try.handlers) &&
|
||||
!asdl_seq_LEN(stmt->v.Try.finalbody)) {
|
||||
|
@ -473,7 +478,7 @@ validate_stmt(stmt_ty stmt)
|
|||
excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i);
|
||||
if ((handler->v.ExceptHandler.type &&
|
||||
!validate_expr(handler->v.ExceptHandler.type, Load)) ||
|
||||
!validate_body(handler->v.ExceptHandler.body, "ExceptHandler"))
|
||||
!validate_body(handler->v.ExceptHandler.body, "ExceptHandler", 0))
|
||||
return 0;
|
||||
}
|
||||
return (!asdl_seq_LEN(stmt->v.Try.finalbody) ||
|
||||
|
@ -498,7 +503,8 @@ validate_stmt(stmt_ty stmt)
|
|||
case Expr_kind:
|
||||
return validate_expr(stmt->v.Expr.value, Load);
|
||||
case AsyncFunctionDef_kind:
|
||||
return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") &&
|
||||
return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef",
|
||||
stmt->v.AsyncFunctionDef.docstring != NULL) &&
|
||||
validate_arguments(stmt->v.AsyncFunctionDef.args) &&
|
||||
validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
|
||||
(!stmt->v.AsyncFunctionDef.returns ||
|
||||
|
@ -594,7 +600,9 @@ struct compiling {
|
|||
static asdl_seq *seq_for_testlist(struct compiling *, const node *);
|
||||
static expr_ty ast_for_expr(struct compiling *, const node *);
|
||||
static stmt_ty ast_for_stmt(struct compiling *, const node *);
|
||||
static asdl_seq *ast_for_suite(struct compiling *, const node *);
|
||||
static asdl_seq *ast_for_body(struct compiling *c, const node *n,
|
||||
string *docstring);
|
||||
static string docstring_from_stmts(asdl_seq *stmts);
|
||||
static asdl_seq *ast_for_exprlist(struct compiling *, const node *,
|
||||
expr_context_ty);
|
||||
static expr_ty ast_for_testlist(struct compiling *, const node *);
|
||||
|
@ -806,7 +814,7 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
|
|||
}
|
||||
}
|
||||
}
|
||||
res = Module(stmts, arena);
|
||||
res = Module(stmts, docstring_from_stmts(stmts), arena);
|
||||
break;
|
||||
case eval_input: {
|
||||
expr_ty testlist_ast;
|
||||
|
@ -1593,6 +1601,7 @@ ast_for_funcdef_impl(struct compiling *c, const node *n,
|
|||
arguments_ty args;
|
||||
asdl_seq *body;
|
||||
expr_ty returns = NULL;
|
||||
string docstring;
|
||||
int name_i = 1;
|
||||
|
||||
REQ(n, funcdef);
|
||||
|
@ -1611,17 +1620,17 @@ ast_for_funcdef_impl(struct compiling *c, const node *n,
|
|||
return NULL;
|
||||
name_i += 2;
|
||||
}
|
||||
body = ast_for_suite(c, CHILD(n, name_i + 3));
|
||||
body = ast_for_body(c, CHILD(n, name_i + 3), &docstring);
|
||||
if (!body)
|
||||
return NULL;
|
||||
|
||||
if (is_async)
|
||||
return AsyncFunctionDef(name, args, body, decorator_seq, returns,
|
||||
LINENO(n),
|
||||
docstring, LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
else
|
||||
return FunctionDef(name, args, body, decorator_seq, returns,
|
||||
LINENO(n),
|
||||
docstring, LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
|
@ -3514,6 +3523,32 @@ ast_for_suite(struct compiling *c, const node *n)
|
|||
return seq;
|
||||
}
|
||||
|
||||
static string
|
||||
docstring_from_stmts(asdl_seq *stmts)
|
||||
{
|
||||
if (stmts && stmts->size) {
|
||||
stmt_ty s = (stmt_ty)asdl_seq_GET(stmts, 0);
|
||||
/* If first statement is a literal string, it's the doc string. */
|
||||
if (s->kind == Expr_kind && s->v.Expr.value->kind == Str_kind) {
|
||||
string doc = s->v.Expr.value->v.Str.s;
|
||||
/* not very efficient, but simple */
|
||||
memmove(&asdl_seq_GET(stmts, 0), &asdl_seq_GET(stmts, 1),
|
||||
(stmts->size - 1) * sizeof(void*));
|
||||
stmts->size--;
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static asdl_seq *
|
||||
ast_for_body(struct compiling *c, const node *n, string *docstring)
|
||||
{
|
||||
asdl_seq *stmts = ast_for_suite(c, n);
|
||||
*docstring = docstring_from_stmts(stmts);
|
||||
return stmts;
|
||||
}
|
||||
|
||||
static stmt_ty
|
||||
ast_for_if_stmt(struct compiling *c, const node *n)
|
||||
{
|
||||
|
@ -3898,12 +3933,13 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
|||
/* classdef: 'class' NAME ['(' arglist ')'] ':' suite */
|
||||
PyObject *classname;
|
||||
asdl_seq *s;
|
||||
string docstring;
|
||||
expr_ty call;
|
||||
|
||||
REQ(n, classdef);
|
||||
|
||||
if (NCH(n) == 4) { /* class NAME ':' suite */
|
||||
s = ast_for_suite(c, CHILD(n, 3));
|
||||
s = ast_for_body(c, CHILD(n, 3), &docstring);
|
||||
if (!s)
|
||||
return NULL;
|
||||
classname = NEW_IDENTIFIER(CHILD(n, 1));
|
||||
|
@ -3911,12 +3947,12 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
|||
return NULL;
|
||||
if (forbidden_name(c, classname, CHILD(n, 3), 0))
|
||||
return NULL;
|
||||
return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
return ClassDef(classname, NULL, NULL, s, decorator_seq, docstring,
|
||||
LINENO(n), n->n_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */
|
||||
s = ast_for_suite(c, CHILD(n,5));
|
||||
s = ast_for_body(c, CHILD(n, 5), &docstring);
|
||||
if (!s)
|
||||
return NULL;
|
||||
classname = NEW_IDENTIFIER(CHILD(n, 1));
|
||||
|
@ -3924,8 +3960,8 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
|||
return NULL;
|
||||
if (forbidden_name(c, classname, CHILD(n, 3), 0))
|
||||
return NULL;
|
||||
return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
return ClassDef(classname, NULL, NULL, s, decorator_seq, docstring,
|
||||
LINENO(n), n->n_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
/* class NAME '(' arglist ')' ':' suite */
|
||||
|
@ -3941,7 +3977,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
|||
if (!call)
|
||||
return NULL;
|
||||
}
|
||||
s = ast_for_suite(c, CHILD(n, 6));
|
||||
s = ast_for_body(c, CHILD(n, 6), &docstring);
|
||||
if (!s)
|
||||
return NULL;
|
||||
classname = NEW_IDENTIFIER(CHILD(n, 1));
|
||||
|
@ -3951,7 +3987,8 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
|||
return NULL;
|
||||
|
||||
return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s,
|
||||
decorator_seq, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
decorator_seq, docstring, LINENO(n), n->n_col_offset,
|
||||
c->c_arena);
|
||||
}
|
||||
|
||||
static stmt_ty
|
||||
|
|
|
@ -1324,18 +1324,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
|||
} \
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_isdocstring(stmt_ty s)
|
||||
{
|
||||
if (s->kind != Expr_kind)
|
||||
return 0;
|
||||
if (s->v.Expr.value->kind == Str_kind)
|
||||
return 1;
|
||||
if (s->v.Expr.value->kind == Constant_kind)
|
||||
return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
is_const(expr_ty e)
|
||||
{
|
||||
|
@ -1435,36 +1423,27 @@ find_ann(asdl_seq *stmts)
|
|||
and for annotations. */
|
||||
|
||||
static int
|
||||
compiler_body(struct compiler *c, asdl_seq *stmts)
|
||||
compiler_body(struct compiler *c, asdl_seq *stmts, string docstring)
|
||||
{
|
||||
int i = 0;
|
||||
stmt_ty st;
|
||||
|
||||
/* Set current line number to the line number of first statement.
|
||||
This way line number for SETUP_ANNOTATIONS will always
|
||||
coincide with the line number of first "real" statement in module.
|
||||
If body is empy, then lineno will be set later in assemble. */
|
||||
if (c->u->u_scope_type == COMPILER_SCOPE_MODULE &&
|
||||
!c->u->u_lineno && asdl_seq_LEN(stmts)) {
|
||||
st = (stmt_ty)asdl_seq_GET(stmts, 0);
|
||||
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
|
||||
c->u->u_lineno = st->lineno;
|
||||
}
|
||||
/* Every annotated class and module should have __annotations__. */
|
||||
if (find_ann(stmts)) {
|
||||
ADDOP(c, SETUP_ANNOTATIONS);
|
||||
}
|
||||
if (!asdl_seq_LEN(stmts))
|
||||
return 1;
|
||||
st = (stmt_ty)asdl_seq_GET(stmts, 0);
|
||||
if (compiler_isdocstring(st) && c->c_optimize < 2) {
|
||||
/* don't generate docstrings if -OO */
|
||||
i = 1;
|
||||
VISIT(c, expr, st->v.Expr.value);
|
||||
if (!compiler_nameop(c, __doc__, Store))
|
||||
return 0;
|
||||
/* if not -OO mode, set docstring */
|
||||
if (c->c_optimize < 2 && docstring) {
|
||||
ADDOP_O(c, LOAD_CONST, docstring, consts);
|
||||
ADDOP_NAME(c, STORE_NAME, __doc__, names);
|
||||
}
|
||||
for (; i < asdl_seq_LEN(stmts); i++)
|
||||
VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i));
|
||||
VISIT_SEQ(c, stmt, stmts);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1484,7 +1463,7 @@ compiler_mod(struct compiler *c, mod_ty mod)
|
|||
return NULL;
|
||||
switch (mod->kind) {
|
||||
case Module_kind:
|
||||
if (!compiler_body(c, mod->v.Module.body)) {
|
||||
if (!compiler_body(c, mod->v.Module.body, mod->v.Module.docstring)) {
|
||||
compiler_exit_scope(c);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1812,15 +1791,13 @@ static int
|
|||
compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
||||
{
|
||||
PyCodeObject *co;
|
||||
PyObject *qualname, *first_const = Py_None;
|
||||
PyObject *qualname, *docstring = Py_None;
|
||||
arguments_ty args;
|
||||
expr_ty returns;
|
||||
identifier name;
|
||||
asdl_seq* decos;
|
||||
asdl_seq *body;
|
||||
stmt_ty st;
|
||||
Py_ssize_t i, n, funcflags;
|
||||
int docstring;
|
||||
Py_ssize_t i, funcflags;
|
||||
int annotations;
|
||||
int scope_type;
|
||||
|
||||
|
@ -1866,27 +1843,18 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
|||
return 0;
|
||||
}
|
||||
|
||||
st = (stmt_ty)asdl_seq_GET(body, 0);
|
||||
docstring = compiler_isdocstring(st);
|
||||
if (docstring && c->c_optimize < 2) {
|
||||
if (st->v.Expr.value->kind == Constant_kind)
|
||||
first_const = st->v.Expr.value->v.Constant.value;
|
||||
else
|
||||
first_const = st->v.Expr.value->v.Str.s;
|
||||
}
|
||||
if (compiler_add_o(c, c->u->u_consts, first_const) < 0) {
|
||||
/* if not -OO mode, add docstring */
|
||||
if (c->c_optimize < 2 && s->v.FunctionDef.docstring)
|
||||
docstring = s->v.FunctionDef.docstring;
|
||||
if (compiler_add_o(c, c->u->u_consts, docstring) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->u->u_argcount = asdl_seq_LEN(args->args);
|
||||
c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
|
||||
n = asdl_seq_LEN(body);
|
||||
/* if there was a docstring, we need to skip the first statement */
|
||||
for (i = docstring; i < n; i++) {
|
||||
st = (stmt_ty)asdl_seq_GET(body, i);
|
||||
VISIT_IN_SCOPE(c, stmt, st);
|
||||
}
|
||||
VISIT_SEQ_IN_SCOPE(c, stmt, body);
|
||||
co = assemble(c, 1);
|
||||
qualname = c->u->u_qualname;
|
||||
Py_INCREF(qualname);
|
||||
|
@ -1967,7 +1935,7 @@ compiler_class(struct compiler *c, stmt_ty s)
|
|||
}
|
||||
Py_DECREF(str);
|
||||
/* compile the body proper */
|
||||
if (!compiler_body(c, s->v.ClassDef.body)) {
|
||||
if (!compiler_body(c, s->v.ClassDef.body, s->v.ClassDef.docstring)) {
|
||||
compiler_exit_scope(c);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,6 @@ static int
|
|||
future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
|
||||
{
|
||||
int i, done = 0, prev_line = 0;
|
||||
stmt_ty first;
|
||||
|
||||
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
|
||||
return 1;
|
||||
|
@ -77,16 +76,7 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
|
|||
but is preceded by a regular import.
|
||||
*/
|
||||
|
||||
i = 0;
|
||||
first = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
|
||||
if (first->kind == Expr_kind
|
||||
&& (first->v.Expr.value->kind == Str_kind
|
||||
|| (first->v.Expr.value->kind == Constant_kind
|
||||
&& PyUnicode_CheckExact(first->v.Expr.value->v.Constant.value))))
|
||||
i++;
|
||||
|
||||
|
||||
for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {
|
||||
for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
|
||||
stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
|
||||
|
||||
if (done && s->lineno > prev_line)
|
||||
|
|
3194
Python/importlib.h
3194
Python/importlib.h
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue