Commit 73cbe7a0 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

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: default avatarINADA Naoki <methane@users.noreply.github.com>
parent 2179022d
......@@ -151,10 +151,6 @@ and classes for traversing abstract syntax trees:
.. versionchanged:: 3.5
: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)
......
......@@ -2161,13 +2161,6 @@ Changes in Python Behavior
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
non-daemon threads complete. Set the new
:attr:`socketserver.ThreadingMixIn.block_on_close` class attribute to
......
......@@ -46,7 +46,6 @@ struct _mod {
union {
struct {
asdl_seq *body;
string docstring;
} Module;
struct {
......@@ -81,7 +80,6 @@ struct _stmt {
asdl_seq *body;
asdl_seq *decorator_list;
expr_ty returns;
string docstring;
} FunctionDef;
struct {
......@@ -90,7 +88,6 @@ struct _stmt {
asdl_seq *body;
asdl_seq *decorator_list;
expr_ty returns;
string docstring;
} AsyncFunctionDef;
struct {
......@@ -99,7 +96,6 @@ struct _stmt {
asdl_seq *keywords;
asdl_seq *body;
asdl_seq *decorator_list;
string docstring;
} ClassDef;
struct {
......@@ -443,27 +439,26 @@ struct _withitem {
};
#define Module(a0, a1, a2) _Py_Module(a0, a1, a2)
mod_ty _Py_Module(asdl_seq * body, string docstring, PyArena *arena);
#define Module(a0, a1) _Py_Module(a0, a1)
mod_ty _Py_Module(asdl_seq * body, PyArena *arena);
#define Interactive(a0, a1) _Py_Interactive(a0, a1)
mod_ty _Py_Interactive(asdl_seq * body, PyArena *arena);
#define Expression(a0, a1) _Py_Expression(a0, a1)
mod_ty _Py_Expression(expr_ty body, PyArena *arena);
#define Suite(a0, a1) _Py_Suite(a0, a1)
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,
asdl_seq * decorator_list, expr_ty returns, string
docstring, int lineno, 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)
asdl_seq * decorator_list, expr_ty returns, int lineno,
int col_offset, PyArena *arena);
#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 *
body, asdl_seq * decorator_list, expr_ty returns,
string docstring, int lineno, int col_offset,
PyArena *arena);
#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8)
int lineno, int col_offset, PyArena *arena);
#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7)
stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords,
asdl_seq * body, asdl_seq * decorator_list, string
docstring, int lineno, int col_offset, PyArena *arena);
asdl_seq * body, asdl_seq * decorator_list, int lineno,
int col_offset, PyArena *arena);
#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);
#define Delete(a0, a1, a2, a3) _Py_Delete(a0, a1, a2, a3)
......
......@@ -206,7 +206,15 @@ def get_docstring(node, clean=True):
"""
if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)):
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:
import inspect
text = inspect.cleandoc(text)
......
......@@ -327,24 +327,9 @@ class AST_Tests(unittest.TestCase):
def test_module(self):
body = [ast.Num(42)]
x = ast.Module(body, None)
x = ast.Module(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):
# Zero arguments constructor explicitly allowed
x = ast.BinOp()
......@@ -411,13 +396,13 @@ class AST_Tests(unittest.TestCase):
def test_invalid_sum(self):
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:
compile(m, "<test>", "exec")
self.assertIn("but got <_ast.expr", str(cm.exception))
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)
with self.assertRaises(TypeError) as cm:
compile(m, "<test>", "exec")
......@@ -462,18 +447,18 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(ast.dump(node),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), "
"args=[Name(id='eggs', ctx=Load()), Str(s='and cheese')], "
"keywords=[]))], docstring=None)"
"keywords=[]))])"
)
self.assertEqual(ast.dump(node, annotate_fields=False),
"Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), "
"Str('and cheese')], []))], None)"
"Str('and cheese')], []))])"
)
self.assertEqual(ast.dump(node, include_attributes=True),
"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=5), Str(s='and cheese', lineno=1, "
"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):
......@@ -498,7 +483,7 @@ class ASTHelpers_Test(unittest.TestCase):
"Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, "
"col_offset=0), args=[Str(s='eggs', lineno=1, col_offset=0)], "
"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):
......@@ -589,7 +574,7 @@ class ASTHelpers_Test(unittest.TestCase):
names=[ast.alias(name='sleep')],
level=None,
lineno=None, col_offset=None)]
mod = ast.Module(body, None)
mod = ast.Module(body)
with self.assertRaises(ValueError) as cm:
compile(mod, 'test', 'exec')
self.assertIn("invalid integer value: None", str(cm.exception))
......@@ -599,7 +584,7 @@ class ASTHelpers_Test(unittest.TestCase):
names=[ast.alias(name='sleep')],
level=None,
lineno=0, col_offset=0)]
mod = ast.Module(body, None)
mod = ast.Module(body)
code = compile(mod, 'test', 'exec')
ns = {}
exec(code, ns)
......@@ -617,11 +602,11 @@ class ASTValidatorTests(unittest.TestCase):
self.assertIn(msg, str(cm.exception))
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)
def stmt(self, stmt, msg=None):
mod = ast.Module([stmt], None)
mod = ast.Module([stmt])
self.mod(mod, msg)
def test_module(self):
......@@ -663,16 +648,16 @@ class ASTValidatorTests(unittest.TestCase):
def test_funcdef(self):
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")
f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())],
None, None)
None)
self.stmt(f, "must have Load context")
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")
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)
def test_classdef(self):
......@@ -686,7 +671,7 @@ class ASTValidatorTests(unittest.TestCase):
if decorator_list is None:
decorator_list = []
return ast.ClassDef("myclass", bases, keywords,
body, decorator_list, None)
body, decorator_list)
self.stmt(cls(bases=[ast.Name("x", ast.Store())]),
"must have Load context")
self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]),
......@@ -1124,53 +1109,53 @@ def main():
#### EVERYTHING BELOW IS GENERATED #####
exec_results = [
('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))], None),
('Module', [], 'module docstring'),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None, None)], None),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [], [], None, '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, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None, None)], 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', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None, None)], 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', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [], None)], None),
('Module', [('ClassDef', (1, 0), 'C', [], [], [], [], 'docstring for class C')], None),
('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [], None)], None),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None, None)], None),
('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])], None),
('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))], None),
('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))], None),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])], None),
('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])], None),
('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])], None),
('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',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])], None),
('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)], 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))], [], [], [('Pass', (4, 2))])], None),
('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)], None),
('Module', [('Import', (1, 0), [('alias', 'sys', None)])], None),
('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)], None),
('Module', [('Global', (1, 0), ['v'])], None),
('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))], None),
('Module', [('Pass', (1, 0))], None),
('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',)), [('Continue', (1, 11))], [])], 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))], [])], 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)]))], 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)]))], 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)]))], 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)]))], 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)]))], 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)]))], 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)]))], 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)]))], None),
('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, []), [('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, []), [('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', [('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), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Num', (1, 3), 1), ('Num', (1, 6), 2)]), ('Load',)), ('Num', (1, 10), 3)]))], 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, None)], None),
('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))]),
('Module', [('Expr', (1, 0), ('Str', (1, 0), 'module docstring'))]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], 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)]),
('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)]),
('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), [], [])]), [('Expr', (1, 58), ('Str', (1, 58), 'doc for f()'))], [], None)]),
('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])]),
('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))], [])]),
('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',))])]),
('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))]),
('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))], [])]),
('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))])]),
('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)]),
('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))])]),
('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]),
('Module', [('Import', (1, 0), [('alias', 'sys', None)])]),
('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)]),
('Module', [('Global', (1, 0), ['v'])]),
('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))]),
('Module', [('Pass', (1, 0))]),
('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))], [])]),
('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)]))]),
('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)]))]),
('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)]))]),
('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)]))]),
('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', (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)]),
('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)]))]),
('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)]),
]
single_results = [
('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]),
......
......@@ -27,7 +27,7 @@ class OpcodeTest(unittest.TestCase):
with open(ann_module.__file__) as f:
txt = f.read()
co = compile(txt, ann_module.__file__, 'exec')
self.assertEqual(co.co_firstlineno, 8)
self.assertEqual(co.co_firstlineno, 6)
except OSError:
pass
......
......@@ -788,7 +788,7 @@ objects.
Add ``docstring`` field to Module, ClassDef, FunctionDef, and
AsyncFunctionDef ast nodes. docstring is not first stmt in their body
anymore. It affects ``co_firstlineno`` and ``co_lnotab`` of code object for
module and class.
module and class. (Reverted in :issue:`32911`.)
..
......
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.
......@@ -6,7 +6,7 @@
module Python
{
mod = Module(stmt* body, string? docstring)
mod = Module(stmt* body)
| Interactive(stmt* body)
| Expression(expr body)
......@@ -14,18 +14,15 @@ module Python
| Suite(stmt* body)
stmt = FunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? docstring)
stmt* body, expr* decorator_list, expr? returns)
| AsyncFunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? docstring)
stmt* body, expr* decorator_list, expr? returns)
| ClassDef(identifier name,
expr* bases,
keyword* keywords,
stmt* body,
expr* decorator_list,
string? docstring)
expr* decorator_list)
| Return(expr? value)
| Delete(expr* targets)
......
......@@ -10,10 +10,8 @@ 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[]={
......@@ -46,7 +44,6 @@ static char *FunctionDef_fields[]={
"body",
"decorator_list",
"returns",
"docstring",
};
static PyTypeObject *AsyncFunctionDef_type;
static char *AsyncFunctionDef_fields[]={
......@@ -55,7 +52,6 @@ static char *AsyncFunctionDef_fields[]={
"body",
"decorator_list",
"returns",
"docstring",
};
static PyTypeObject *ClassDef_type;
_Py_IDENTIFIER(bases);
......@@ -66,7 +62,6 @@ static char *ClassDef_fields[]={
"keywords",
"body",
"decorator_list",
"docstring",
};
static PyTypeObject *Return_type;
_Py_IDENTIFIER(value);
......@@ -847,7 +842,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, 2);
Module_type = make_type("Module", mod_type, Module_fields, 1);
if (!Module_type) return 0;
Interactive_type = make_type("Interactive", mod_type, Interactive_fields,
1);
......@@ -860,12 +855,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,
6);
5);
if (!FunctionDef_type) return 0;
AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type,
AsyncFunctionDef_fields, 6);
AsyncFunctionDef_fields, 5);
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;
Return_type = make_type("Return", stmt_type, Return_fields, 1);
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);
mod_ty
Module(asdl_seq * body, string docstring, PyArena *arena)
Module(asdl_seq * body, PyArena *arena)
{
mod_ty p;
p = (mod_ty)PyArena_Malloc(arena, sizeof(*p));
......@@ -1200,7 +1195,6 @@ Module(asdl_seq * body, string docstring, PyArena *arena)
return NULL;
p->kind = Module_kind;
p->v.Module.body = body;
p->v.Module.docstring = docstring;
return p;
}
......@@ -1247,8 +1241,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, string docstring, int lineno, int
col_offset, PyArena *arena)
decorator_list, expr_ty returns, int lineno, int col_offset,
PyArena *arena)
{
stmt_ty p;
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.decorator_list = decorator_list;
p->v.FunctionDef.returns = returns;
p->v.FunctionDef.docstring = docstring;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
......@@ -1278,8 +1271,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, string docstring, int
lineno, int col_offset, PyArena *arena)
* decorator_list, expr_ty returns, int lineno, int col_offset,
PyArena *arena)
{
stmt_ty p;
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.decorator_list = decorator_list;
p->v.AsyncFunctionDef.returns = returns;
p->v.AsyncFunctionDef.docstring = docstring;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
......@@ -1309,8 +1301,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, string docstring, int lineno, int
col_offset, PyArena *arena)
body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena
*arena)
{
stmt_ty p;
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.body = body;
p->v.ClassDef.decorator_list = decorator_list;
p->v.ClassDef.docstring = docstring;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
......@@ -2591,11 +2582,6 @@ 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);
......@@ -2670,11 +2656,6 @@ 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,11 +2686,6 @@ 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);
......@@ -2739,11 +2715,6 @@ 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);
......@@ -3984,7 +3955,6 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena)
}
if (isinstance) {
asdl_seq* body;
string docstring;
if (_PyObject_LookupAttrId(obj, &PyId_body, &tmp) < 0) {
return 1;
......@@ -4016,20 +3986,7 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena)
}
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 = Module(body, docstring, arena);
*out = Module(body, arena);
if (*out == NULL) goto failed;
return 0;
}
......@@ -4195,7 +4152,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
asdl_seq* body;
asdl_seq* decorator_list;
expr_ty returns;
string docstring;
if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) {
return 1;
......@@ -4296,21 +4252,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
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 = FunctionDef(name, args, body, decorator_list, returns,
docstring, lineno, col_offset, arena);
*out = FunctionDef(name, args, body, decorator_list, returns, lineno,
col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
......@@ -4324,7 +4267,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
asdl_seq* body;
asdl_seq* decorator_list;
expr_ty returns;
string docstring;
if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) {
return 1;
......@@ -4425,21 +4367,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
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,
docstring, lineno, col_offset, arena);
lineno, col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
......@@ -4453,7 +4382,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
asdl_seq* keywords;
asdl_seq* body;
asdl_seq* decorator_list;
string docstring;
if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) {
return 1;
......@@ -4588,21 +4516,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
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 = ClassDef(name, bases, keywords, body, decorator_list, docstring,
lineno, col_offset, arena);
*out = ClassDef(name, bases, keywords, body, decorator_list, lineno,
col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
......
......@@ -367,12 +367,9 @@ validate_assignlist(asdl_seq *targets, expr_context_ty ctx)
}
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 0;
}
return validate_stmts(body);
return validate_nonempty_seq(body, "body", owner) && validate_stmts(body);
}
static int
......@@ -381,15 +378,13 @@ validate_stmt(stmt_ty stmt)
int i;
switch (stmt->kind) {
case FunctionDef_kind:
return validate_body(stmt->v.FunctionDef.body, "FunctionDef",
stmt->v.FunctionDef.docstring != NULL) &&
return validate_body(stmt->v.FunctionDef.body, "FunctionDef") &&
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",
stmt->v.ClassDef.docstring != NULL) &&
return validate_body(stmt->v.ClassDef.body, "ClassDef") &&
validate_exprs(stmt->v.ClassDef.bases, Load, 0) &&
validate_keywords(stmt->v.ClassDef.keywords) &&
validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0);
......@@ -417,20 +412,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", 0) &&
validate_body(stmt->v.For.body, "For") &&
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", 0) &&
validate_body(stmt->v.AsyncFor.body, "AsyncFor") &&
validate_stmts(stmt->v.AsyncFor.orelse);
case While_kind:
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);
case If_kind:
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);
case With_kind:
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)))
return 0;
}
return validate_body(stmt->v.With.body, "With", 0);
return validate_body(stmt->v.With.body, "With");
case AsyncWith_kind:
if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith"))
return 0;
......@@ -451,7 +446,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", 0);
return validate_body(stmt->v.AsyncWith.body, "AsyncWith");
case Raise_kind:
if (stmt->v.Raise.exc) {
return validate_expr(stmt->v.Raise.exc, Load) &&
......@@ -463,7 +458,7 @@ validate_stmt(stmt_ty stmt)
}
return 1;
case Try_kind:
if (!validate_body(stmt->v.Try.body, "Try", 0))
if (!validate_body(stmt->v.Try.body, "Try"))
return 0;
if (!asdl_seq_LEN(stmt->v.Try.handlers) &&
!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);
if ((handler->v.ExceptHandler.type &&
!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 (!asdl_seq_LEN(stmt->v.Try.finalbody) ||
......@@ -504,8 +499,7 @@ 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",
stmt->v.AsyncFunctionDef.docstring != NULL) &&
return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") &&
validate_arguments(stmt->v.AsyncFunctionDef.args) &&
validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
(!stmt->v.AsyncFunctionDef.returns ||
......@@ -600,9 +594,7 @@ 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_body(struct compiling *c, const node *n,
string *docstring);
static string docstring_from_stmts(asdl_seq *stmts);
static asdl_seq *ast_for_suite(struct compiling *c, const node *n);
static asdl_seq *ast_for_exprlist(struct compiling *, const node *,
expr_context_ty);
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;
case eval_input: {
expr_ty testlist_ast;
......@@ -1585,7 +1577,6 @@ 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);
......@@ -1604,18 +1595,16 @@ ast_for_funcdef_impl(struct compiling *c, const node *n,
return NULL;
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)
return NULL;
if (is_async)
return AsyncFunctionDef(name, args, body, decorator_seq, returns,
docstring, LINENO(n),
n->n_col_offset, c->c_arena);
LINENO(n), n->n_col_offset, c->c_arena);
else
return FunctionDef(name, args, body, decorator_seq, returns,
docstring, LINENO(n),
n->n_col_offset, c->c_arena);
LINENO(n), n->n_col_offset, c->c_arena);
}
static stmt_ty
......@@ -3528,32 +3517,6 @@ 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)
{
......@@ -3938,13 +3901,12 @@ 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_body(c, CHILD(n, 3), &docstring);
s = ast_for_suite(c, CHILD(n, 3));
if (!s)
return NULL;
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;
if (forbidden_name(c, classname, CHILD(n, 3), 0))
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);
}
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)
return NULL;
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;
if (forbidden_name(c, classname, CHILD(n, 3), 0))
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);
}
......@@ -3982,7 +3944,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
if (!call)
return NULL;
}
s = ast_for_body(c, CHILD(n, 6), &docstring);
s = ast_for_suite(c, CHILD(n, 6));
if (!s)
return NULL;
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 ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s,
decorator_seq, docstring, LINENO(n), n->n_col_offset,
c->c_arena);
decorator_seq, LINENO(n), n->n_col_offset, c->c_arena);
}
static stmt_ty
......
......@@ -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
astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_)
{
switch (node_->kind) {
case Module_kind:
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Module.body);
CALL(astfold_body, asdl_seq, node_->v.Module.body);
break;
case Interactive_kind:
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) {
case FunctionDef_kind:
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_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
break;
case AsyncFunctionDef_kind:
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_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
break;
case ClassDef_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
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);
break;
case Return_kind:
......
......@@ -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
is_const(expr_ty e)
{
......@@ -1587,27 +1599,37 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
and for annotations. */
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.
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)) {
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
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 not -OO mode, set docstring */
if (c->c_optimize < 2 && docstring) {
ADDOP_LOAD_CONST(c, docstring);
ADDOP_NAME(c, STORE_NAME, __doc__, names);
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;
}
VISIT_SEQ(c, stmt, stmts);
for (; i < asdl_seq_LEN(stmts); i++)
VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i));
return 1;
}
......@@ -1627,7 +1649,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, mod->v.Module.docstring)) {
if (!compiler_body(c, mod->v.Module.body)) {
compiler_exit_scope(c);
return 0;
}
......@@ -1957,13 +1979,15 @@ static int
compiler_function(struct compiler *c, stmt_ty s, int is_async)
{
PyCodeObject *co;
PyObject *qualname, *docstring = Py_None;
PyObject *qualname, *first_const = Py_None;
arguments_ty args;
expr_ty returns;
identifier name;
asdl_seq* decos;
asdl_seq *body;
stmt_ty st;
Py_ssize_t i, funcflags;
int docstring;
int annotations;
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 (c->c_optimize < 2 && s->v.FunctionDef.docstring)
docstring = s->v.FunctionDef.docstring;
if (compiler_add_const(c, docstring) < 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_const(c, first_const) < 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);
/* if there was a docstring, we need to skip the first statement */
VISIT_SEQ_IN_SCOPE(c, stmt, body);
co = assemble(c, 1);
qualname = c->u->u_qualname;
......@@ -2101,7 +2130,7 @@ compiler_class(struct compiler *c, stmt_ty s)
}
Py_DECREF(str);
/* 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);
return 0;
}
......
......@@ -63,6 +63,7 @@ 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;
......@@ -78,7 +79,15 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
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);
if (done && s->lineno > prev_line)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -71,8 +71,6 @@ class Unparser:
########################################################
def _Module(self, tree):
if tree.docstring is not None:
self.fill(repr(tree.docstring))
for stmt in tree.body:
self.dispatch(stmt)
......@@ -237,8 +235,6 @@ class Unparser:
self.write(")")
self.enter()
if t.docstring is not None:
self.fill(repr(t.docstring))
self.dispatch(t.body)
self.leave()
......@@ -261,8 +257,6 @@ class Unparser:
self.write(" -> ")
self.dispatch(t.returns)
self.enter()
if t.docstring is not None:
self.fill(repr(t.docstring))
self.dispatch(t.body)
self.leave()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment