Skip to content

Commit cb41b27

Browse files
methanevstinner
authored andcommitted
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
1 parent 1bc1564 commit cb41b27

File tree

15 files changed

+3150
-3045
lines changed

15 files changed

+3150
-3045
lines changed

Doc/library/ast.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,17 @@ and classes for traversing abstract syntax trees:
133133
.. function:: get_docstring(node, clean=True)
134134

135135
Return the docstring of the given *node* (which must be a
136-
:class:`FunctionDef`, :class:`ClassDef` or :class:`Module` node), or ``None``
137-
if it has no docstring. If *clean* is true, clean up the docstring's
138-
indentation with :func:`inspect.cleandoc`.
136+
:class:`FunctionDef`, :class:`AsyncFunctionDef`, :class:`ClassDef`,
137+
or :class:`Module` node), or ``None`` if it has no docstring.
138+
If *clean* is true, clean up the docstring's indentation with
139+
:func:`inspect.cleandoc`.
140+
141+
.. versionchanged:: 3.5
142+
:class:`AsyncFunctionDef` is now supported.
143+
144+
.. versionchanged:: 3.7
145+
The docstring is now exported from the node docstring field, instead of
146+
the first body statement.
139147

140148

141149
.. function:: fix_missing_locations(node)

Doc/whatsnew/3.7.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@ Changes in the Python API
196196
Use the :meth:`~http.cookies.Morsel.set` method for setting them.
197197
(Contributed by Serhiy Storchaka in :issue:`29192`.)
198198

199+
* ``Module``, ``FunctionDef``, ``AsyncFunctionDef``, and
200+
``ClassDef`` AST nodes now have a new ``docstring`` field.
201+
The first statement in their body is not considered as a docstring
202+
anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class
203+
and module are affected by this change.
204+
(Contributed by INADA Naoki and Eugene Toder in :issue:`29463`.)
199205

200206
CPython bytecode changes
201207
------------------------

Include/Python-ast.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct _mod {
4646
union {
4747
struct {
4848
asdl_seq *body;
49+
string docstring;
4950
} Module;
5051

5152
struct {
@@ -80,6 +81,7 @@ struct _stmt {
8081
asdl_seq *body;
8182
asdl_seq *decorator_list;
8283
expr_ty returns;
84+
string docstring;
8385
} FunctionDef;
8486

8587
struct {
@@ -88,6 +90,7 @@ struct _stmt {
8890
asdl_seq *body;
8991
asdl_seq *decorator_list;
9092
expr_ty returns;
93+
string docstring;
9194
} AsyncFunctionDef;
9295

9396
struct {
@@ -96,6 +99,7 @@ struct _stmt {
9699
asdl_seq *keywords;
97100
asdl_seq *body;
98101
asdl_seq *decorator_list;
102+
string docstring;
99103
} ClassDef;
100104

101105
struct {
@@ -439,26 +443,27 @@ struct _withitem {
439443
};
440444

441445

442-
#define Module(a0, a1) _Py_Module(a0, a1)
443-
mod_ty _Py_Module(asdl_seq * body, PyArena *arena);
446+
#define Module(a0, a1, a2) _Py_Module(a0, a1, a2)
447+
mod_ty _Py_Module(asdl_seq * body, string docstring, PyArena *arena);
444448
#define Interactive(a0, a1) _Py_Interactive(a0, a1)
445449
mod_ty _Py_Interactive(asdl_seq * body, PyArena *arena);
446450
#define Expression(a0, a1) _Py_Expression(a0, a1)
447451
mod_ty _Py_Expression(expr_ty body, PyArena *arena);
448452
#define Suite(a0, a1) _Py_Suite(a0, a1)
449453
mod_ty _Py_Suite(asdl_seq * body, PyArena *arena);
450-
#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7)
454+
#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8)
451455
stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body,
452-
asdl_seq * decorator_list, expr_ty returns, int lineno,
453-
int col_offset, PyArena *arena);
454-
#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7)
456+
asdl_seq * decorator_list, expr_ty returns, string
457+
docstring, int lineno, int col_offset, PyArena *arena);
458+
#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8)
455459
stmt_ty _Py_AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq *
456460
body, asdl_seq * decorator_list, expr_ty returns,
457-
int lineno, int col_offset, PyArena *arena);
458-
#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7)
461+
string docstring, int lineno, int col_offset,
462+
PyArena *arena);
463+
#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8)
459464
stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords,
460-
asdl_seq * body, asdl_seq * decorator_list, int lineno,
461-
int col_offset, PyArena *arena);
465+
asdl_seq * body, asdl_seq * decorator_list, string
466+
docstring, int lineno, int col_offset, PyArena *arena);
462467
#define Return(a0, a1, a2, a3) _Py_Return(a0, a1, a2, a3)
463468
stmt_ty _Py_Return(expr_ty value, int lineno, int col_offset, PyArena *arena);
464469
#define Delete(a0, a1, a2, a3) _Py_Delete(a0, a1, a2, a3)

Lib/ast.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,7 @@ def get_docstring(node, clean=True):
197197
"""
198198
if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)):
199199
raise TypeError("%r can't have docstrings" % node.__class__.__name__)
200-
if not(node.body and isinstance(node.body[0], Expr)):
201-
return
202-
node = node.body[0].value
203-
if isinstance(node, Str):
204-
text = node.s
205-
elif isinstance(node, Constant) and isinstance(node.value, str):
206-
text = node.value
207-
else:
208-
return
200+
text = node.docstring
209201
if clean:
210202
import inspect
211203
text = inspect.cleandoc(text)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy