bpo-32911: Revert bpo-29463. (GH-7121) (GH-7197)

Remove the docstring attribute of AST types and restore docstring
expression as a first stmt in their body.

Co-authored-by: INADA Naoki <methane@users.noreply.github.com>
This commit is contained in:
Serhiy Storchaka 2018-05-29 12:04:55 +03:00 committed by GitHub
parent 2179022d94
commit 73cbe7a01a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 3287 additions and 3358 deletions

View File

@ -151,10 +151,6 @@ and classes for traversing abstract syntax trees:
.. versionchanged:: 3.5 .. versionchanged:: 3.5
:class:`AsyncFunctionDef` is now supported. :class:`AsyncFunctionDef` is now supported.
.. versionchanged:: 3.7
The docstring is now exported from the node docstring field, instead of
the first body statement.
.. function:: fix_missing_locations(node) .. function:: fix_missing_locations(node)

View File

@ -2161,13 +2161,6 @@ Changes in Python Behavior
Changes in the Python API Changes in the Python API
------------------------- -------------------------
* ``Module``, ``FunctionDef``, ``AsyncFunctionDef``, and
``ClassDef`` AST nodes now have the new ``docstring`` attribute.
The first statement in their body is not considered as a docstring
anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class
and module are affected by this change. (Contributed by INADA Naoki and
Eugene Toder in :issue:`29463`.)
* :meth:`socketserver.ThreadingMixIn.server_close` now waits until all * :meth:`socketserver.ThreadingMixIn.server_close` now waits until all
non-daemon threads complete. Set the new non-daemon threads complete. Set the new
:attr:`socketserver.ThreadingMixIn.block_on_close` class attribute to :attr:`socketserver.ThreadingMixIn.block_on_close` class attribute to

View File

@ -46,7 +46,6 @@ struct _mod {
union { union {
struct { struct {
asdl_seq *body; asdl_seq *body;
string docstring;
} Module; } Module;
struct { struct {
@ -81,7 +80,6 @@ struct _stmt {
asdl_seq *body; asdl_seq *body;
asdl_seq *decorator_list; asdl_seq *decorator_list;
expr_ty returns; expr_ty returns;
string docstring;
} FunctionDef; } FunctionDef;
struct { struct {
@ -90,7 +88,6 @@ struct _stmt {
asdl_seq *body; asdl_seq *body;
asdl_seq *decorator_list; asdl_seq *decorator_list;
expr_ty returns; expr_ty returns;
string docstring;
} AsyncFunctionDef; } AsyncFunctionDef;
struct { struct {
@ -99,7 +96,6 @@ struct _stmt {
asdl_seq *keywords; asdl_seq *keywords;
asdl_seq *body; asdl_seq *body;
asdl_seq *decorator_list; asdl_seq *decorator_list;
string docstring;
} ClassDef; } ClassDef;
struct { struct {
@ -443,27 +439,26 @@ struct _withitem {
}; };
#define Module(a0, a1, a2) _Py_Module(a0, a1, a2) #define Module(a0, a1) _Py_Module(a0, a1)
mod_ty _Py_Module(asdl_seq * body, string docstring, PyArena *arena); mod_ty _Py_Module(asdl_seq * body, PyArena *arena);
#define Interactive(a0, a1) _Py_Interactive(a0, a1) #define Interactive(a0, a1) _Py_Interactive(a0, a1)
mod_ty _Py_Interactive(asdl_seq * body, PyArena *arena); mod_ty _Py_Interactive(asdl_seq * body, PyArena *arena);
#define Expression(a0, a1) _Py_Expression(a0, a1) #define Expression(a0, a1) _Py_Expression(a0, a1)
mod_ty _Py_Expression(expr_ty body, PyArena *arena); mod_ty _Py_Expression(expr_ty body, PyArena *arena);
#define Suite(a0, a1) _Py_Suite(a0, a1) #define Suite(a0, a1) _Py_Suite(a0, a1)
mod_ty _Py_Suite(asdl_seq * body, PyArena *arena); mod_ty _Py_Suite(asdl_seq * body, PyArena *arena);
#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) #define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7)
stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body, stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body,
asdl_seq * decorator_list, expr_ty returns, string asdl_seq * decorator_list, expr_ty returns, int lineno,
docstring, int lineno, int col_offset, PyArena *arena); int col_offset, PyArena *arena);
#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) #define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7)
stmt_ty _Py_AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * stmt_ty _Py_AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq *
body, asdl_seq * decorator_list, expr_ty returns, body, asdl_seq * decorator_list, expr_ty returns,
string docstring, int lineno, int col_offset, int lineno, int col_offset, PyArena *arena);
PyArena *arena); #define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7)
#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8)
stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords,
asdl_seq * body, asdl_seq * decorator_list, string asdl_seq * body, asdl_seq * decorator_list, int lineno,
docstring, int lineno, int col_offset, PyArena *arena); int col_offset, PyArena *arena);
#define Return(a0, a1, a2, a3) _Py_Return(a0, a1, a2, a3) #define Return(a0, a1, a2, a3) _Py_Return(a0, a1, a2, a3)
stmt_ty _Py_Return(expr_ty value, int lineno, int col_offset, PyArena *arena); stmt_ty _Py_Return(expr_ty value, int lineno, int col_offset, PyArena *arena);
#define Delete(a0, a1, a2, a3) _Py_Delete(a0, a1, a2, a3) #define Delete(a0, a1, a2, a3) _Py_Delete(a0, a1, a2, a3)

View File

@ -206,7 +206,15 @@ def get_docstring(node, clean=True):
""" """
if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)): if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)):
raise TypeError("%r can't have docstrings" % node.__class__.__name__) raise TypeError("%r can't have docstrings" % node.__class__.__name__)
text = node.docstring if not node.body:
return None
node = node.body[0].value
if isinstance(node, Str):
text = node.s
elif isinstance(node, Constant) and isinstance(node.value, str):
text = node.value
else:
return None
if clean and text: if clean and text:
import inspect import inspect
text = inspect.cleandoc(text) text = inspect.cleandoc(text)

View File

