bpo-33691: Add _PyAST_GetDocString(). (GH-7236)

This commit is contained in:
Serhiy Storchaka 2018-05-30 10:56:16 +03:00 committed by GitHub
parent e9537ad6a1
commit 143ce5c6db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 58 deletions

View File

@ -21,6 +21,11 @@ PyAPI_FUNC(mod_ty) PyAST_FromNodeObject(
/* _PyAST_ExprAsUnicode is defined in ast_unparse.c */ /* _PyAST_ExprAsUnicode is defined in ast_unparse.c */
PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode(expr_ty); PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode(expr_ty);
/* Return the borrowed reference to the first literal string in the
sequence of statemnts or NULL if it doesn't start from a literal string.
Doesn't set exception. */
PyAPI_FUNC(PyObject *) _PyAST_GetDocString(asdl_seq *);
#endif /* !Py_LIMITED_API */ #endif /* !Py_LIMITED_API */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -5260,3 +5260,23 @@ error:
FstringParser_Dealloc(&state); FstringParser_Dealloc(&state);
return NULL; return NULL;
} }
PyObject *
_PyAST_GetDocString(asdl_seq *body)
{
if (!asdl_seq_LEN(body)) {
return NULL;
}
stmt_ty st = (stmt_ty)asdl_seq_GET(body, 0);
if (st->kind != Expr_kind) {
return NULL;
}
expr_ty e = st->v.Expr.value;
if (e->kind == Str_kind) {
return e->v.Str.s;
}
if (e->kind == Constant_kind && PyUnicode_CheckExact(e->v.Constant.value)) {
return e->v.Constant.value;
}
return NULL;
}

View File

@ -1,6 +1,8 @@
/* AST Optimizer */ /* AST Optimizer */
#include "Python.h" #include "Python.h"
#include "Python-ast.h" #include "Python-ast.h"
#include "node.h"
#include "ast.h"
/* TODO: is_const and get_const_value are copied from Python/compile.c. /* TODO: is_const and get_const_value are copied from Python/compile.c.
@ -467,37 +469,19 @@ static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int opti
} \ } \
} }
static int
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 static int
astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_) astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
{ {
if (!asdl_seq_LEN(stmts)) { int docstring = _PyAST_GetDocString(stmts) != NULL;
return 1;
}
int docstring = isdocstring((stmt_ty)asdl_seq_GET(stmts, 0));
CALL_SEQ(astfold_stmt, stmt_ty, stmts); CALL_SEQ(astfold_stmt, stmt_ty, stmts);
if (docstring) { if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
return 1; stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
}
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
if (isdocstring(st)) {
asdl_seq *values = _Py_asdl_seq_new(1, ctx_); asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
if (!values) { if (!values) {
return 0; return 0;
} }
asdl_seq_SET(values, 0, st->v.Expr.value); asdl_seq_SET(values, 0, st->v.Expr.value);
expr_ty expr = _Py_JoinedStr(values, st->lineno, st->col_offset, ctx_); expr_ty expr = JoinedStr(values, st->lineno, st->col_offset, ctx_);
if (!expr) { if (!expr) {
return 0; return 0;
} }

View File

@ -1392,18 +1392,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 static int
is_const(expr_ty e) is_const(expr_ty e)
{ {
@ -1603,6 +1591,7 @@ compiler_body(struct compiler *c, asdl_seq *stmts)
{ {
int i = 0; int i = 0;
stmt_ty st; stmt_ty st;
PyObject *docstring;
/* Set current line number to the line number of first statement. /* Set current line number to the line number of first statement.
This way line number for SETUP_ANNOTATIONS will always This way line number for SETUP_ANNOTATIONS will always
@ -1619,14 +1608,17 @@ compiler_body(struct compiler *c, asdl_seq *stmts)
} }
if (!asdl_seq_LEN(stmts)) if (!asdl_seq_LEN(stmts))
return 1; return 1;
st = (stmt_ty)asdl_seq_GET(stmts, 0);
/* if not -OO mode, set docstring */ /* if not -OO mode, set docstring */
if (compiler_isdocstring(st) && c->c_optimize < 2) { if (c->c_optimize < 2) {
/* don't generate docstrings if -OO */ docstring = _PyAST_GetDocString(stmts);
i = 1; if (docstring) {
VISIT(c, expr, st->v.Expr.value); i = 1;
if (!compiler_nameop(c, __doc__, Store)) st = (stmt_ty)asdl_seq_GET(stmts, 0);
return 0; assert(st->kind == Expr_kind);
VISIT(c, expr, st->v.Expr.value);
if (!compiler_nameop(c, __doc__, Store))
return 0;
}
} }
for (; i < asdl_seq_LEN(stmts); i++) for (; i < asdl_seq_LEN(stmts); i++)
VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i)); VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i));
@ -1979,15 +1971,13 @@ static int
compiler_function(struct compiler *c, stmt_ty s, int is_async) compiler_function(struct compiler *c, stmt_ty s, int is_async)
{ {
PyCodeObject *co; PyCodeObject *co;
PyObject *qualname, *first_const = Py_None; PyObject *qualname, *docstring = NULL;
arguments_ty args; arguments_ty args;
expr_ty returns; expr_ty returns;
identifier name; identifier name;
asdl_seq* decos; asdl_seq* decos;
asdl_seq *body; asdl_seq *body;
stmt_ty st;
Py_ssize_t i, funcflags; Py_ssize_t i, funcflags;
int docstring;
int annotations; int annotations;
int scope_type; int scope_type;
@ -2034,15 +2024,10 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
} }
/* if not -OO mode, add docstring */ /* if not -OO mode, add docstring */
st = (stmt_ty)asdl_seq_GET(body, 0); if (c->c_optimize < 2) {
docstring = compiler_isdocstring(st); docstring = _PyAST_GetDocString(body);
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_const(c, first_const) < 0) { if (compiler_add_const(c, docstring ? docstring : Py_None) < 0) {
compiler_exit_scope(c); compiler_exit_scope(c);
return 0; return 0;
} }

View File

@ -5,6 +5,7 @@
#include "graminit.h" #include "graminit.h"
#include "code.h" #include "code.h"
#include "symtable.h" #include "symtable.h"
#include "ast.h"
#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined" #define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
#define ERR_LATE_FUTURE \ #define ERR_LATE_FUTURE \
@ -63,7 +64,6 @@ static int
future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename) future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
{ {
int i, done = 0, prev_line = 0; int i, done = 0, prev_line = 0;
stmt_ty first;
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
return 1; return 1;
@ -80,11 +80,7 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
*/ */
i = 0; i = 0;
first = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); if (_PyAST_GetDocString(mod->v.Module.body) != NULL)
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++; i++;
for (; i < asdl_seq_LEN(mod->v.Module.body); i++) { for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {