Skip to content

Commit 08f127a

Browse files
bpo-33851: Fix ast.get_docstring() for a node that lacks a docstring. (GH-7682)
1 parent 9e7c921 commit 08f127a

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

Lib/ast.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def get_docstring(node, clean=True):
206206
"""
207207
if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)):
208208
raise TypeError("%r can't have docstrings" % node.__class__.__name__)
209-
if not node.body:
209+
if not(node.body and isinstance(node.body[0], Expr)):
210210
return None
211211
node = node.body[0].value
212212
if isinstance(node, Str):
@@ -215,7 +215,7 @@ def get_docstring(node, clean=True):
215215
text = node.value
216216
else:
217217
return None
218-
if clean and text:
218+
if clean:
219219
import inspect
220220
text = inspect.cleandoc(text)
221221
return text

Lib/test/test_ast.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,13 +521,44 @@ def test_iter_child_nodes(self):
521521
)
522522

523523
def test_get_docstring(self):
524+
node = ast.parse('"""line one\n line two"""')
525+
self.assertEqual(ast.get_docstring(node),
526+
'line one\nline two')
527+
528+
node = ast.parse('class foo:\n """line one\n line two"""')
529+
self.assertEqual(ast.get_docstring(node.body[0]),
530+
'line one\nline two')
531+
524532
node = ast.parse('def foo():\n """line one\n line two"""')
525533
self.assertEqual(ast.get_docstring(node.body[0]),
526534
'line one\nline two')
527535

528536
node = ast.parse('async def foo():\n """spam\n ham"""')
529537
self.assertEqual(ast.get_docstring(node.body[0]), 'spam\nham')
538+
539+
def test_get_docstring_none(self):
530540
self.assertIsNone(ast.get_docstring(ast.parse('')))
541+
node = ast.parse('x = "not docstring"')
542+
self.assertIsNone(ast.get_docstring(node))
543+
node = ast.parse('def foo():\n pass')
544+
self.assertIsNone(ast.get_docstring(node))
545+
546+
node = ast.parse('class foo:\n pass')
547+
self.assertIsNone(ast.get_docstring(node.body[0]))
548+
node = ast.parse('class foo:\n x = "not docstring"')
549+
self.assertIsNone(ast.get_docstring(node.body[0]))
550+
node = ast.parse('class foo:\n def bar(self): pass')
551+
self.assertIsNone(ast.get_docstring(node.body[0]))
552+
553+
node = ast.parse('def foo():\n pass')
554+
self.assertIsNone(ast.get_docstring(node.body[0]))
555+
node = ast.parse('def foo():\n x = "not docstring"')
556+
self.assertIsNone(ast.get_docstring(node.body[0]))
557+
558+
node = ast.parse('async def foo():\n pass')
559+
self.assertIsNone(ast.get_docstring(node.body[0]))
560+
node = ast.parse('async def foo():\n x = "not docstring"')
561+
self.assertIsNone(ast.get_docstring(node.body[0]))
531562

532563
def test_literal_eval(self):
533564
self.assertEqual(ast.literal_eval('[1, 2, 3]'), [1, 2, 3])
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix :func:`ast.get_docstring` for a node that lacks a docstring.

0 commit comments

Comments
 (0)