@ -327,24 +327,9 @@ class AST_Tests(unittest.TestCase):
def test_module(self): def test_module(self):
body = [ast.Num(42)] body = [ast.Num(42)]
x = ast.Module(body, None) x = ast.Module(body)
self.assertEqual(x.body, body) self.assertEqual(x.body, body)
def test_docstring(self):
body = [] # AST nodes having docstring must accept empty body
x = ast.Module(body, "module docstring")
self.assertEqual(x.docstring, "module docstring")
a = ast.arguments()
x = ast.FunctionDef("x", a, body, [], None, "func docstring")
self.assertEqual(x.docstring, "func docstring")
x = ast.AsyncFunctionDef("x", a, body, [], None, "async func docstring")
self.assertEqual(x.docstring, "async func docstring")
x = ast.ClassDef("x", [], [], body, [], "class docstring")
self.assertEqual(x.docstring, "class docstring")
def test_nodeclasses(self): def test_nodeclasses(self):
# Zero arguments constructor explicitly allowed # Zero arguments constructor explicitly allowed
x = ast.BinOp() x = ast.BinOp()
@ -411,13 +396,13 @@ class AST_Tests(unittest.TestCase):
def test_invalid_sum(self): def test_invalid_sum(self):
pos = dict(lineno=2, col_offset=3) pos = dict(lineno=2, col_offset=3)
m = ast.Module([ast.Expr(ast.expr(**pos), **pos)], "doc") m = ast.Module([ast.Expr(ast.expr(**pos), **pos)])
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
compile(m, "<test>", "exec") compile(m, "<test>", "exec")
self.assertIn("but got <_ast.expr", str(cm.exception)) self.assertIn("but got <_ast.expr", str(cm.exception))
def test_invalid_identitifer(self): def test_invalid_identitifer(self):
m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))], None) m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))])
ast.fix_missing_locations(m) ast.fix_missing_locations(m)
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
compile(m, "<test>", "exec") compile(m, "<test>", "exec")
@ -462,18 +447,18 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(ast.dump(node), self.assertEqual(ast.dump(node),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), " "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), "
"args=[Name(id='eggs', ctx=Load()), Str(s='and cheese')], " "args=[Name(id='eggs', ctx=Load()), Str(s='and cheese')], "
"keywords=[]))], docstring=None)" "keywords=[]))])"
) )
self.assertEqual(ast.dump(node, annotate_fields=False), self.assertEqual(ast.dump(node, annotate_fields=False),
"Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), " "Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), "
"Str('and cheese')], []))], None)" "Str('and cheese')], []))])"
) )
self.assertEqual(ast.dump(node, include_attributes=True), self.assertEqual(ast.dump(node, include_attributes=True),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), " "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), "
"lineno=1, col_offset=0), args=[Name(id='eggs', ctx=Load(), " "lineno=1, col_offset=0), args=[Name(id='eggs', ctx=Load(), "
"lineno=1, col_offset=5), Str(s='and cheese', lineno=1, " "lineno=1, col_offset=5), Str(s='and cheese', lineno=1, "
"col_offset=11)], keywords=[], " "col_offset=11)], keywords=[], "
"lineno=1, col_offset=0), lineno=1, col_offset=0)], docstring=None)" "lineno=1, col_offset=0), lineno=1, col_offset=0)])"
) )
def test_copy_location(self): def test_copy_location(self):
@ -498,7 +483,7 @@ class ASTHelpers_Test(unittest.TestCase):
"Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, " "Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, "
"col_offset=0), args=[Str(s='eggs', lineno=1, col_offset=0)], " "col_offset=0), args=[Str(s='eggs', lineno=1, col_offset=0)], "
"keywords=[], lineno=1, " "keywords=[], lineno=1, "
"col_offset=0), lineno=1, col_offset=0)], docstring=None)" "col_offset=0), lineno=1, col_offset=0)])"
) )
def test_increment_lineno(self): def test_increment_lineno(self):
@ -589,7 +574,7 @@ class ASTHelpers_Test(unittest.TestCase):
names=[ast.alias(name='sleep')], names=[ast.alias(name='sleep')],
level=None, level=None,
lineno=None, col_offset=None)] lineno=None, col_offset=None)]
mod = ast.Module(body, None) mod = ast.Module(body)
with self.assertRaises(ValueError) as cm: with self.assertRaises(ValueError) as cm:
compile(mod, 'test', 'exec') compile(mod, 'test', 'exec')
self.assertIn("invalid integer value: None", str(cm.exception)) self.assertIn("invalid integer value: None", str(cm.exception))
@ -599,7 +584,7 @@ class ASTHelpers_Test(unittest.TestCase):
names=[ast.alias(name='sleep')], names=[ast.alias(name='sleep')],
level=None, level=None,
lineno=0, col_offset=0)] lineno=0, col_offset=0)]
mod = ast.Module(body, None) mod = ast.Module(body)
code = compile(mod, 'test', 'exec') code = compile(mod, 'test', 'exec')
ns = {} ns = {}
exec(code, ns) exec(code, ns)
@ -617,11 +602,11 @@ class ASTValidatorTests(unittest.TestCase):
self.assertIn(msg, str(cm.exception)) self.assertIn(msg, str(cm.exception))
def expr(self, node, msg=None, *, exc=ValueError): def expr(self, node, msg=None, *, exc=ValueError):
mod = ast.Module([ast.Expr(node)], None) mod = ast.Module([ast.Expr(node)])
self.mod(mod, msg, exc=exc) self.mod(mod, msg, exc=exc)
def stmt(self, stmt, msg=None): def stmt(self, stmt, msg=None):
mod = ast.Module([stmt], None) mod = ast.Module([stmt])
self.mod(mod, msg) self.mod(mod, msg)
def test_module(self): def test_module(self):
@ -663,16 +648,16 @@ class ASTValidatorTests(unittest.TestCase):
def test_funcdef(self): def test_funcdef(self):
a = ast.arguments([], None, [], [], None, []) a = ast.arguments([], None, [], [], None, [])
f = ast.FunctionDef("x", a, [], [], None, None) f = ast.FunctionDef("x", a, [], [], None)
self.stmt(f, "empty body on FunctionDef") self.stmt(f, "empty body on FunctionDef")
f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())], f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())],
None, None) None)
self.stmt(f, "must have Load context") self.stmt(f, "must have Load context")
f = ast.FunctionDef("x", a, [ast.Pass()], [], f = ast.FunctionDef("x", a, [ast.Pass()], [],
ast.Name("x", ast.Store()), None) ast.Name("x", ast.Store()))
self.stmt(f, "must have Load context") self.stmt(f, "must have Load context")
def fac(args): def fac(args):
return ast.FunctionDef("x", args, [ast.Pass()], [], None, None) return ast.FunctionDef("x", args, [ast.Pass()], [], None)
self._check_arguments(fac, self.stmt) self._check_arguments(fac, self.stmt)
def test_classdef(self): def test_classdef(self):
@ -686,7 +671,7 @@ class ASTValidatorTests(unittest.TestCase):
if decorator_list is None: if decorator_list is None:
decorator_list = [] decorator_list = []
return ast.ClassDef("myclass", bases, keywords, return ast.ClassDef("myclass", bases, keywords,
body, decorator_list, None) body, decorator_list)
self.stmt(cls(bases=[ast.Name("x", ast.Store())]), self.stmt(cls(bases=[ast.Name("x", ast.Store())]),
"must have Load context") "must have Load context")
self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]), self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]),
@ -1124,53 +1109,53 @@ def main():
#### EVERYTHING BELOW IS GENERATED ##### #### EVERYTHING BELOW IS GENERATED #####
exec_results = [ exec_results = [
('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))], None), ('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))]),
('Module', [], 'module docstring'), ('Module', [('Expr', (1, 0), ('Str', (1, 0), 'module docstring'))]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None, None)], None), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [], [], None, 'function docstring')], None), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (1, 9), ('Str', (1, 9), 'function docstring'))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, []), [('Pass', (1, 10))], [], None, None)], None), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, []), [('Pass', (1, 10))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None, None)], None), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None, None)], None), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None, None)], None), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [], [], None, 'doc for f()')], None), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Expr', (1, 58), ('Str', (1, 58), 'doc for f()'))], [], None)]),
('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [], None)], None), ('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])]),
('Module', [('ClassDef', (1, 0), 'C', [], [], [], [], 'docstring for class C')], None), ('Module', [('ClassDef', (1, 0), 'C', [], [], [('Expr', (1, 9), ('Str', (1, 9), 'docstring for class C'))], [])]),
('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [], None)], None), ('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [])]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None, None)], None), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]),
('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])], None), ('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]),
('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))], None), ('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]),
('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))], None), ('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))]),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])], None), ('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])]),
('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])], None), ('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]),
('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])], None), ('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])], None), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])]),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])], None), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])]),
('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)], None), ('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)]),
('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])], None), ('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])]),
('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])], None), ('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])]),
('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)], None), ('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]),
('Module', [('Import', (1, 0), [('alias', 'sys', None)])], None), ('Module', [('Import', (1, 0), [('alias', 'sys', None)])]),
('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)], None), ('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)]),
('Module', [('Global', (1, 0), ['v'])], None), ('Module', [('Global', (1, 0), ['v'])]),
('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))], None), ('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))]),
('Module', [('Pass', (1, 0))], None), ('Module', [('Pass', (1, 0))]),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [])], None), ('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [])]),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [])], None), ('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [])]),
('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [])], None), ('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [])]),
('Module', [('Expr', (1, 0), ('ListComp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))], None), ('Module', [('Expr', (1, 0), ('ListComp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))]),
('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))], None), ('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))]),
('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 12), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)]))], None), ('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 12), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)]))]),
('Module', [('Expr', (1, 0), ('GeneratorExp', (2, 4), ('Tuple', (3, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [], 0)]))], None), ('Module', [('Expr', (1, 0), ('GeneratorExp', (2, 4), ('Tuple', (3, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [], 0)]))]),
('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))], 0)]))], None), ('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))], 0)]))]),
('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))], None), ('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))]),
('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))], None), ('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))]),
('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))], None), ('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))]),
('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None, 'async function')], None), ('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('Str', (2, 1), 'async function')), ('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None)]),
('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 7), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Num', (2, 19), 1))], [('Expr', (3, 7), ('Num', (3, 7), 2))])], [], None, None)], None), ('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 7), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Num', (2, 19), 1))], [('Expr', (3, 7), ('Num', (3, 7), 2))])], [], None)]),
('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 7), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Num', (2, 20), 1))])], [], None, None)], None), ('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 7), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Num', (2, 20), 1))])], [], None)]),
('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Num', (1, 10), 2)], [('Dict', (1, 3), [('Num', (1, 4), 1)], [('Num', (1, 6), 2)]), ('Num', (1, 12), 3)]))], None), ('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Num', (1, 10), 2)], [('Dict', (1, 3), [('Num', (1, 4), 1)], [('Num', (1, 6), 2)]), ('Num', (1, 12), 3)]))]),
('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Num', (1, 3), 1), ('Num', (1, 6), 2)]), ('Load',)), ('Num', (1, 10), 3)]))], None), ('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Num', (1, 3), 1), ('Num', (1, 6), 2)]), ('Load',)), ('Num', (1, 10), 3)]))]),
('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 2), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None, None)], None), ('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 2), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None)]),
] ]
single_results = [ single_results = [
('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]), ('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]),

View File

@ -27,7 +27,7 @@ class OpcodeTest(unittest.TestCase):
with open(ann_module.__file__) as f: with open(ann_module.__file__) as f:
txt = f.read() txt = f.read()
co = compile(txt, ann_module.__file__, 'exec') co = compile(txt, ann_module.__file__, 'exec')
self.assertEqual(co.co_firstlineno, 8) self.assertEqual(co.co_firstlineno, 6)
except OSError: except OSError:
pass pass

View File

@ -788,7 +788,7 @@ objects.
Add ``docstring`` field to Module, ClassDef, FunctionDef, and Add ``docstring`` field to Module, ClassDef, FunctionDef, and
AsyncFunctionDef ast nodes. docstring is not first stmt in their body AsyncFunctionDef ast nodes. docstring is not first stmt in their body
anymore. It affects ``co_firstlineno`` and ``co_lnotab`` of code object for anymore. It affects ``co_firstlineno`` and ``co_lnotab`` of code object for
module and class. module and class. (Reverted in :issue:`32911`.)
.. ..

View File

@ -0,0 +1,5 @@
Due to unexpected compatibility issues discovered during downstream beta
testing, reverted :issue:`29463`. ``docstring`` field is removed from Module,
ClassDef, FunctionDef, and AsyncFunctionDef ast nodes which was added in
3.7a1. Docstring expression is restored as a first statement in their body.
Based on patch by Inada Naoki.

View File

@ -6,7 +6,7 @@
module Python module Python
{ {
mod = Module(stmt* body, string? docstring) mod = Module(stmt* body)
| Interactive(stmt* body) | Interactive(stmt* body)
| Expression(expr body) | Expression(expr body)
@ -14,18 +14,15 @@ module Python
| Suite(stmt* body) | Suite(stmt* body)
stmt = FunctionDef(identifier name, arguments args, stmt = FunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns, stmt* body, expr* decorator_list, expr? returns)
string? docstring)
| AsyncFunctionDef(identifier name, arguments args, | AsyncFunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns, stmt* body, expr* decorator_list, expr? returns)
string? docstring)
| ClassDef(identifier name, | ClassDef(identifier name,
expr* bases, expr* bases,
keyword* keywords, keyword* keywords,
stmt* body, stmt* body,
expr* decorator_list, expr* decorator_list)
string? docstring)
| Return(expr? value) | Return(expr? value)
| Delete(expr* targets) | Delete(expr* targets)

View File

@ -10,10 +10,8 @@ static PyTypeObject *mod_type;
static PyObject* ast2obj_mod(void*); static PyObject* ast2obj_mod(void*);
static PyTypeObject *Module_type; static PyTypeObject *Module_type;
_Py_IDENTIFIER(body); _Py_IDENTIFIER(body);
_Py_IDENTIFIER(docstring);
static char *Module_fields[]={ static char *Module_fields[]={
"body", "body",
"docstring",
}; };
static PyTypeObject *Interactive_type; static PyTypeObject *Interactive_type;
static char *Interactive_fields[]={ static char *Interactive_fields[]={
@ -46,7 +44,6 @@ static char *FunctionDef_fields[]={
"body", "body",
"decorator_list", "decorator_list",
"returns", "returns",
"docstring",
}; };
static PyTypeObject *AsyncFunctionDef_type; static PyTypeObject *AsyncFunctionDef_type;
static char *AsyncFunctionDef_fields[]={ static char *AsyncFunctionDef_fields[]={
@ -55,7 +52,6 @@ static char *AsyncFunctionDef_fields[]={
"body", "body",
"decorator_list", "decorator_list",
"returns", "returns",
"docstring",
}; };
static PyTypeObject *ClassDef_type; static PyTypeObject *ClassDef_type;
_Py_IDENTIFIER(bases); _Py_IDENTIFIER(bases);
@ -66,7 +62,6 @@ static char *ClassDef_fields[]={
"keywords", "keywords",
"body", "body",
"decorator_list", "decorator_list",
"docstring",
}; };
static PyTypeObject *Return_type; static PyTypeObject *Return_type;
_Py_IDENTIFIER(value); _Py_IDENTIFIER(value);
@ -847,7 +842,7 @@ static int init_types(void)
mod_type = make_type("mod", &AST_type, NULL, 0); mod_type = make_type("mod", &AST_type, NULL, 0);
if (!mod_type) return 0; if (!mod_type) return 0;
if (!add_attributes(mod_type, NULL, 0)) return 0; if (!add_attributes(mod_type, NULL, 0)) return 0;
Module_type = make_type("Module", mod_type, Module_fields, 2); Module_type = make_type("Module", mod_type, Module_fields, 1);
if (!Module_type) return 0; if (!Module_type) return 0;
Interactive_type = make_type("Interactive", mod_type, Interactive_fields, Interactive_type = make_type("Interactive", mod_type, Interactive_fields,
1); 1);
@ -860,12 +855,12 @@ static int init_types(void)
if (!stmt_type) return 0; if (!stmt_type) return 0;
if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0; if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0;
FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields, FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields,
6); 5);
if (!FunctionDef_type) return 0; if (!FunctionDef_type) return 0;
AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type, AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type,
AsyncFunctionDef_fields, 6); AsyncFunctionDef_fields, 5);
if (!AsyncFunctionDef_type) return 0; if (!AsyncFunctionDef_type) return 0;
ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 6); ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 5);
if (!ClassDef_type) return 0; if (!ClassDef_type) return 0;
Return_type = make_type("Return", stmt_type, Return_fields, 1); Return_type = make_type("Return", stmt_type, Return_fields, 1);
if (!Return_type) return 0; if (!Return_type) return 0;
@ -1192,7 +1187,7 @@ static int obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena);
static int obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena); static int obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena);
mod_ty mod_ty
Module(asdl_seq * body, string docstring, PyArena *arena) Module(asdl_seq * body, PyArena *arena)
{ {
mod_ty p; mod_ty p;
p = (mod_ty)PyArena_Malloc(arena, sizeof(*p)); p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
@ -1200,7 +1195,6 @@ Module(asdl_seq * body, string docstring, PyArena *arena)
return NULL; return NULL;
p->kind = Module_kind; p->kind = Module_kind;
p->v.Module.body = body; p->v.Module.body = body;
p->v.Module.docstring = docstring;
return p; return p;
} }
@ -1247,8 +1241,8 @@ Suite(asdl_seq * body, PyArena *arena)
stmt_ty stmt_ty
FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
decorator_list, expr_ty returns, string docstring, int lineno, int decorator_list, expr_ty returns, int lineno, int col_offset,
col_offset, PyArena *arena) PyArena *arena)
{ {
stmt_ty p; stmt_ty p;
if (!name) { if (!name) {
@ -1270,7 +1264,6 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
p->v.FunctionDef.body = body; p->v.FunctionDef.body = body;
p->v.FunctionDef.decorator_list = decorator_list; p->v.FunctionDef.decorator_list = decorator_list;
p->v.FunctionDef.returns = returns; p->v.FunctionDef.returns = returns;
p->v.FunctionDef.docstring = docstring;
p->lineno = lineno; p->lineno = lineno;
p->col_offset = col_offset; p->col_offset = col_offset;
return p; return p;
@ -1278,8 +1271,8 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
stmt_ty stmt_ty
AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
* decorator_list, expr_ty returns, string docstring, int * decorator_list, expr_ty returns, int lineno, int col_offset,
lineno, int col_offset, PyArena *arena) PyArena *arena)
{ {
stmt_ty p; stmt_ty p;
if (!name) { if (!name) {
@ -1301,7 +1294,6 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
p->v.AsyncFunctionDef.body = body; p->v.AsyncFunctionDef.body = body;
p->v.AsyncFunctionDef.decorator_list = decorator_list; p->v.AsyncFunctionDef.decorator_list = decorator_list;
p->v.AsyncFunctionDef.returns = returns; p->v.AsyncFunctionDef.returns = returns;
p->v.AsyncFunctionDef.docstring = docstring;
p->lineno = lineno; p->lineno = lineno;
p->col_offset = col_offset; p->col_offset = col_offset;
return p; return p;
@ -1309,8 +1301,8 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
stmt_ty stmt_ty
ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq * ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq *
body, asdl_seq * decorator_list, string docstring, int lineno, int body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena
col_offset, PyArena *arena) *arena)
{ {
stmt_ty p; stmt_ty p;
if (!name) { if (!name) {
@ -1327,7 +1319,6 @@ ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq *
p->v.ClassDef.keywords = keywords; p->v.ClassDef.keywords = keywords;
p->v.ClassDef.body = body; p->v.ClassDef.body = body;
p->v.ClassDef.decorator_list = decorator_list; p->v.ClassDef.decorator_list = decorator_list;
p->v.ClassDef.docstring = docstring;
p->lineno = lineno; p->lineno = lineno;
p->col_offset = col_offset; p->col_offset = col_offset;
return p; return p;
@ -2591,11 +2582,6 @@ ast2obj_mod(void* _o)
if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
goto failed; goto failed;
Py_DECREF(value); 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; break;
case Interactive_kind: case Interactive_kind:
result = PyType_GenericNew(Interactive_type, NULL, NULL); result = PyType_GenericNew(Interactive_type, NULL, NULL);
@ -2670,11 +2656,6 @@ ast2obj_stmt(void* _o)
if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1) if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1)
goto failed; goto failed;
Py_DECREF(value); 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; break;
case AsyncFunctionDef_kind: case AsyncFunctionDef_kind:
result = PyType_GenericNew(AsyncFunctionDef_type, NULL, NULL); result = PyType_GenericNew(AsyncFunctionDef_type, NULL, NULL);
@ -2705,11 +2686,6 @@ ast2obj_stmt(void* _o)
if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1) if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1)
goto failed; goto failed;
Py_DECREF(value); 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; break;
case ClassDef_kind: case ClassDef_kind:
result = PyType_GenericNew(ClassDef_type, NULL, NULL); result = PyType_GenericNew(ClassDef_type, NULL, NULL);
@ -2739,11 +2715,6 @@ ast2obj_stmt(void* _o)
if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1) if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1)
goto failed; goto failed;
Py_DECREF(value); 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; break;
case Return_kind: case Return_kind:
result = PyType_GenericNew(Return_type, NULL, NULL); result = PyType_GenericNew(Return_type, NULL, NULL);
@ -3984,7 +3955,6 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena)
} }
if (isinstance) { if (isinstance) {
asdl_seq* body; asdl_seq* body;
string docstring;
if (_PyObject_LookupAttrId(obj, &PyId_body, &tmp) < 0) { if (_PyObject_LookupAttrId(obj, &PyId_body, &tmp) < 0) {
return 1; return 1;
@ -4016,20 +3986,7 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena)
} }
Py_CLEAR(tmp); Py_CLEAR(tmp);
} }
if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { *out = Module(body, arena);
return 1;
}
if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp);
docstring = NULL;
}
else {
int res;
res = obj2ast_string(tmp, &docstring, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = Module(body, docstring, arena);
if (*out == NULL) goto failed; if (*out == NULL) goto failed;
return 0; return 0;
} }
@ -4195,7 +4152,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
asdl_seq* body; asdl_seq* body;
asdl_seq* decorator_list; asdl_seq* decorator_list;
expr_ty returns; expr_ty returns;
string docstring;
if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) {
return 1; return 1;
@ -4296,21 +4252,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed; if (res != 0) goto failed;
Py_CLEAR(tmp); Py_CLEAR(tmp);
} }
if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { *out = FunctionDef(name, args, body, decorator_list, returns, lineno,
return 1; col_offset, arena);
}
if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp);
docstring = NULL;
}
else {
int res;
res = obj2ast_string(tmp, &docstring, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = FunctionDef(name, args, body, decorator_list, returns,
docstring, lineno, col_offset, arena);
if (*out == NULL) goto failed; if (*out == NULL) goto failed;
return 0; return 0;
} }
@ -4324,7 +4267,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
asdl_seq* body; asdl_seq* body;
asdl_seq* decorator_list; asdl_seq* decorator_list;
expr_ty returns; expr_ty returns;
string docstring;
if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) {
return 1; return 1;
@ -4425,21 +4367,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed; if (res != 0) goto failed;
Py_CLEAR(tmp); Py_CLEAR(tmp);
} }
if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp);
docstring = NULL;
}
else {
int res;
res = obj2ast_string(tmp, &docstring, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = AsyncFunctionDef(name, args, body, decorator_list, returns, *out = AsyncFunctionDef(name, args, body, decorator_list, returns,
docstring, lineno, col_offset, arena); lineno, col_offset, arena);
if (*out == NULL) goto failed; if (*out == NULL) goto failed;
return 0; return 0;
} }
@ -4453,7 +4382,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
asdl_seq* keywords; asdl_seq* keywords;
asdl_seq* body; asdl_seq* body;
asdl_seq* decorator_list; asdl_seq* decorator_list;
string docstring;
if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) {
return 1; return 1;
@ -4588,21 +4516,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
} }
Py_CLEAR(tmp); Py_CLEAR(tmp);
} }
if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { *out = ClassDef(name, bases, keywords, body, decorator_list, lineno,
return 1; col_offset, arena);
}
if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp);
docstring = NULL;
}
else {
int res;
res = obj2ast_string(tmp, &docstring, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = ClassDef(name, bases, keywords, body, decorator_list, docstring,
lineno, col_offset, arena);
if (*out == NULL) goto failed; if (*out == NULL) goto failed;
return 0; return 0;
} }

View File

@ -367,12 +367,9 @@ validate_assignlist(asdl_seq *targets, expr_context_ty ctx)
} }
static int static int
validate_body(asdl_seq *body, const char *owner, int allowempty) validate_body(asdl_seq *body, const char *owner)
{ {
if (!allowempty && !validate_nonempty_seq(body, "body", owner)) { return validate_nonempty_seq(body, "body", owner) && validate_stmts(body);
return 0;
}
return validate_stmts(body);
} }
static int static int
@ -381,15 +378,13 @@ validate_stmt(stmt_ty stmt)
int i; int i;
switch (stmt->kind) { switch (stmt->kind) {
case FunctionDef_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_arguments(stmt->v.FunctionDef.args) &&
validate_exprs(stmt->v.FunctionDef.decorator_list, Load, 0) && validate_exprs(stmt->v.FunctionDef.decorator_list, Load, 0) &&
(!stmt->v.FunctionDef.returns || (!stmt->v.FunctionDef.returns ||
validate_expr(stmt->v.FunctionDef.returns, Load)); validate_expr(stmt->v.FunctionDef.returns, Load));
case ClassDef_kind: 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_exprs(stmt->v.ClassDef.bases, Load, 0) &&
validate_keywords(stmt->v.ClassDef.keywords) && validate_keywords(stmt->v.ClassDef.keywords) &&
validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0); validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0);
@ -417,20 +412,20 @@ validate_stmt(stmt_ty stmt)
case For_kind: case For_kind:
return validate_expr(stmt->v.For.target, Store) && return validate_expr(stmt->v.For.target, Store) &&
validate_expr(stmt->v.For.iter, Load) && validate_expr(stmt->v.For.iter, Load) &&
validate_body(stmt->v.For.body, "For", 0) && validate_body(stmt->v.For.body, "For") &&
validate_stmts(stmt->v.For.orelse); validate_stmts(stmt->v.For.orelse);
case AsyncFor_kind: case AsyncFor_kind:
return validate_expr(stmt->v.AsyncFor.target, Store) && return validate_expr(stmt->v.AsyncFor.target, Store) &&
validate_expr(stmt->v.AsyncFor.iter, Load) && validate_expr(stmt->v.AsyncFor.iter, Load) &&
validate_body(stmt->v.AsyncFor.body, "AsyncFor", 0) && validate_body(stmt->v.AsyncFor.body, "AsyncFor") &&
validate_stmts(stmt->v.AsyncFor.orelse); validate_stmts(stmt->v.AsyncFor.orelse);
case While_kind: case While_kind:
return validate_expr(stmt->v.While.test, Load) && return validate_expr(stmt->v.While.test, Load) &&
validate_body(stmt->v.While.body, "While", 0) && validate_body(stmt->v.While.body, "While") &&
validate_stmts(stmt->v.While.orelse); validate_stmts(stmt->v.While.orelse);
case If_kind: case If_kind:
return validate_expr(stmt->v.If.test, Load) && return validate_expr(stmt->v.If.test, Load) &&
validate_body(stmt->v.If.body, "If", 0) && validate_body(stmt->v.If.body, "If") &&
validate_stmts(stmt->v.If.orelse); validate_stmts(stmt->v.If.orelse);
case With_kind: case With_kind:
if (!validate_nonempty_seq(stmt->v.With.items, "items", "With")) if (!validate_nonempty_seq(stmt->v.With.items, "items", "With"))
@ -441,7 +436,7 @@ validate_stmt(stmt_ty stmt)
(item->optional_vars && !validate_expr(item->optional_vars, Store))) (item->optional_vars && !validate_expr(item->optional_vars, Store)))
return 0; return 0;
} }
return validate_body(stmt->v.With.body, "With", 0); return validate_body(stmt->v.With.body, "With");
case AsyncWith_kind: case AsyncWith_kind:
if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith")) if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith"))
return 0; return 0;
@ -451,7 +446,7 @@ validate_stmt(stmt_ty stmt)
(item->optional_vars && !validate_expr(item->optional_vars, Store))) (item->optional_vars && !validate_expr(item->optional_vars, Store)))
return 0; return 0;
} }
return validate_body(stmt->v.AsyncWith.body, "AsyncWith", 0); return validate_body(stmt->v.AsyncWith.body, "AsyncWith");
case Raise_kind: case Raise_kind:
if (stmt->v.Raise.exc) { if (stmt->v.Raise.exc) {
return validate_expr(stmt->v.Raise.exc, Load) && return validate_expr(stmt->v.Raise.exc, Load) &&
@ -463,7 +458,7 @@ validate_stmt(stmt_ty stmt)
} }
return 1; return 1;
case Try_kind: case Try_kind:
if (!validate_body(stmt->v.Try.body, "Try", 0)) if (!validate_body(stmt->v.Try.body, "Try"))
return 0; return 0;
if (!asdl_seq_LEN(stmt->v.Try.handlers) && if (!asdl_seq_LEN(stmt->v.Try.handlers) &&
!asdl_seq_LEN(stmt->v.Try.finalbody)) { !asdl_seq_LEN(stmt->v.Try.finalbody)) {
@ -479,7 +474,7 @@ validate_stmt(stmt_ty stmt)
excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i); excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i);
if ((handler->v.ExceptHandler.type && if ((handler->v.ExceptHandler.type &&
!validate_expr(handler->v.ExceptHandler.type, Load)) || !validate_expr(handler->v.ExceptHandler.type, Load)) ||
!validate_body(handler->v.ExceptHandler.body, "ExceptHandler", 0)) !validate_body(handler->v.ExceptHandler.body, "ExceptHandler"))
return 0; return 0;
} }
return (!asdl_seq_LEN(stmt->v.Try.finalbody) || return (!asdl_seq_LEN(stmt->v.Try.finalbody) ||
@ -504,8 +499,7 @@ validate_stmt(stmt_ty stmt)
case Expr_kind: case Expr_kind:
return validate_expr(stmt->v.Expr.value, Load); return validate_expr(stmt->v.Expr.value, Load);
case AsyncFunctionDef_kind: 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_arguments(stmt->v.AsyncFunctionDef.args) &&
validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) && validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
(!stmt->v.AsyncFunctionDef.returns || (!stmt->v.AsyncFunctionDef.returns ||
@ -600,9 +594,7 @@ struct compiling {
static asdl_seq *seq_for_testlist(struct compiling *, const node *); static asdl_seq *seq_for_testlist(struct compiling *, const node *);
static expr_ty ast_for_expr(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 stmt_ty ast_for_stmt(struct compiling *, const node *);
static asdl_seq *ast_for_body(struct compiling *c, const node *n, static asdl_seq *ast_for_suite(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 *, static asdl_seq *ast_for_exprlist(struct compiling *, const node *,
expr_context_ty); expr_context_ty);
static expr_ty ast_for_testlist(struct compiling *, const node *); static expr_ty ast_for_testlist(struct compiling *, const node *);
@ -820,7 +812,7 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
} }
} }
} }
res = Module(stmts, docstring_from_stmts(stmts), arena); res = Module(stmts, arena);
break; break;
case eval_input: { case eval_input: {
expr_ty testlist_ast; expr_ty testlist_ast;
@ -1585,7 +1577,6 @@ ast_for_funcdef_impl(struct compiling *c, const node *n,
arguments_ty args; arguments_ty args;
asdl_seq *body; asdl_seq *body;
expr_ty returns = NULL; expr_ty returns = NULL;
string docstring;
int name_i = 1; int name_i = 1;
REQ(n, funcdef); REQ(n, funcdef);
@ -1604,18 +1595,16 @@ ast_for_funcdef_impl(struct compiling *c, const node *n,
return NULL; return NULL;
name_i += 2; name_i += 2;
} }
body = ast_for_body(c, CHILD(n, name_i + 3), &docstring); body = ast_for_suite(c, CHILD(n, name_i + 3));
if (!body) if (!body)
return NULL; return NULL;
if (is_async) if (is_async)
return AsyncFunctionDef(name, args, body, decorator_seq, returns, return AsyncFunctionDef(name, args, body, decorator_seq, returns,
docstring, LINENO(n), LINENO(n), n->n_col_offset, c->c_arena);
n->n_col_offset, c->c_arena);
else else
return FunctionDef(name, args, body, decorator_seq, returns, return FunctionDef(name, args, body, decorator_seq, returns,
docstring, LINENO(n), LINENO(n), n->n_col_offset, c->c_arena);
n->n_col_offset, c->c_arena);
} }
static stmt_ty static stmt_ty
@ -3528,32 +3517,6 @@ ast_for_suite(struct compiling *c, const node *n)
return seq; 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 static stmt_ty
ast_for_if_stmt(struct compiling *c, const node *n) ast_for_if_stmt(struct compiling *c, const node *n)
{ {
@ -3938,13 +3901,12 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
/* classdef: 'class' NAME ['(' arglist ')'] ':' suite */ /* classdef: 'class' NAME ['(' arglist ')'] ':' suite */
PyObject *classname; PyObject *classname;
asdl_seq *s; asdl_seq *s;
string docstring;
expr_ty call; expr_ty call;
REQ(n, classdef); REQ(n, classdef);
if (NCH(n) == 4) { /* class NAME ':' suite */ if (NCH(n) == 4) { /* class NAME ':' suite */
s = ast_for_body(c, CHILD(n, 3), &docstring); s = ast_for_suite(c, CHILD(n, 3));
if (!s) if (!s)
return NULL; return NULL;
classname = NEW_IDENTIFIER(CHILD(n, 1)); classname = NEW_IDENTIFIER(CHILD(n, 1));
@ -3952,12 +3914,12 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
return NULL; return NULL;
if (forbidden_name(c, classname, CHILD(n, 3), 0)) if (forbidden_name(c, classname, CHILD(n, 3), 0))
return NULL; return NULL;
return ClassDef(classname, NULL, NULL, s, decorator_seq, docstring, return ClassDef(classname, NULL, NULL, s, decorator_seq,
LINENO(n), n->n_col_offset, c->c_arena); LINENO(n), n->n_col_offset, c->c_arena);
} }
if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */ if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */
s = ast_for_body(c, CHILD(n, 5), &docstring); s = ast_for_suite(c, CHILD(n, 5));
if (!s) if (!s)
return NULL; return NULL;
classname = NEW_IDENTIFIER(CHILD(n, 1)); classname = NEW_IDENTIFIER(CHILD(n, 1));
@ -3965,7 +3927,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
return NULL; return NULL;
if (forbidden_name(c, classname, CHILD(n, 3), 0)) if (forbidden_name(c, classname, CHILD(n, 3), 0))
return NULL; return NULL;
return ClassDef(classname, NULL, NULL, s, decorator_seq, docstring, return ClassDef(classname, NULL, NULL, s, decorator_seq,
LINENO(n), n->n_col_offset, c->c_arena); LINENO(n), n->n_col_offset, c->c_arena);
} }
@ -3982,7 +3944,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
if (!call) if (!call)
return NULL; return NULL;
} }
s = ast_for_body(c, CHILD(n, 6), &docstring); s = ast_for_suite(c, CHILD(n, 6));
if (!s) if (!s)
return NULL; return NULL;
classname = NEW_IDENTIFIER(CHILD(n, 1)); classname = NEW_IDENTIFIER(CHILD(n, 1));
@ -3992,8 +3954,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
return NULL; return NULL;
return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s, return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s,
decorator_seq, docstring, LINENO(n), n->n_col_offset, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena);
c->c_arena);
} }
static stmt_ty static stmt_ty

View File

@ -467,12 +467,51 @@ 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
astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
{
if (!asdl_seq_LEN(stmts)) {
return 1;
}
int docstring = isdocstring((stmt_ty)asdl_seq_GET(stmts, 0));
CALL_SEQ(astfold_stmt, stmt_ty, stmts);
if (docstring) {
return 1;
}
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
if (isdocstring(st)) {
asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
if (!values) {
return 0;
}
asdl_seq_SET(values, 0, st->v.Expr.value);
expr_ty expr = _Py_JoinedStr(values, st->lineno, st->col_offset, ctx_);
if (!expr) {
return 0;
}
st->v.Expr.value = expr;
}
return 1;
}
static int static int
astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_) astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_)
{ {
switch (node_->kind) { switch (node_->kind) {
case Module_kind: case Module_kind:
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Module.body); CALL(astfold_body, asdl_seq, node_->v.Module.body);
break; break;
case Interactive_kind: case Interactive_kind:
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body); CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
@ -657,20 +696,20 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_)
switch (node_->kind) { switch (node_->kind) {
case FunctionDef_kind: case FunctionDef_kind:
CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args); CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.FunctionDef.body); CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list); CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns); CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
break; break;
case AsyncFunctionDef_kind: case AsyncFunctionDef_kind:
CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args); CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFunctionDef.body); CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list); CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns); CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
break; break;
case ClassDef_kind: case ClassDef_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases); CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords); CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ClassDef.body); CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list); CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
break; break;
case Return_kind: case Return_kind:

View File

@ -1392,6 +1392,18 @@ 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)
{ {
@ -1587,27 +1599,37 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
and for annotations. */ and for annotations. */
static int static int
compiler_body(struct compiler *c, asdl_seq *stmts, string docstring) compiler_body(struct compiler *c, asdl_seq *stmts)
{ {
int i = 0;
stmt_ty st;
/* 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
coincide with the line number of first "real" statement in module. coincide with the line number of first "real" statement in module.
If body is empy, then lineno will be set later in assemble. */ If body is empy, then lineno will be set later in assemble. */
if (c->u->u_scope_type == COMPILER_SCOPE_MODULE && if (c->u->u_scope_type == COMPILER_SCOPE_MODULE &&
!c->u->u_lineno && asdl_seq_LEN(stmts)) { !c->u->u_lineno && asdl_seq_LEN(stmts)) {
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); st = (stmt_ty)asdl_seq_GET(stmts, 0);
c->u->u_lineno = st->lineno; c->u->u_lineno = st->lineno;
} }
/* Every annotated class and module should have __annotations__. */ /* Every annotated class and module should have __annotations__. */
if (find_ann(stmts)) { if (find_ann(stmts)) {
ADDOP(c, SETUP_ANNOTATIONS); ADDOP(c, SETUP_ANNOTATIONS);
} }
if (!asdl_seq_LEN(stmts))
return 1;
st = (stmt_ty)asdl_seq_GET(stmts, 0);
/* if not -OO mode, set docstring */ /* if not -OO mode, set docstring */
if (c->c_optimize < 2 && docstring) { if (compiler_isdocstring(st) && c->c_optimize < 2) {
ADDOP_LOAD_CONST(c, docstring); /* don't generate docstrings if -OO */
ADDOP_NAME(c, STORE_NAME, __doc__, names); i = 1;
VISIT(c, expr, st->v.Expr.value);
if (!compiler_nameop(c, __doc__, Store))
return 0;
} }
VISIT_SEQ(c, stmt, stmts); for (; i < asdl_seq_LEN(stmts); i++)
VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i));
return 1; return 1;
} }
@ -1627,7 +1649,7 @@ compiler_mod(struct compiler *c, mod_ty mod)
return NULL; return NULL;
switch (mod->kind) { switch (mod->kind) {
case Module_kind: case Module_kind:
if (!compiler_body(c, mod->v.Module.body, mod->v.Module.docstring)) { if (!compiler_body(c, mod->v.Module.body)) {
compiler_exit_scope(c); compiler_exit_scope(c);
return 0; return 0;
} }
@ -1957,13 +1979,15 @@ 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, *docstring = Py_None; PyObject *qualname, *first_const = Py_None;
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;
@ -2010,16 +2034,21 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
} }
/* if not -OO mode, add docstring */ /* if not -OO mode, add docstring */
if (c->c_optimize < 2 && s->v.FunctionDef.docstring) st = (stmt_ty)asdl_seq_GET(body, 0);
docstring = s->v.FunctionDef.docstring; docstring = compiler_isdocstring(st);
if (compiler_add_const(c, docstring) < 0) { 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) {
compiler_exit_scope(c); compiler_exit_scope(c);
return 0; return 0;
} }
c->u->u_argcount = asdl_seq_LEN(args->args); c->u->u_argcount = asdl_seq_LEN(args->args);
c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
/* if there was a docstring, we need to skip the first statement */
VISIT_SEQ_IN_SCOPE(c, stmt, body); VISIT_SEQ_IN_SCOPE(c, stmt, body);
co = assemble(c, 1); co = assemble(c, 1);
qualname = c->u->u_qualname; qualname = c->u->u_qualname;
@ -2101,7 +2130,7 @@ compiler_class(struct compiler *c, stmt_ty s)
} }
Py_DECREF(str); Py_DECREF(str);
/* compile the body proper */ /* compile the body proper */
if (!compiler_body(c, s->v.ClassDef.body, s->v.ClassDef.docstring)) { if (!compiler_body(c, s->v.ClassDef.body)) {
compiler_exit_scope(c); compiler_exit_scope(c);
return 0; return 0;
} }

View File

@ -63,6 +63,7 @@ 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;
@ -78,7 +79,15 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
but is preceded by a regular import. but is preceded by a regular import.
*/ */
for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) { 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++) {
stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
if (done && s->lineno > prev_line) if (done && s->lineno > prev_line)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -71,8 +71,6 @@ class Unparser:
######################################################## ########################################################
def _Module(self, tree): def _Module(self, tree):
if tree.docstring is not None:
self.fill(repr(tree.docstring))
for stmt in tree.body: for stmt in tree.body:
self.dispatch(stmt) self.dispatch(stmt)
@ -237,8 +235,6 @@ class Unparser:
self.write(")") self.write(")")
self.enter() self.enter()
if t.docstring is not None:
self.fill(repr(t.docstring))
self.dispatch(t.body) self.dispatch(t.body)
self.leave() self.leave()
@ -261,8 +257,6 @@ class Unparser:
self.write(" -> ") self.write(" -> ")
self.dispatch(t.returns) self.dispatch(t.returns)
self.enter() self.enter()
if t.docstring is not None:
self.fill(repr(t.docstring))
self.dispatch(t.body) self.dispatch(t.body)
self.leave() self.leave()